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