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_UNKNOWN (0xFF) 33 #define MASK_FORMAT_JUST_ADVANCE MASK_FORMAT_UNKNOWN 34 35 #define kMaxGlyphWidth (1<<13) 36 37 struct SkGlyph { 38 void* fImage; 39 SkPath* fPath; 40 SkFixed fAdvanceX, fAdvanceY; 41 42 uint32_t fID; 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 initSkGlyph49 void init(uint32_t id) { 50 fID = id; 51 fImage = NULL; 52 fPath = NULL; 53 fMaskFormat = MASK_FORMAT_UNKNOWN; 54 } 55 56 /** 57 * Compute the rowbytes for the specified width and mask-format. 58 */ ComputeRowBytesSkGlyph59 static unsigned ComputeRowBytes(unsigned width, SkMask::Format format) { 60 unsigned rb = width; 61 if (SkMask::kBW_Format == format) { 62 rb = (rb + 7) >> 3; 63 } else if (SkMask::kARGB32_Format == format) { 64 rb <<= 2; 65 } else if (SkMask::kLCD16_Format == format) { 66 rb = SkAlign4(rb << 1); 67 } else { 68 rb = SkAlign4(rb); 69 } 70 return rb; 71 } 72 rowBytesSkGlyph73 unsigned rowBytes() const { 74 return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat); 75 } 76 isJustAdvanceSkGlyph77 bool isJustAdvance() const { 78 return MASK_FORMAT_JUST_ADVANCE == fMaskFormat; 79 } 80 isFullMetricsSkGlyph81 bool isFullMetrics() const { 82 return MASK_FORMAT_JUST_ADVANCE != fMaskFormat; 83 } 84 getGlyphIDSkGlyph85 uint16_t getGlyphID() const { 86 return ID2Code(fID); 87 } 88 getGlyphIDSkGlyph89 unsigned getGlyphID(unsigned baseGlyphCount) const { 90 unsigned code = ID2Code(fID); 91 SkASSERT(code >= baseGlyphCount); 92 return code - baseGlyphCount; 93 } 94 getSubXSkGlyph95 unsigned getSubX() const { 96 return ID2SubX(fID); 97 } 98 getSubXFixedSkGlyph99 SkFixed getSubXFixed() const { 100 return SubToFixed(ID2SubX(fID)); 101 } 102 getSubYFixedSkGlyph103 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 enum { 116 kSubBits = 2, 117 kSubMask = ((1 << kSubBits) - 1), 118 kSubShift = 24, // must be large enough for glyphs and unichars 119 kCodeMask = ((1 << kSubShift) - 1), 120 // relative offsets for X and Y subpixel bits 121 kSubShiftX = kSubBits, 122 kSubShiftY = 0 123 }; 124 ID2CodeSkGlyph125 static unsigned ID2Code(uint32_t id) { 126 return id & kCodeMask; 127 } 128 ID2SubXSkGlyph129 static unsigned ID2SubX(uint32_t id) { 130 return id >> (kSubShift + kSubShiftX); 131 } 132 ID2SubYSkGlyph133 static unsigned ID2SubY(uint32_t id) { 134 return (id >> (kSubShift + kSubShiftY)) & kSubMask; 135 } 136 FixedToSubSkGlyph137 static unsigned FixedToSub(SkFixed n) { 138 return (n >> (16 - kSubBits)) & kSubMask; 139 } 140 SubToFixedSkGlyph141 static SkFixed SubToFixed(unsigned sub) { 142 SkASSERT(sub <= kSubMask); 143 return sub << (16 - kSubBits); 144 } 145 MakeIDSkGlyph146 static uint32_t MakeID(unsigned code) { 147 return code; 148 } 149 MakeIDSkGlyph150 static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) { 151 SkASSERT(code <= kCodeMask); 152 x = FixedToSub(x); 153 y = FixedToSub(y); 154 return (x << (kSubShift + kSubShiftX)) | 155 (y << (kSubShift + kSubShiftY)) | 156 code; 157 } 158 159 void toMask(SkMask* mask) const; 160 161 /** Given a glyph which is has a mask format of LCD or VerticalLCD, take 162 the A8 plane in fImage and produce a valid LCD plane from it. 163 */ 164 void expandA8ToLCD() const; 165 }; 166 167 class SkScalerContext { 168 public: 169 enum Flags { 170 kFrameAndFill_Flag = 0x01, 171 kDevKernText_Flag = 0x02, 172 kGammaForBlack_Flag = 0x04, // illegal to set both Gamma flags 173 kGammaForWhite_Flag = 0x08, // illegal to set both Gamma flags 174 // together, these two flags resulting in a two bit value which matches 175 // up with the SkPaint::Hinting enum. 176 kHintingBit1_Flag = 0x10, 177 kHintingBit2_Flag = 0x20, 178 kEmbeddedBitmapText_Flag = 0x40, 179 kEmbolden_Flag = 0x80, 180 kSubpixelPositioning_Flag = 0x100, 181 kAutohinting_Flag = 0x200, 182 // these should only ever be set if fMaskFormat is LCD 183 kLCD_Vertical_Flag = 0x400, // else Horizontal 184 kLCD_BGROrder_Flag = 0x800, // else RGB order 185 }; 186 private: 187 enum { 188 kHintingMask = kHintingBit1_Flag | kHintingBit2_Flag 189 }; 190 public: 191 struct Rec { 192 uint32_t fOrigFontID; 193 uint32_t fFontID; 194 SkScalar fTextSize, fPreScaleX, fPreSkewX; 195 SkScalar fPost2x2[2][2]; 196 SkScalar fFrameWidth, fMiterLimit; 197 uint8_t fMaskFormat; 198 uint8_t fStrokeJoin; 199 uint16_t fFlags; 200 // Warning: when adding members note that the size of this structure 201 // must be a multiple of 4. SkDescriptor requires that its arguments be 202 // multiples of four and this structure is put in an SkDescriptor in 203 // SkPaint::MakeRec. 204 205 void getMatrixFrom2x2(SkMatrix*) const; 206 void getLocalMatrix(SkMatrix*) const; 207 void getSingleMatrix(SkMatrix*) const; 208 getHintingRec209 SkPaint::Hinting getHinting() const { 210 return static_cast<SkPaint::Hinting>((fFlags & kHintingMask) >> 4); 211 } 212 setHintingRec213 void setHinting(SkPaint::Hinting hinting) { 214 fFlags = (fFlags & ~kHintingMask) | (hinting << 4); 215 } 216 getFormatRec217 SkMask::Format getFormat() const { 218 return static_cast<SkMask::Format>(fMaskFormat); 219 } 220 isLCDRec221 bool isLCD() const { 222 return SkMask::FormatIsLCD(this->getFormat()); 223 } 224 }; 225 226 SkScalerContext(const SkDescriptor* desc); 227 virtual ~SkScalerContext(); 228 getMaskFormat()229 SkMask::Format getMaskFormat() const { 230 return (SkMask::Format)fRec.fMaskFormat; 231 } 232 233 // remember our glyph offset/base setBaseGlyphCount(unsigned baseGlyphCount)234 void setBaseGlyphCount(unsigned baseGlyphCount) { 235 fBaseGlyphCount = baseGlyphCount; 236 } 237 238 /** Return the corresponding glyph for the specified unichar. Since contexts 239 may be chained (under the hood), the glyphID that is returned may in 240 fact correspond to a different font/context. In that case, we use the 241 base-glyph-count to know how to translate back into local glyph space. 242 */ 243 uint16_t charToGlyphID(SkUnichar uni); 244 245 /** Map the glyphID to its glyph index, and then to its char code. Unmapped 246 glyphs return zero. 247 */ 248 SkUnichar glyphIDToChar(uint16_t glyphID); 249 getGlyphCount()250 unsigned getGlyphCount() { return this->generateGlyphCount(); } 251 void getAdvance(SkGlyph*); 252 void getMetrics(SkGlyph*); 253 void getImage(const SkGlyph&); 254 void getPath(const SkGlyph&, SkPath*); 255 void getFontMetrics(SkPaint::FontMetrics* mX, 256 SkPaint::FontMetrics* mY); 257 258 static inline void MakeRec(const SkPaint&, const SkMatrix*, Rec* rec); 259 static SkScalerContext* Create(const SkDescriptor*); 260 261 protected: 262 Rec fRec; 263 unsigned fBaseGlyphCount; 264 265 virtual unsigned generateGlyphCount() = 0; 266 virtual uint16_t generateCharToGlyph(SkUnichar) = 0; 267 virtual void generateAdvance(SkGlyph*) = 0; 268 virtual void generateMetrics(SkGlyph*) = 0; 269 virtual void generateImage(const SkGlyph&) = 0; 270 virtual void generatePath(const SkGlyph&, SkPath*) = 0; 271 virtual void generateFontMetrics(SkPaint::FontMetrics* mX, 272 SkPaint::FontMetrics* mY) = 0; 273 // default impl returns 0, indicating failure. 274 virtual SkUnichar generateGlyphToChar(uint16_t); 275 276 private: 277 SkPathEffect* fPathEffect; 278 SkMaskFilter* fMaskFilter; 279 SkRasterizer* fRasterizer; 280 SkScalar fDevFrameWidth; 281 282 void internalGetPath(const SkGlyph& glyph, SkPath* fillPath, 283 SkPath* devPath, SkMatrix* fillToDevMatrix); 284 285 // return the next context, treating fNextContext as a cache of the answer 286 SkScalerContext* getNextContext(); 287 288 // returns the right context from our link-list for this glyph. If no match 289 // is found, just returns the original context (this) 290 SkScalerContext* getGlyphContext(const SkGlyph& glyph); 291 292 // link-list of context, to handle missing chars. null-terminated. 293 SkScalerContext* fNextContext; 294 }; 295 296 #define kRec_SkDescriptorTag SkSetFourByteTag('s', 'r', 'e', 'c') 297 #define kPathEffect_SkDescriptorTag SkSetFourByteTag('p', 't', 'h', 'e') 298 #define kMaskFilter_SkDescriptorTag SkSetFourByteTag('m', 's', 'k', 'f') 299 #define kRasterizer_SkDescriptorTag SkSetFourByteTag('r', 'a', 's', 't') 300 301 #endif 302 303