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 initWithGlyphID(uint32_t glyph_id)50 void initWithGlyphID(uint32_t glyph_id) { 51 this->initCommon(MakeID(glyph_id)); 52 } 53 initGlyphIdFrom(const SkGlyph & glyph)54 void initGlyphIdFrom(const SkGlyph& glyph) { 55 this->initCommon(glyph.fID); 56 } 57 initGlyphFromCombinedID(uint32_t combined_id)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 */ ComputeRowBytes(unsigned width,SkMask::Format format)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 rowBytes()79 unsigned rowBytes() const { 80 return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat); 81 } 82 isJustAdvance()83 bool isJustAdvance() const { 84 return MASK_FORMAT_JUST_ADVANCE == fMaskFormat; 85 } 86 isFullMetrics()87 bool isFullMetrics() const { 88 return MASK_FORMAT_JUST_ADVANCE != fMaskFormat; 89 } 90 getGlyphID()91 uint16_t getGlyphID() const { 92 return ID2Code(fID); 93 } 94 getSubX()95 unsigned getSubX() const { 96 return ID2SubX(fID); 97 } 98 getSubXFixed()99 SkFixed getSubXFixed() const { 100 return SubToFixed(ID2SubX(fID)); 101 } 102 getSubYFixed()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 initCommon(uint32_t id)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 ID2Code(uint32_t id)129 static unsigned ID2Code(uint32_t id) { 130 return id & kCodeMask; 131 } 132 ID2SubX(uint32_t id)133 static unsigned ID2SubX(uint32_t id) { 134 return id >> (kSubShift + kSubShiftX); 135 } 136 ID2SubY(uint32_t id)137 static unsigned ID2SubY(uint32_t id) { 138 return (id >> (kSubShift + kSubShiftY)) & kSubMask; 139 } 140 FixedToSub(SkFixed n)141 static unsigned FixedToSub(SkFixed n) { 142 return (n >> (16 - kSubBits)) & kSubMask; 143 } 144 SubToFixed(unsigned sub)145 static SkFixed SubToFixed(unsigned sub) { 146 SkASSERT(sub <= kSubMask); 147 return sub << (16 - kSubBits); 148 } 149 MakeID(unsigned code)150 static uint32_t MakeID(unsigned code) { 151 SkASSERT(code <= kCodeMask); 152 SkASSERT(code != kImpossibleID); 153 return code; 154 } 155 MakeID(unsigned code,SkFixed x,SkFixed y)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