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