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 initWithGlyphID(uint32_t glyph_id)68 void initWithGlyphID(uint32_t glyph_id) { 69 this->initCommon(MakeID(glyph_id)); 70 } 71 initGlyphIdFrom(const SkGlyph & glyph)72 void initGlyphIdFrom(const SkGlyph& glyph) { 73 this->initCommon(glyph.fID); 74 } 75 initGlyphFromCombinedID(uint32_t combined_id)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 */ ComputeRowBytes(unsigned width,SkMask::Format format)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 rowBytes()97 unsigned rowBytes() const { 98 return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat); 99 } 100 isJustAdvance()101 bool isJustAdvance() const { 102 return MASK_FORMAT_JUST_ADVANCE == fMaskFormat; 103 } 104 isFullMetrics()105 bool isFullMetrics() const { 106 return MASK_FORMAT_JUST_ADVANCE != fMaskFormat; 107 } 108 getGlyphID()109 uint16_t getGlyphID() const { 110 return ID2Code(fID); 111 } 112 getSubX()113 unsigned getSubX() const { 114 return ID2SubX(fID); 115 } 116 getSubXFixed()117 SkFixed getSubXFixed() const { 118 return SubToFixed(ID2SubX(fID)); 119 } 120 getSubYFixed()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: GetKey(const SkGlyph & glyph)137 static uint32_t GetKey(const SkGlyph& glyph) { 138 return glyph.fID; 139 } Hash(uint32_t glyphId)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 initCommon(uint32_t id)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 ID2Code(uint32_t id)157 static unsigned ID2Code(uint32_t id) { 158 return id & kCodeMask; 159 } 160 ID2SubX(uint32_t id)161 static unsigned ID2SubX(uint32_t id) { 162 return id >> (kSubShift + kSubShiftX); 163 } 164 ID2SubY(uint32_t id)165 static unsigned ID2SubY(uint32_t id) { 166 return (id >> (kSubShift + kSubShiftY)) & kSubMask; 167 } 168 FixedToSub(SkFixed n)169 static unsigned FixedToSub(SkFixed n) { 170 return (n >> (16 - kSubBits)) & kSubMask; 171 } 172 SubToFixed(unsigned sub)173 static SkFixed SubToFixed(unsigned sub) { 174 SkASSERT(sub <= kSubMask); 175 return sub << (16 - kSubBits); 176 } 177 MakeID(unsigned code)178 static uint32_t MakeID(unsigned code) { 179 SkASSERT(code <= kCodeMask); 180 SkASSERT(code != kImpossibleID); 181 return code; 182 } 183 MakeID(unsigned code,SkFixed x,SkFixed y)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