Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef SkGlyph_DEFINED
      9 #define SkGlyph_DEFINED
     10 
     11 #include "SkTypes.h"
     12 #include "SkFixed.h"
     13 #include "SkMask.h"
     14 
     15 class SkPath;
     16 class SkGlyphCache;
     17 
     18 // needs to be != to any valid SkMask::Format
     19 #define MASK_FORMAT_UNKNOWN         (0xFF)
     20 #define MASK_FORMAT_JUST_ADVANCE    MASK_FORMAT_UNKNOWN
     21 
     22 #define kMaxGlyphWidth (1<<13)
     23 
     24 class SkGlyph {
     25     enum {
     26         kSubBits = 2,
     27         kSubMask = ((1 << kSubBits) - 1),
     28         kSubShift = 24, // must be large enough for glyphs and unichars
     29         kCodeMask = ((1 << kSubShift) - 1),
     30         // relative offsets for X and Y subpixel bits
     31         kSubShiftX = kSubBits,
     32         kSubShiftY = 0
     33     };
     34 
     35  public:
     36     static const SkFixed kSubpixelRound = SK_FixedHalf >> SkGlyph::kSubBits;
     37     // A value that can never be generated by MakeID.
     38     static const uint32_t kImpossibleID = ~0;
     39     void*       fImage;
     40     SkPath*     fPath;
     41     SkFixed     fAdvanceX, fAdvanceY;
     42 
     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     int8_t      fForceBW;
     49 
     50     void initWithGlyphID(uint32_t glyph_id) {
     51         this->initCommon(MakeID(glyph_id));
     52     }
     53 
     54     void initGlyphIdFrom(const SkGlyph& glyph) {
     55         this->initCommon(glyph.fID);
     56     }
     57 
     58     void initGlyphFromCombinedID(uint32_t combined_id) {
     59       this->initCommon(combined_id);
     60     }
     61 
     62     /**
     63      *  Compute the rowbytes for the specified width and mask-format.
     64      */
     65     static unsigned ComputeRowBytes(unsigned width, SkMask::Format format) {
     66         unsigned rb = width;
     67         if (SkMask::kBW_Format == format) {
     68             rb = (rb + 7) >> 3;
     69         } else if (SkMask::kARGB32_Format == format) {
     70             rb <<= 2;
     71         } else if (SkMask::kLCD16_Format == format) {
     72             rb = SkAlign4(rb << 1);
     73         } else {
     74             rb = SkAlign4(rb);
     75         }
     76         return rb;
     77     }
     78 
     79     unsigned rowBytes() const {
     80         return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat);
     81     }
     82 
     83     bool isJustAdvance() const {
     84         return MASK_FORMAT_JUST_ADVANCE == fMaskFormat;
     85     }
     86 
     87     bool isFullMetrics() const {
     88         return MASK_FORMAT_JUST_ADVANCE != fMaskFormat;
     89     }
     90 
     91     uint16_t getGlyphID() const {
     92         return ID2Code(fID);
     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     void toMask(SkMask* mask) const;
    116 
    117  private:
    118     // TODO(herb) remove friend statement after SkGlyphCache cleanup.
    119     friend class SkGlyphCache;
    120 
    121     void initCommon(uint32_t id) {
    122         fID             = id;
    123         fImage          = NULL;
    124         fPath           = NULL;
    125         fMaskFormat     = MASK_FORMAT_UNKNOWN;
    126         fForceBW        = 0;
    127     }
    128 
    129     static unsigned ID2Code(uint32_t id) {
    130         return id & kCodeMask;
    131     }
    132 
    133     static unsigned ID2SubX(uint32_t id) {
    134         return id >> (kSubShift + kSubShiftX);
    135     }
    136 
    137     static unsigned ID2SubY(uint32_t id) {
    138         return (id >> (kSubShift + kSubShiftY)) & kSubMask;
    139     }
    140 
    141     static unsigned FixedToSub(SkFixed n) {
    142         return (n >> (16 - kSubBits)) & kSubMask;
    143     }
    144 
    145     static SkFixed SubToFixed(unsigned sub) {
    146         SkASSERT(sub <= kSubMask);
    147         return sub << (16 - kSubBits);
    148     }
    149 
    150     static uint32_t MakeID(unsigned code) {
    151         SkASSERT(code <= kCodeMask);
    152         SkASSERT(code != kImpossibleID);
    153         return code;
    154     }
    155 
    156     static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) {
    157         SkASSERT(code <= kCodeMask);
    158         x = FixedToSub(x);
    159         y = FixedToSub(y);
    160         uint32_t ID = (x << (kSubShift + kSubShiftX)) |
    161                       (y << (kSubShift + kSubShiftY)) |
    162                       code;
    163         SkASSERT(ID != kImpossibleID);
    164         return ID;
    165     }
    166 
    167   // FIXME - This is needed because the Android frame work directly
    168   // accesses fID. Remove when fID accesses are cleaned up.
    169 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    170   public:
    171 #endif
    172     uint32_t    fID;
    173 };
    174 
    175 #endif
    176