Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef SkScalerContext_DEFINED
     18 #define SkScalerContext_DEFINED
     19 
     20 #include "SkMask.h"
     21 #include "SkMatrix.h"
     22 #include "SkPaint.h"
     23 #include "SkPath.h"
     24 #include "SkPoint.h"
     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 			rb <<= 2;
     65 		} else if (SkMask::kLCD16_Format == format) {
     66 			rb = SkAlign4(rb << 1);
     67         } else {
     68             rb = SkAlign4(rb);
     69         }
     70         return rb;
     71     }
     72 
     73     unsigned rowBytes() const {
     74         return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat);
     75     }
     76 
     77     bool isJustAdvance() const {
     78         return MASK_FORMAT_JUST_ADVANCE == fMaskFormat;
     79     }
     80 
     81     bool isFullMetrics() const {
     82         return MASK_FORMAT_JUST_ADVANCE != fMaskFormat;
     83     }
     84 
     85     uint16_t getGlyphID() const {
     86         return ID2Code(fID);
     87     }
     88 
     89     unsigned getGlyphID(unsigned baseGlyphCount) const {
     90         unsigned code = ID2Code(fID);
     91         SkASSERT(code >= baseGlyphCount);
     92         return code - baseGlyphCount;
     93     }
     94 
     95     unsigned getSubX() const {
     96         return ID2SubX(fID);
     97     }
     98 
     99     SkFixed getSubXFixed() const {
    100         return SubToFixed(ID2SubX(fID));
    101     }
    102 
    103     SkFixed getSubYFixed() const {
    104         return SubToFixed(ID2SubY(fID));
    105     }
    106 
    107     size_t computeImageSize() const;
    108 
    109     /** Call this to set all of the metrics fields to 0 (e.g. if the scaler
    110         encounters an error measuring a glyph). Note: this does not alter the
    111         fImage, fPath, fID, fMaskFormat fields.
    112      */
    113     void zeroMetrics();
    114 
    115     enum {
    116         kSubBits = 2,
    117         kSubMask = ((1 << kSubBits) - 1),
    118         kSubShift = 24, // must be large enough for glyphs and unichars
    119         kCodeMask = ((1 << kSubShift) - 1),
    120         // relative offsets for X and Y subpixel bits
    121         kSubShiftX = kSubBits,
    122         kSubShiftY = 0
    123     };
    124 
    125     static unsigned ID2Code(uint32_t id) {
    126         return id & kCodeMask;
    127     }
    128 
    129     static unsigned ID2SubX(uint32_t id) {
    130         return id >> (kSubShift + kSubShiftX);
    131     }
    132 
    133     static unsigned ID2SubY(uint32_t id) {
    134         return (id >> (kSubShift + kSubShiftY)) & kSubMask;
    135     }
    136 
    137     static unsigned FixedToSub(SkFixed n) {
    138         return (n >> (16 - kSubBits)) & kSubMask;
    139     }
    140 
    141     static SkFixed SubToFixed(unsigned sub) {
    142         SkASSERT(sub <= kSubMask);
    143         return sub << (16 - kSubBits);
    144     }
    145 
    146     static uint32_t MakeID(unsigned code) {
    147         return code;
    148     }
    149 
    150     static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) {
    151         SkASSERT(code <= kCodeMask);
    152         x = FixedToSub(x);
    153         y = FixedToSub(y);
    154         return (x << (kSubShift + kSubShiftX)) |
    155                (y << (kSubShift + kSubShiftY)) |
    156                code;
    157     }
    158 
    159     void toMask(SkMask* mask) const;
    160 
    161     /** Given a glyph which is has a mask format of LCD or VerticalLCD, take
    162         the A8 plane in fImage and produce a valid LCD plane from it.
    163     */
    164     void expandA8ToLCD() const;
    165 };
    166 
    167 class SkScalerContext {
    168 public:
    169     enum Flags {
    170         kFrameAndFill_Flag  = 0x01,
    171         kDevKernText_Flag   = 0x02,
    172         kGammaForBlack_Flag = 0x04, // illegal to set both Gamma flags
    173         kGammaForWhite_Flag = 0x08, // illegal to set both Gamma flags
    174         // together, these two flags resulting in a two bit value which matches
    175         // up with the SkPaint::Hinting enum.
    176         kHintingBit1_Flag   = 0x10,
    177         kHintingBit2_Flag   = 0x20,
    178         kEmbeddedBitmapText_Flag = 0x40,
    179         kEmbolden_Flag      = 0x80,
    180         kSubpixelPositioning_Flag = 0x100,
    181         kAutohinting_Flag   = 0x200,
    182         // these should only ever be set if fMaskFormat is LCD
    183         kLCD_Vertical_Flag  = 0x400,    // else Horizontal
    184         kLCD_BGROrder_Flag  = 0x800,    // else RGB order
    185     };
    186 private:
    187     enum {
    188         kHintingMask = kHintingBit1_Flag | kHintingBit2_Flag
    189     };
    190 public:
    191     struct Rec {
    192         uint32_t    fOrigFontID;
    193         uint32_t    fFontID;
    194         SkScalar    fTextSize, fPreScaleX, fPreSkewX;
    195         SkScalar    fPost2x2[2][2];
    196         SkScalar    fFrameWidth, fMiterLimit;
    197         uint8_t     fMaskFormat;
    198         uint8_t     fStrokeJoin;
    199         uint16_t    fFlags;
    200         // Warning: when adding members note that the size of this structure
    201         // must be a multiple of 4. SkDescriptor requires that its arguments be
    202         // multiples of four and this structure is put in an SkDescriptor in
    203         // SkPaint::MakeRec.
    204 
    205         void    getMatrixFrom2x2(SkMatrix*) const;
    206         void    getLocalMatrix(SkMatrix*) const;
    207         void    getSingleMatrix(SkMatrix*) const;
    208 
    209         SkPaint::Hinting getHinting() const {
    210             return static_cast<SkPaint::Hinting>((fFlags & kHintingMask) >> 4);
    211         }
    212 
    213         void setHinting(SkPaint::Hinting hinting) {
    214             fFlags = (fFlags & ~kHintingMask) | (hinting << 4);
    215         }
    216 
    217         SkMask::Format getFormat() const {
    218             return static_cast<SkMask::Format>(fMaskFormat);
    219         }
    220 
    221         bool isLCD() const {
    222             return SkMask::FormatIsLCD(this->getFormat());
    223         }
    224     };
    225 
    226     SkScalerContext(const SkDescriptor* desc);
    227     virtual ~SkScalerContext();
    228 
    229     SkMask::Format getMaskFormat() const {
    230         return (SkMask::Format)fRec.fMaskFormat;
    231     }
    232 
    233     // remember our glyph offset/base
    234     void setBaseGlyphCount(unsigned baseGlyphCount) {
    235         fBaseGlyphCount = baseGlyphCount;
    236     }
    237 
    238     /** Return the corresponding glyph for the specified unichar. Since contexts
    239         may be chained (under the hood), the glyphID that is returned may in
    240         fact correspond to a different font/context. In that case, we use the
    241         base-glyph-count to know how to translate back into local glyph space.
    242      */
    243     uint16_t    charToGlyphID(SkUnichar uni);
    244 
    245     /** Map the glyphID to its glyph index, and then to its char code. Unmapped
    246         glyphs return zero.
    247     */
    248     SkUnichar glyphIDToChar(uint16_t glyphID);
    249 
    250     unsigned    getGlyphCount() { return this->generateGlyphCount(); }
    251     void        getAdvance(SkGlyph*);
    252     void        getMetrics(SkGlyph*);
    253     void        getImage(const SkGlyph&);
    254     void        getPath(const SkGlyph&, SkPath*);
    255     void        getFontMetrics(SkPaint::FontMetrics* mX,
    256                                SkPaint::FontMetrics* mY);
    257 
    258     static inline void MakeRec(const SkPaint&, const SkMatrix*, Rec* rec);
    259     static SkScalerContext* Create(const SkDescriptor*);
    260 
    261 protected:
    262     Rec         fRec;
    263     unsigned    fBaseGlyphCount;
    264 
    265     virtual unsigned generateGlyphCount() = 0;
    266     virtual uint16_t generateCharToGlyph(SkUnichar) = 0;
    267     virtual void generateAdvance(SkGlyph*) = 0;
    268     virtual void generateMetrics(SkGlyph*) = 0;
    269     virtual void generateImage(const SkGlyph&) = 0;
    270     virtual void generatePath(const SkGlyph&, SkPath*) = 0;
    271     virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
    272                                      SkPaint::FontMetrics* mY) = 0;
    273     // default impl returns 0, indicating failure.
    274     virtual SkUnichar generateGlyphToChar(uint16_t);
    275 
    276 private:
    277     SkPathEffect*   fPathEffect;
    278     SkMaskFilter*   fMaskFilter;
    279     SkRasterizer*   fRasterizer;
    280     SkScalar        fDevFrameWidth;
    281 
    282     void internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
    283                          SkPath* devPath, SkMatrix* fillToDevMatrix);
    284 
    285     // return the next context, treating fNextContext as a cache of the answer
    286     SkScalerContext* getNextContext();
    287 
    288     // returns the right context from our link-list for this glyph. If no match
    289     // is found, just returns the original context (this)
    290     SkScalerContext* getGlyphContext(const SkGlyph& glyph);
    291 
    292     // link-list of context, to handle missing chars. null-terminated.
    293     SkScalerContext* fNextContext;
    294 };
    295 
    296 #define kRec_SkDescriptorTag            SkSetFourByteTag('s', 'r', 'e', 'c')
    297 #define kPathEffect_SkDescriptorTag     SkSetFourByteTag('p', 't', 'h', 'e')
    298 #define kMaskFilter_SkDescriptorTag     SkSetFourByteTag('m', 's', 'k', 'f')
    299 #define kRasterizer_SkDescriptorTag     SkSetFourByteTag('r', 'a', 's', 't')
    300 
    301 #endif
    302 
    303