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_JUST_ADVANCE    (0xFF)
     33 
     34 struct SkGlyph {
     35     void*       fImage;
     36     SkPath*     fPath;
     37     SkFixed     fAdvanceX, fAdvanceY;
     38 
     39     uint32_t    fID;
     40     uint16_t    fWidth, fHeight;
     41     int16_t     fTop, fLeft;
     42 
     43     uint8_t     fMaskFormat;
     44     int8_t      fRsbDelta, fLsbDelta;  // used by auto-kerning
     45 
     46     unsigned rowBytes() const {
     47         unsigned rb = fWidth;
     48         if (SkMask::kBW_Format == fMaskFormat) {
     49             rb = (rb + 7) >> 3;
     50         } else {
     51             rb = SkAlign4(rb);
     52         }
     53         return rb;
     54     }
     55 
     56     bool isJustAdvance() const {
     57         return MASK_FORMAT_JUST_ADVANCE == fMaskFormat;
     58     }
     59 
     60     bool isFullMetrics() const {
     61         return MASK_FORMAT_JUST_ADVANCE != fMaskFormat;
     62     }
     63 
     64     uint16_t getGlyphID() const {
     65         return ID2Code(fID);
     66     }
     67 
     68     unsigned getGlyphID(unsigned baseGlyphCount) const {
     69         unsigned code = ID2Code(fID);
     70         SkASSERT(code >= baseGlyphCount);
     71         return code - baseGlyphCount;
     72     }
     73 
     74     unsigned getSubX() const {
     75         return ID2SubX(fID);
     76     }
     77 
     78     SkFixed getSubXFixed() const {
     79         return SubToFixed(ID2SubX(fID));
     80     }
     81 
     82     SkFixed getSubYFixed() const {
     83         return SubToFixed(ID2SubY(fID));
     84     }
     85 
     86     size_t computeImageSize() const;
     87 
     88     /** Call this to set all of the metrics fields to 0 (e.g. if the scaler
     89         encounters an error measuring a glyph). Note: this does not alter the
     90         fImage, fPath, fID, fMaskFormat fields.
     91      */
     92     void zeroMetrics();
     93 
     94     enum {
     95         kSubBits = 2,
     96         kSubMask = ((1 << kSubBits) - 1),
     97         kSubShift = 24, // must be large enough for glyphs and unichars
     98         kCodeMask = ((1 << kSubShift) - 1),
     99         // relative offsets for X and Y subpixel bits
    100         kSubShiftX = kSubBits,
    101         kSubShiftY = 0
    102     };
    103 
    104     static unsigned ID2Code(uint32_t id) {
    105         return id & kCodeMask;
    106     }
    107 
    108     static unsigned ID2SubX(uint32_t id) {
    109         return id >> (kSubShift + kSubShiftX);
    110     }
    111 
    112     static unsigned ID2SubY(uint32_t id) {
    113         return (id >> (kSubShift + kSubShiftY)) & kSubMask;
    114     }
    115 
    116     static unsigned FixedToSub(SkFixed n) {
    117         return (n >> (16 - kSubBits)) & kSubMask;
    118     }
    119 
    120     static SkFixed SubToFixed(unsigned sub) {
    121         SkASSERT(sub <= kSubMask);
    122         return sub << (16 - kSubBits);
    123     }
    124 
    125     static uint32_t MakeID(unsigned code) {
    126         return code;
    127     }
    128 
    129     static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) {
    130         SkASSERT(code <= kCodeMask);
    131         x = FixedToSub(x);
    132         y = FixedToSub(y);
    133         return (x << (kSubShift + kSubShiftX)) |
    134                (y << (kSubShift + kSubShiftY)) |
    135                code;
    136     }
    137 
    138     void toMask(SkMask* mask) const;
    139 
    140     /** Given a glyph which is has a mask format of LCD or VerticalLCD, take
    141         the A8 plane in fImage and produce a valid LCD plane from it.
    142     */
    143     void expandA8ToLCD() const;
    144 };
    145 
    146 class SkScalerContext {
    147 public:
    148     enum Flags {
    149         kFrameAndFill_Flag  = 0x01,
    150         kDevKernText_Flag   = 0x02,
    151         kGammaForBlack_Flag = 0x04, // illegal to set both Gamma flags
    152         kGammaForWhite_Flag = 0x08, // illegal to set both Gamma flags
    153         // together, these two flags resulting in a two bit value which matches
    154         // up with the SkPaint::Hinting enum.
    155         kHintingBit1_Flag   = 0x10,
    156         kHintingBit2_Flag   = 0x20,
    157         kEmbeddedBitmapText_Flag = 0x40,
    158         kEmbolden_Flag      = 0x80,
    159     };
    160 private:
    161     enum {
    162         kHintingMask = kHintingBit1_Flag | kHintingBit2_Flag
    163     };
    164 public:
    165     struct Rec {
    166         uint32_t    fFontID;
    167         SkScalar    fTextSize, fPreScaleX, fPreSkewX;
    168         SkScalar    fPost2x2[2][2];
    169         SkScalar    fFrameWidth, fMiterLimit;
    170         bool        fSubpixelPositioning;
    171         uint8_t     fMaskFormat;
    172         uint8_t     fStrokeJoin;
    173         uint8_t     fFlags;
    174         // Warning: when adding members note that the size of this structure
    175         // must be a multiple of 4. SkDescriptor requires that its arguments be
    176         // multiples of four and this structure is put in an SkDescriptor in
    177         // SkPaint::MakeRec.
    178 
    179         void    getMatrixFrom2x2(SkMatrix*) const;
    180         void    getLocalMatrix(SkMatrix*) const;
    181         void    getSingleMatrix(SkMatrix*) const;
    182 
    183         SkPaint::Hinting getHinting() const {
    184             return static_cast<SkPaint::Hinting>((fFlags & kHintingMask) >> 4);
    185         }
    186 
    187         void setHinting(SkPaint::Hinting hinting) {
    188             fFlags = (fFlags & ~kHintingMask) | (hinting << 4);
    189         }
    190 
    191         SkMask::Format getFormat() const {
    192             return static_cast<SkMask::Format>(fMaskFormat);
    193         }
    194 
    195         bool isLCD() const {
    196             return SkMask::FormatIsLCD(this->getFormat());
    197         }
    198     };
    199 
    200     SkScalerContext(const SkDescriptor* desc);
    201     virtual ~SkScalerContext();
    202 
    203     // remember our glyph offset/base
    204     void setBaseGlyphCount(unsigned baseGlyphCount) {
    205         fBaseGlyphCount = baseGlyphCount;
    206     }
    207 
    208     /** Return the corresponding glyph for the specified unichar. Since contexts
    209         may be chained (under the hood), the glyphID that is returned may in
    210         fact correspond to a different font/context. In that case, we use the
    211         base-glyph-count to know how to translate back into local glyph space.
    212      */
    213     uint16_t    charToGlyphID(SkUnichar uni);
    214 
    215     /** Map the glyphID to its glyph index, and then to its char code. Unmapped
    216         glyphs return zero.
    217     */
    218     SkUnichar glyphIDToChar(uint16_t glyphID);
    219 
    220     unsigned    getGlyphCount() const { return this->generateGlyphCount(); }
    221     void        getAdvance(SkGlyph*);
    222     void        getMetrics(SkGlyph*);
    223     void        getImage(const SkGlyph&);
    224     void        getPath(const SkGlyph&, SkPath*);
    225     void        getFontMetrics(SkPaint::FontMetrics* mX,
    226                                SkPaint::FontMetrics* mY);
    227 
    228     static inline void MakeRec(const SkPaint&, const SkMatrix*, Rec* rec);
    229     static SkScalerContext* Create(const SkDescriptor*);
    230 
    231 protected:
    232     Rec         fRec;
    233     unsigned    fBaseGlyphCount;
    234 
    235     virtual unsigned generateGlyphCount() const = 0;
    236     virtual uint16_t generateCharToGlyph(SkUnichar) = 0;
    237     virtual void generateAdvance(SkGlyph*) = 0;
    238     virtual void generateMetrics(SkGlyph*) = 0;
    239     virtual void generateImage(const SkGlyph&) = 0;
    240     virtual void generatePath(const SkGlyph&, SkPath*) = 0;
    241     virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
    242                                      SkPaint::FontMetrics* mY) = 0;
    243     // default impl returns 0, indicating failure.
    244     virtual SkUnichar generateGlyphToChar(uint16_t);
    245 
    246 private:
    247     SkPathEffect*   fPathEffect;
    248     SkMaskFilter*   fMaskFilter;
    249     SkRasterizer*   fRasterizer;
    250     SkScalar        fDevFrameWidth;
    251 
    252     void internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
    253                          SkPath* devPath, SkMatrix* fillToDevMatrix);
    254 
    255     // return the next context, treating fNextContext as a cache of the answer
    256     SkScalerContext* getNextContext();
    257 
    258     // returns the right context from our link-list for this glyph. If no match
    259     // is found, just returns the original context (this)
    260     SkScalerContext* getGlyphContext(const SkGlyph& glyph);
    261 
    262     // link-list of context, to handle missing chars. null-terminated.
    263     SkScalerContext* fNextContext;
    264 };
    265 
    266 #define kRec_SkDescriptorTag            SkSetFourByteTag('s', 'r', 'e', 'c')
    267 #define kPathEffect_SkDescriptorTag     SkSetFourByteTag('p', 't', 'h', 'e')
    268 #define kMaskFilter_SkDescriptorTag     SkSetFourByteTag('m', 's', 'k', 'f')
    269 #define kRasterizer_SkDescriptorTag     SkSetFourByteTag('r', 'a', 's', 't')
    270 
    271 #endif
    272 
    273