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 "SkChecksum.h"
     12 #include "SkTypes.h"
     13 #include "SkFixed.h"
     14 #include "SkMask.h"
     15 
     16 class SkPath;
     17 class SkGlyphCache;
     18 
     19 // needs to be != to any valid SkMask::Format
     20 #define MASK_FORMAT_UNKNOWN         (0xFF)
     21 #define MASK_FORMAT_JUST_ADVANCE    MASK_FORMAT_UNKNOWN
     22 
     23 #define kMaxGlyphWidth (1<<13)
     24 
     25 SK_BEGIN_REQUIRE_DENSE
     26 class SkGlyph {
     27     enum {
     28         kSubBits = 2,
     29         kSubMask = ((1 << kSubBits) - 1),
     30         kSubShift = 24, // must be large enough for glyphs and unichars
     31         kCodeMask = ((1 << kSubShift) - 1),
     32         // relative offsets for X and Y subpixel bits
     33         kSubShiftX = kSubBits,
     34         kSubShiftY = 0
     35     };
     36 
     37     // Support horizontal and vertical skipping strike-through / underlines.
     38     // The caller walks the linked list looking for a match. For a horizontal underline,
     39     // the fBounds contains the top and bottom of the underline. The fInterval pair contains the
     40     // beginning and end of of the intersection of the bounds and the glyph's path.
     41     // If interval[0] >= interval[1], no intesection was found.
     42     struct Intercept {
     43         Intercept* fNext;
     44         SkScalar   fBounds[2];    // for horz underlines, the boundaries in Y
     45         SkScalar   fInterval[2];  // the outside intersections of the axis and the glyph
     46     };
     47 
     48     struct PathData {
     49         Intercept* fIntercept;
     50         SkPath*    fPath;
     51     };
     52 
     53 public:
     54     static const SkFixed kSubpixelRound = SK_FixedHalf >> SkGlyph::kSubBits;
     55     // A value that can never be generated by MakeID.
     56     static const uint32_t kImpossibleID = ~0;
     57     void*       fImage;
     58     PathData*   fPathData;
     59     SkFixed     fAdvanceX, fAdvanceY;
     60 
     61     uint16_t    fWidth, fHeight;
     62     int16_t     fTop, fLeft;
     63 
     64     uint8_t     fMaskFormat;
     65     int8_t      fRsbDelta, fLsbDelta;  // used by auto-kerning
     66     int8_t      fForceBW;
     67 
     68     void initWithGlyphID(uint32_t glyph_id) {
     69         this->initCommon(MakeID(glyph_id));
     70     }
     71 
     72     void initGlyphIdFrom(const SkGlyph& glyph) {
     73         this->initCommon(glyph.fID);
     74     }
     75 
     76     void initGlyphFromCombinedID(uint32_t combined_id) {
     77       this->initCommon(combined_id);
     78     }
     79 
     80     /**
     81      *  Compute the rowbytes for the specified width and mask-format.
     82      */
     83     static unsigned ComputeRowBytes(unsigned width, SkMask::Format format) {
     84         unsigned rb = width;
     85         if (SkMask::kBW_Format == format) {
     86             rb = (rb + 7) >> 3;
     87         } else if (SkMask::kARGB32_Format == format) {
     88             rb <<= 2;
     89         } else if (SkMask::kLCD16_Format == format) {
     90             rb = SkAlign4(rb << 1);
     91         } else {
     92             rb = SkAlign4(rb);
     93         }
     94         return rb;
     95     }
     96 
     97     unsigned rowBytes() const {
     98         return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat);
     99     }
    100 
    101     bool isJustAdvance() const {
    102         return MASK_FORMAT_JUST_ADVANCE == fMaskFormat;
    103     }
    104 
    105     bool isFullMetrics() const {
    106         return MASK_FORMAT_JUST_ADVANCE != fMaskFormat;
    107     }
    108 
    109     uint16_t getGlyphID() const {
    110         return ID2Code(fID);
    111     }
    112 
    113     unsigned getSubX() const {
    114         return ID2SubX(fID);
    115     }
    116 
    117     SkFixed getSubXFixed() const {
    118         return SubToFixed(ID2SubX(fID));
    119     }
    120 
    121     SkFixed getSubYFixed() const {
    122         return SubToFixed(ID2SubY(fID));
    123     }
    124 
    125     size_t computeImageSize() const;
    126 
    127     /** Call this to set all of the metrics fields to 0 (e.g. if the scaler
    128         encounters an error measuring a glyph). Note: this does not alter the
    129         fImage, fPath, fID, fMaskFormat fields.
    130      */
    131     void zeroMetrics();
    132 
    133     void toMask(SkMask* mask) const;
    134 
    135     class HashTraits {
    136     public:
    137         static uint32_t GetKey(const SkGlyph& glyph) {
    138             return glyph.fID;
    139         }
    140         static uint32_t Hash(uint32_t glyphId) {
    141             return SkChecksum::CheapMix(glyphId);
    142         }
    143     };
    144 
    145  private:
    146     // TODO(herb) remove friend statement after SkGlyphCache cleanup.
    147     friend class SkGlyphCache;
    148 
    149     void initCommon(uint32_t id) {
    150         fID             = id;
    151         fImage          = nullptr;
    152         fPathData       = nullptr;
    153         fMaskFormat     = MASK_FORMAT_UNKNOWN;
    154         fForceBW        = 0;
    155     }
    156 
    157     static unsigned ID2Code(uint32_t id) {
    158         return id & kCodeMask;
    159     }
    160 
    161     static unsigned ID2SubX(uint32_t id) {
    162         return id >> (kSubShift + kSubShiftX);
    163     }
    164 
    165     static unsigned ID2SubY(uint32_t id) {
    166         return (id >> (kSubShift + kSubShiftY)) & kSubMask;
    167     }
    168 
    169     static unsigned FixedToSub(SkFixed n) {
    170         return (n >> (16 - kSubBits)) & kSubMask;
    171     }
    172 
    173     static SkFixed SubToFixed(unsigned sub) {
    174         SkASSERT(sub <= kSubMask);
    175         return sub << (16 - kSubBits);
    176     }
    177 
    178     static uint32_t MakeID(unsigned code) {
    179         SkASSERT(code <= kCodeMask);
    180         SkASSERT(code != kImpossibleID);
    181         return code;
    182     }
    183 
    184     static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) {
    185         SkASSERT(code <= kCodeMask);
    186         x = FixedToSub(x);
    187         y = FixedToSub(y);
    188         uint32_t ID = (x << (kSubShift + kSubShiftX)) |
    189                       (y << (kSubShift + kSubShiftY)) |
    190                       code;
    191         SkASSERT(ID != kImpossibleID);
    192         return ID;
    193     }
    194 
    195     // FIXME - This is needed because the Android frame work directly
    196   // accesses fID. Remove when fID accesses are cleaned up.
    197 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    198   public:
    199 #endif
    200     uint32_t    fID;
    201 };
    202 SK_END_REQUIRE_DENSE
    203 
    204 #endif
    205