1 2 /* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #ifndef SkScalerContext_DEFINED 11 #define SkScalerContext_DEFINED 12 13 #include "SkMask.h" 14 #include "SkMatrix.h" 15 #include "SkPaint.h" 16 #include "SkPath.h" 17 #include "SkPoint.h" 18 19 //#define SK_USE_COLOR_LUMINANCE 20 21 class SkDescriptor; 22 class SkMaskFilter; 23 class SkPathEffect; 24 class SkRasterizer; 25 26 // needs to be != to any valid SkMask::Format 27 #define MASK_FORMAT_UNKNOWN (0xFF) 28 #define MASK_FORMAT_JUST_ADVANCE MASK_FORMAT_UNKNOWN 29 30 #define kMaxGlyphWidth (1<<13) 31 32 struct SkGlyph { 33 void* fImage; 34 SkPath* fPath; 35 SkFixed fAdvanceX, fAdvanceY; 36 37 uint32_t fID; 38 uint16_t fWidth, fHeight; 39 int16_t fTop, fLeft; 40 41 uint8_t fMaskFormat; 42 int8_t fRsbDelta, fLsbDelta; // used by auto-kerning 43 initSkGlyph44 void init(uint32_t id) { 45 fID = id; 46 fImage = NULL; 47 fPath = NULL; 48 fMaskFormat = MASK_FORMAT_UNKNOWN; 49 } 50 51 /** 52 * Compute the rowbytes for the specified width and mask-format. 53 */ ComputeRowBytesSkGlyph54 static unsigned ComputeRowBytes(unsigned width, SkMask::Format format) { 55 unsigned rb = width; 56 if (SkMask::kBW_Format == format) { 57 rb = (rb + 7) >> 3; 58 } else if (SkMask::kARGB32_Format == format || 59 SkMask::kLCD32_Format == format) 60 { 61 rb <<= 2; 62 } else if (SkMask::kLCD16_Format == format) { 63 rb = SkAlign4(rb << 1); 64 } else { 65 rb = SkAlign4(rb); 66 } 67 return rb; 68 } 69 rowBytesSkGlyph70 unsigned rowBytes() const { 71 return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat); 72 } 73 isJustAdvanceSkGlyph74 bool isJustAdvance() const { 75 return MASK_FORMAT_JUST_ADVANCE == fMaskFormat; 76 } 77 isFullMetricsSkGlyph78 bool isFullMetrics() const { 79 return MASK_FORMAT_JUST_ADVANCE != fMaskFormat; 80 } 81 getGlyphIDSkGlyph82 uint16_t getGlyphID() const { 83 return ID2Code(fID); 84 } 85 getGlyphIDSkGlyph86 unsigned getGlyphID(unsigned baseGlyphCount) const { 87 unsigned code = ID2Code(fID); 88 SkASSERT(code >= baseGlyphCount); 89 return code - baseGlyphCount; 90 } 91 getSubXSkGlyph92 unsigned getSubX() const { 93 return ID2SubX(fID); 94 } 95 getSubXFixedSkGlyph96 SkFixed getSubXFixed() const { 97 return SubToFixed(ID2SubX(fID)); 98 } 99 getSubYFixedSkGlyph100 SkFixed getSubYFixed() const { 101 return SubToFixed(ID2SubY(fID)); 102 } 103 104 size_t computeImageSize() const; 105 106 /** Call this to set all of the metrics fields to 0 (e.g. if the scaler 107 encounters an error measuring a glyph). Note: this does not alter the 108 fImage, fPath, fID, fMaskFormat fields. 109 */ 110 void zeroMetrics(); 111 112 enum { 113 kSubBits = 2, 114 kSubMask = ((1 << kSubBits) - 1), 115 kSubShift = 24, // must be large enough for glyphs and unichars 116 kCodeMask = ((1 << kSubShift) - 1), 117 // relative offsets for X and Y subpixel bits 118 kSubShiftX = kSubBits, 119 kSubShiftY = 0 120 }; 121 ID2CodeSkGlyph122 static unsigned ID2Code(uint32_t id) { 123 return id & kCodeMask; 124 } 125 ID2SubXSkGlyph126 static unsigned ID2SubX(uint32_t id) { 127 return id >> (kSubShift + kSubShiftX); 128 } 129 ID2SubYSkGlyph130 static unsigned ID2SubY(uint32_t id) { 131 return (id >> (kSubShift + kSubShiftY)) & kSubMask; 132 } 133 FixedToSubSkGlyph134 static unsigned FixedToSub(SkFixed n) { 135 return (n >> (16 - kSubBits)) & kSubMask; 136 } 137 SubToFixedSkGlyph138 static SkFixed SubToFixed(unsigned sub) { 139 SkASSERT(sub <= kSubMask); 140 return sub << (16 - kSubBits); 141 } 142 MakeIDSkGlyph143 static uint32_t MakeID(unsigned code) { 144 return code; 145 } 146 MakeIDSkGlyph147 static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) { 148 SkASSERT(code <= kCodeMask); 149 x = FixedToSub(x); 150 y = FixedToSub(y); 151 return (x << (kSubShift + kSubShiftX)) | 152 (y << (kSubShift + kSubShiftY)) | 153 code; 154 } 155 156 void toMask(SkMask* mask) const; 157 }; 158 159 class SkScalerContext { 160 public: 161 enum Flags { 162 kFrameAndFill_Flag = 0x0001, 163 kDevKernText_Flag = 0x0002, 164 kEmbeddedBitmapText_Flag = 0x0004, 165 kEmbolden_Flag = 0x0008, 166 kSubpixelPositioning_Flag = 0x0010, 167 kAutohinting_Flag = 0x0020, 168 kVertical_Flag = 0x0040, 169 170 // together, these two flags resulting in a two bit value which matches 171 // up with the SkPaint::Hinting enum. 172 kHinting_Shift = 7, // to shift into the other flags above 173 kHintingBit1_Flag = 0x0080, 174 kHintingBit2_Flag = 0x0100, 175 176 // these should only ever be set if fMaskFormat is LCD16 or LCD32 177 kLCD_Vertical_Flag = 0x0200, // else Horizontal 178 kLCD_BGROrder_Flag = 0x0400, // else RGB order 179 180 // Generate A8 from LCD source (for GDI), only meaningful if fMaskFormat is kA8 181 // Perhaps we can store this (instead) in fMaskFormat, in hight bit? 182 kGenA8FromLCD_Flag = 0x0800, 183 184 #ifdef SK_USE_COLOR_LUMINANCE 185 kLuminance_Bits = 3, 186 #else 187 // luminance : 0 for black text, kLuminance_Max for white text 188 kLuminance_Shift = 13, // shift to land in the high 3-bits of Flags 189 kLuminance_Bits = 3, // ensure Flags doesn't exceed 16bits 190 #endif 191 }; 192 193 // computed values 194 enum { 195 kHinting_Mask = kHintingBit1_Flag | kHintingBit2_Flag, 196 #ifdef SK_USE_COLOR_LUMINANCE 197 #else 198 kLuminance_Max = (1 << kLuminance_Bits) - 1, 199 kLuminance_Mask = kLuminance_Max << kLuminance_Shift, 200 #endif 201 }; 202 203 struct Rec { 204 uint32_t fOrigFontID; 205 uint32_t fFontID; 206 SkScalar fTextSize, fPreScaleX, fPreSkewX; 207 SkScalar fPost2x2[2][2]; 208 SkScalar fFrameWidth, fMiterLimit; 209 #ifdef SK_USE_COLOR_LUMINANCE 210 uint32_t fLumBits; 211 #endif 212 uint8_t fMaskFormat; 213 uint8_t fStrokeJoin; 214 uint16_t fFlags; 215 // Warning: when adding members note that the size of this structure 216 // must be a multiple of 4. SkDescriptor requires that its arguments be 217 // multiples of four and this structure is put in an SkDescriptor in 218 // SkPaint::MakeRec. 219 220 void getMatrixFrom2x2(SkMatrix*) const; 221 void getLocalMatrix(SkMatrix*) const; 222 void getSingleMatrix(SkMatrix*) const; 223 getHintingRec224 SkPaint::Hinting getHinting() const { 225 unsigned hint = (fFlags & kHinting_Mask) >> kHinting_Shift; 226 return static_cast<SkPaint::Hinting>(hint); 227 } 228 setHintingRec229 void setHinting(SkPaint::Hinting hinting) { 230 fFlags = (fFlags & ~kHinting_Mask) | (hinting << kHinting_Shift); 231 } 232 getFormatRec233 SkMask::Format getFormat() const { 234 return static_cast<SkMask::Format>(fMaskFormat); 235 } 236 237 #ifdef SK_USE_COLOR_LUMINANCE getLuminanceColorRec238 SkColor getLuminanceColor() const { 239 return fLumBits; 240 } 241 setLuminanceColorRec242 void setLuminanceColor(SkColor c) { 243 fLumBits = c; 244 } 245 #else getLuminanceBitsRec246 unsigned getLuminanceBits() const { 247 return (fFlags & kLuminance_Mask) >> kLuminance_Shift; 248 } 249 setLuminanceBitsRec250 void setLuminanceBits(unsigned lum) { 251 SkASSERT(lum <= kLuminance_Max); 252 fFlags = (fFlags & ~kLuminance_Mask) | (lum << kLuminance_Shift); 253 } 254 getLuminanceByteRec255 U8CPU getLuminanceByte() const { 256 SkASSERT(3 == kLuminance_Bits); 257 unsigned lum = this->getLuminanceBits(); 258 lum |= (lum << kLuminance_Bits); 259 lum |= (lum << kLuminance_Bits*2); 260 return lum >> (4*kLuminance_Bits - 8); 261 } 262 #endif 263 }; 264 265 SkScalerContext(const SkDescriptor* desc); 266 virtual ~SkScalerContext(); 267 getMaskFormat()268 SkMask::Format getMaskFormat() const { 269 return (SkMask::Format)fRec.fMaskFormat; 270 } 271 isSubpixel()272 bool isSubpixel() const { 273 return SkToBool(fRec.fFlags & kSubpixelPositioning_Flag); 274 } 275 276 // remember our glyph offset/base setBaseGlyphCount(unsigned baseGlyphCount)277 void setBaseGlyphCount(unsigned baseGlyphCount) { 278 fBaseGlyphCount = baseGlyphCount; 279 } 280 281 /** Return the corresponding glyph for the specified unichar. Since contexts 282 may be chained (under the hood), the glyphID that is returned may in 283 fact correspond to a different font/context. In that case, we use the 284 base-glyph-count to know how to translate back into local glyph space. 285 */ 286 uint16_t charToGlyphID(SkUnichar uni); 287 288 /** Map the glyphID to its glyph index, and then to its char code. Unmapped 289 glyphs return zero. 290 */ 291 SkUnichar glyphIDToChar(uint16_t glyphID); 292 getGlyphCount()293 unsigned getGlyphCount() { return this->generateGlyphCount(); } 294 void getAdvance(SkGlyph*); 295 void getMetrics(SkGlyph*); 296 void getImage(const SkGlyph&); 297 void getPath(const SkGlyph&, SkPath*); 298 void getFontMetrics(SkPaint::FontMetrics* mX, 299 SkPaint::FontMetrics* mY); 300 301 #ifdef SK_BUILD_FOR_ANDROID 302 unsigned getBaseGlyphCount(SkUnichar charCode); 303 #endif 304 305 static inline void MakeRec(const SkPaint&, const SkMatrix*, Rec* rec); 306 static inline void PostMakeRec(Rec*); 307 308 static SkScalerContext* Create(const SkDescriptor*); 309 310 protected: 311 Rec fRec; 312 unsigned fBaseGlyphCount; 313 314 virtual unsigned generateGlyphCount() = 0; 315 virtual uint16_t generateCharToGlyph(SkUnichar) = 0; 316 virtual void generateAdvance(SkGlyph*) = 0; 317 virtual void generateMetrics(SkGlyph*) = 0; 318 virtual void generateImage(const SkGlyph&) = 0; 319 virtual void generatePath(const SkGlyph&, SkPath*) = 0; 320 virtual void generateFontMetrics(SkPaint::FontMetrics* mX, 321 SkPaint::FontMetrics* mY) = 0; 322 // default impl returns 0, indicating failure. 323 virtual SkUnichar generateGlyphToChar(uint16_t); 324 forceGenerateImageFromPath()325 void forceGenerateImageFromPath() { fGenerateImageFromPath = true; } 326 327 private: 328 SkPathEffect* fPathEffect; 329 SkMaskFilter* fMaskFilter; 330 SkRasterizer* fRasterizer; 331 SkScalar fDevFrameWidth; 332 333 // if this is set, we draw the image from a path, rather than 334 // calling generateImage. 335 bool fGenerateImageFromPath; 336 337 void internalGetPath(const SkGlyph& glyph, SkPath* fillPath, 338 SkPath* devPath, SkMatrix* fillToDevMatrix); 339 340 // return the next context, treating fNextContext as a cache of the answer 341 SkScalerContext* getNextContext(); 342 343 // returns the right context from our link-list for this glyph. If no match 344 // is found, just returns the original context (this) 345 SkScalerContext* getGlyphContext(const SkGlyph& glyph); 346 347 // link-list of context, to handle missing chars. null-terminated. 348 SkScalerContext* fNextContext; 349 }; 350 351 #define kRec_SkDescriptorTag SkSetFourByteTag('s', 'r', 'e', 'c') 352 #define kPathEffect_SkDescriptorTag SkSetFourByteTag('p', 't', 'h', 'e') 353 #define kMaskFilter_SkDescriptorTag SkSetFourByteTag('m', 's', 'k', 'f') 354 #define kRasterizer_SkDescriptorTag SkSetFourByteTag('r', 'a', 's', 't') 355 356 /////////////////////////////////////////////////////////////////////////////// 357 358 enum SkAxisAlignment { 359 kNone_SkAxisAlignment, 360 kX_SkAxisAlignment, 361 kY_SkAxisAlignment 362 }; 363 364 /** 365 * Return the axis (if any) that the baseline for horizontal text will land on 366 * after running through the specified matrix. 367 * 368 * As an example, the identity matrix will return kX_SkAxisAlignment 369 */ 370 SkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix); 371 372 #endif 373 374