Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #ifndef SkScalerContext_DEFINED
     11 #define SkScalerContext_DEFINED
     12 
     13 #include "SkMask.h"
     14 #include "SkMatrix.h"
     15 #include "SkPaint.h"
     16 #include "SkPath.h"
     17 #include "SkPoint.h"
     18 
     19 //#define SK_USE_COLOR_LUMINANCE
     20 
     21 class SkDescriptor;
     22 class SkMaskFilter;
     23 class SkPathEffect;
     24 class SkRasterizer;
     25 
     26 // needs to be != to any valid SkMask::Format
     27 #define MASK_FORMAT_UNKNOWN         (0xFF)
     28 #define MASK_FORMAT_JUST_ADVANCE    MASK_FORMAT_UNKNOWN
     29 
     30 #define kMaxGlyphWidth (1<<13)
     31 
     32 struct SkGlyph {
     33     void*       fImage;
     34     SkPath*     fPath;
     35     SkFixed     fAdvanceX, fAdvanceY;
     36 
     37     uint32_t    fID;
     38     uint16_t    fWidth, fHeight;
     39     int16_t     fTop, fLeft;
     40 
     41     uint8_t     fMaskFormat;
     42     int8_t      fRsbDelta, fLsbDelta;  // used by auto-kerning
     43 
     44     void init(uint32_t id) {
     45         fID             = id;
     46         fImage          = NULL;
     47         fPath           = NULL;
     48         fMaskFormat     = MASK_FORMAT_UNKNOWN;
     49     }
     50 
     51     /**
     52      *  Compute the rowbytes for the specified width and mask-format.
     53      */
     54     static unsigned ComputeRowBytes(unsigned width, SkMask::Format format) {
     55         unsigned rb = width;
     56         if (SkMask::kBW_Format == format) {
     57             rb = (rb + 7) >> 3;
     58 		} else if (SkMask::kARGB32_Format == format ||
     59                    SkMask::kLCD32_Format == format)
     60         {
     61 			rb <<= 2;
     62 		} else if (SkMask::kLCD16_Format == format) {
     63 			rb = SkAlign4(rb << 1);
     64         } else {
     65             rb = SkAlign4(rb);
     66         }
     67         return rb;
     68     }
     69 
     70     unsigned rowBytes() const {
     71         return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat);
     72     }
     73 
     74     bool isJustAdvance() const {
     75         return MASK_FORMAT_JUST_ADVANCE == fMaskFormat;
     76     }
     77 
     78     bool isFullMetrics() const {
     79         return MASK_FORMAT_JUST_ADVANCE != fMaskFormat;
     80     }
     81 
     82     uint16_t getGlyphID() const {
     83         return ID2Code(fID);
     84     }
     85 
     86     unsigned getGlyphID(unsigned baseGlyphCount) const {
     87         unsigned code = ID2Code(fID);
     88         SkASSERT(code >= baseGlyphCount);
     89         return code - baseGlyphCount;
     90     }
     91 
     92     unsigned getSubX() const {
     93         return ID2SubX(fID);
     94     }
     95 
     96     SkFixed getSubXFixed() const {
     97         return SubToFixed(ID2SubX(fID));
     98     }
     99 
    100     SkFixed getSubYFixed() const {
    101         return SubToFixed(ID2SubY(fID));
    102     }
    103 
    104     size_t computeImageSize() const;
    105 
    106     /** Call this to set all of the metrics fields to 0 (e.g. if the scaler
    107         encounters an error measuring a glyph). Note: this does not alter the
    108         fImage, fPath, fID, fMaskFormat fields.
    109      */
    110     void zeroMetrics();
    111 
    112     enum {
    113         kSubBits = 2,
    114         kSubMask = ((1 << kSubBits) - 1),
    115         kSubShift = 24, // must be large enough for glyphs and unichars
    116         kCodeMask = ((1 << kSubShift) - 1),
    117         // relative offsets for X and Y subpixel bits
    118         kSubShiftX = kSubBits,
    119         kSubShiftY = 0
    120     };
    121 
    122     static unsigned ID2Code(uint32_t id) {
    123         return id & kCodeMask;
    124     }
    125 
    126     static unsigned ID2SubX(uint32_t id) {
    127         return id >> (kSubShift + kSubShiftX);
    128     }
    129 
    130     static unsigned ID2SubY(uint32_t id) {
    131         return (id >> (kSubShift + kSubShiftY)) & kSubMask;
    132     }
    133 
    134     static unsigned FixedToSub(SkFixed n) {
    135         return (n >> (16 - kSubBits)) & kSubMask;
    136     }
    137 
    138     static SkFixed SubToFixed(unsigned sub) {
    139         SkASSERT(sub <= kSubMask);
    140         return sub << (16 - kSubBits);
    141     }
    142 
    143     static uint32_t MakeID(unsigned code) {
    144         return code;
    145     }
    146 
    147     static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) {
    148         SkASSERT(code <= kCodeMask);
    149         x = FixedToSub(x);
    150         y = FixedToSub(y);
    151         return (x << (kSubShift + kSubShiftX)) |
    152                (y << (kSubShift + kSubShiftY)) |
    153                code;
    154     }
    155 
    156     void toMask(SkMask* mask) const;
    157 };
    158 
    159 class SkScalerContext {
    160 public:
    161     enum Flags {
    162         kFrameAndFill_Flag        = 0x0001,
    163         kDevKernText_Flag         = 0x0002,
    164         kEmbeddedBitmapText_Flag  = 0x0004,
    165         kEmbolden_Flag            = 0x0008,
    166         kSubpixelPositioning_Flag = 0x0010,
    167         kAutohinting_Flag         = 0x0020,
    168         kVertical_Flag            = 0x0040,
    169 
    170         // together, these two flags resulting in a two bit value which matches
    171         // up with the SkPaint::Hinting enum.
    172         kHinting_Shift            = 7, // to shift into the other flags above
    173         kHintingBit1_Flag         = 0x0080,
    174         kHintingBit2_Flag         = 0x0100,
    175 
    176         // these should only ever be set if fMaskFormat is LCD16 or LCD32
    177         kLCD_Vertical_Flag        = 0x0200,    // else Horizontal
    178         kLCD_BGROrder_Flag        = 0x0400,    // else RGB order
    179 
    180         // Generate A8 from LCD source (for GDI), only meaningful if fMaskFormat is kA8
    181         // Perhaps we can store this (instead) in fMaskFormat, in hight bit?
    182         kGenA8FromLCD_Flag        = 0x0800,
    183 
    184 #ifdef SK_USE_COLOR_LUMINANCE
    185         kLuminance_Bits           = 3,
    186 #else
    187         // luminance : 0 for black text, kLuminance_Max for white text
    188         kLuminance_Shift          = 13, // shift to land in the high 3-bits of Flags
    189         kLuminance_Bits           = 3,  // ensure Flags doesn't exceed 16bits
    190 #endif
    191     };
    192 
    193     // computed values
    194     enum {
    195         kHinting_Mask   = kHintingBit1_Flag | kHintingBit2_Flag,
    196 #ifdef SK_USE_COLOR_LUMINANCE
    197 #else
    198         kLuminance_Max  = (1 << kLuminance_Bits) - 1,
    199         kLuminance_Mask = kLuminance_Max << kLuminance_Shift,
    200 #endif
    201     };
    202 
    203     struct Rec {
    204         uint32_t    fOrigFontID;
    205         uint32_t    fFontID;
    206         SkScalar    fTextSize, fPreScaleX, fPreSkewX;
    207         SkScalar    fPost2x2[2][2];
    208         SkScalar    fFrameWidth, fMiterLimit;
    209 #ifdef SK_USE_COLOR_LUMINANCE
    210         uint32_t    fLumBits;
    211 #endif
    212         uint8_t     fMaskFormat;
    213         uint8_t     fStrokeJoin;
    214         uint16_t    fFlags;
    215         // Warning: when adding members note that the size of this structure
    216         // must be a multiple of 4. SkDescriptor requires that its arguments be
    217         // multiples of four and this structure is put in an SkDescriptor in
    218         // SkPaint::MakeRec.
    219 
    220         void    getMatrixFrom2x2(SkMatrix*) const;
    221         void    getLocalMatrix(SkMatrix*) const;
    222         void    getSingleMatrix(SkMatrix*) const;
    223 
    224         SkPaint::Hinting getHinting() const {
    225             unsigned hint = (fFlags & kHinting_Mask) >> kHinting_Shift;
    226             return static_cast<SkPaint::Hinting>(hint);
    227         }
    228 
    229         void setHinting(SkPaint::Hinting hinting) {
    230             fFlags = (fFlags & ~kHinting_Mask) | (hinting << kHinting_Shift);
    231         }
    232 
    233         SkMask::Format getFormat() const {
    234             return static_cast<SkMask::Format>(fMaskFormat);
    235         }
    236 
    237 #ifdef SK_USE_COLOR_LUMINANCE
    238         SkColor getLuminanceColor() const {
    239             return fLumBits;
    240         }
    241 
    242         void setLuminanceColor(SkColor c) {
    243             fLumBits = c;
    244         }
    245 #else
    246         unsigned getLuminanceBits() const {
    247             return (fFlags & kLuminance_Mask) >> kLuminance_Shift;
    248         }
    249 
    250         void setLuminanceBits(unsigned lum) {
    251             SkASSERT(lum <= kLuminance_Max);
    252             fFlags = (fFlags & ~kLuminance_Mask) | (lum << kLuminance_Shift);
    253         }
    254 
    255         U8CPU getLuminanceByte() const {
    256             SkASSERT(3 == kLuminance_Bits);
    257             unsigned lum = this->getLuminanceBits();
    258             lum |= (lum << kLuminance_Bits);
    259             lum |= (lum << kLuminance_Bits*2);
    260             return lum >> (4*kLuminance_Bits - 8);
    261         }
    262 #endif
    263     };
    264 
    265     SkScalerContext(const SkDescriptor* desc);
    266     virtual ~SkScalerContext();
    267 
    268     SkMask::Format getMaskFormat() const {
    269         return (SkMask::Format)fRec.fMaskFormat;
    270     }
    271 
    272     bool isSubpixel() const {
    273         return SkToBool(fRec.fFlags & kSubpixelPositioning_Flag);
    274     }
    275 
    276     // remember our glyph offset/base
    277     void setBaseGlyphCount(unsigned baseGlyphCount) {
    278         fBaseGlyphCount = baseGlyphCount;
    279     }
    280 
    281     /** Return the corresponding glyph for the specified unichar. Since contexts
    282         may be chained (under the hood), the glyphID that is returned may in
    283         fact correspond to a different font/context. In that case, we use the
    284         base-glyph-count to know how to translate back into local glyph space.
    285      */
    286     uint16_t charToGlyphID(SkUnichar uni);
    287 
    288     /** Map the glyphID to its glyph index, and then to its char code. Unmapped
    289         glyphs return zero.
    290     */
    291     SkUnichar glyphIDToChar(uint16_t glyphID);
    292 
    293     unsigned    getGlyphCount() { return this->generateGlyphCount(); }
    294     void        getAdvance(SkGlyph*);
    295     void        getMetrics(SkGlyph*);
    296     void        getImage(const SkGlyph&);
    297     void        getPath(const SkGlyph&, SkPath*);
    298     void        getFontMetrics(SkPaint::FontMetrics* mX,
    299                                SkPaint::FontMetrics* mY);
    300 
    301 #ifdef SK_BUILD_FOR_ANDROID
    302     unsigned getBaseGlyphCount(SkUnichar charCode);
    303 #endif
    304 
    305     static inline void MakeRec(const SkPaint&, const SkMatrix*, Rec* rec);
    306     static inline void PostMakeRec(Rec*);
    307 
    308     static SkScalerContext* Create(const SkDescriptor*);
    309 
    310 protected:
    311     Rec         fRec;
    312     unsigned    fBaseGlyphCount;
    313 
    314     virtual unsigned generateGlyphCount() = 0;
    315     virtual uint16_t generateCharToGlyph(SkUnichar) = 0;
    316     virtual void generateAdvance(SkGlyph*) = 0;
    317     virtual void generateMetrics(SkGlyph*) = 0;
    318     virtual void generateImage(const SkGlyph&) = 0;
    319     virtual void generatePath(const SkGlyph&, SkPath*) = 0;
    320     virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
    321                                      SkPaint::FontMetrics* mY) = 0;
    322     // default impl returns 0, indicating failure.
    323     virtual SkUnichar generateGlyphToChar(uint16_t);
    324 
    325     void forceGenerateImageFromPath() { fGenerateImageFromPath = true; }
    326 
    327 private:
    328     SkPathEffect*   fPathEffect;
    329     SkMaskFilter*   fMaskFilter;
    330     SkRasterizer*   fRasterizer;
    331     SkScalar        fDevFrameWidth;
    332 
    333     // if this is set, we draw the image from a path, rather than
    334     // calling generateImage.
    335     bool fGenerateImageFromPath;
    336 
    337     void internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
    338                          SkPath* devPath, SkMatrix* fillToDevMatrix);
    339 
    340     // return the next context, treating fNextContext as a cache of the answer
    341     SkScalerContext* getNextContext();
    342 
    343     // returns the right context from our link-list for this glyph. If no match
    344     // is found, just returns the original context (this)
    345     SkScalerContext* getGlyphContext(const SkGlyph& glyph);
    346 
    347     // link-list of context, to handle missing chars. null-terminated.
    348     SkScalerContext* fNextContext;
    349 };
    350 
    351 #define kRec_SkDescriptorTag            SkSetFourByteTag('s', 'r', 'e', 'c')
    352 #define kPathEffect_SkDescriptorTag     SkSetFourByteTag('p', 't', 'h', 'e')
    353 #define kMaskFilter_SkDescriptorTag     SkSetFourByteTag('m', 's', 'k', 'f')
    354 #define kRasterizer_SkDescriptorTag     SkSetFourByteTag('r', 'a', 's', 't')
    355 
    356 ///////////////////////////////////////////////////////////////////////////////
    357 
    358 enum SkAxisAlignment {
    359     kNone_SkAxisAlignment,
    360     kX_SkAxisAlignment,
    361     kY_SkAxisAlignment
    362 };
    363 
    364 /**
    365  *  Return the axis (if any) that the baseline for horizontal text will land on
    366  *  after running through the specified matrix.
    367  *
    368  *  As an example, the identity matrix will return kX_SkAxisAlignment
    369  */
    370 SkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix);
    371 
    372 #endif
    373 
    374