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#ifdef SK_BUILD_FOR_ANDROID 21#include "SkLanguage.h" 22#endif 23 24//#define SK_USE_COLOR_LUMINANCE 25 26class SkDescriptor; 27class SkMaskFilter; 28class SkPathEffect; 29class 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 37struct 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 49 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 */ 59 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 SkMask::kLCD32_Format == format) 65 { 66 rb <<= 2; 67 } else if (SkMask::kLCD16_Format == format) { 68 rb = SkAlign4(rb << 1); 69 } else { 70 rb = SkAlign4(rb); 71 } 72 return rb; 73 } 74 75 unsigned rowBytes() const { 76 return ComputeRowBytes(fWidth, (SkMask::Format)fMaskFormat); 77 } 78 79 bool isJustAdvance() const { 80 return MASK_FORMAT_JUST_ADVANCE == fMaskFormat; 81 } 82 83 bool isFullMetrics() const { 84 return MASK_FORMAT_JUST_ADVANCE != fMaskFormat; 85 } 86 87 uint16_t getGlyphID() const { 88 return ID2Code(fID); 89 } 90 91 unsigned getGlyphID(unsigned baseGlyphCount) const { 92 unsigned code = ID2Code(fID); 93 SkASSERT(code >= baseGlyphCount); 94 return code - baseGlyphCount; 95 } 96 97 unsigned getSubX() const { 98 return ID2SubX(fID); 99 } 100 101 SkFixed getSubXFixed() const { 102 return SubToFixed(ID2SubX(fID)); 103 } 104 105 SkFixed getSubYFixed() const { 106 return SubToFixed(ID2SubY(fID)); 107 } 108 109 size_t computeImageSize() const; 110 111 /** Call this to set all of the metrics fields to 0 (e.g. if the scaler 112 encounters an error measuring a glyph). Note: this does not alter the 113 fImage, fPath, fID, fMaskFormat fields. 114 */ 115 void zeroMetrics(); 116 117 enum { 118 kSubBits = 2, 119 kSubMask = ((1 << kSubBits) - 1), 120 kSubShift = 24, // must be large enough for glyphs and unichars 121 kCodeMask = ((1 << kSubShift) - 1), 122 // relative offsets for X and Y subpixel bits 123 kSubShiftX = kSubBits, 124 kSubShiftY = 0 125 }; 126 127 static unsigned ID2Code(uint32_t id) { 128 return id & kCodeMask; 129 } 130 131 static unsigned ID2SubX(uint32_t id) { 132 return id >> (kSubShift + kSubShiftX); 133 } 134 135 static unsigned ID2SubY(uint32_t id) { 136 return (id >> (kSubShift + kSubShiftY)) & kSubMask; 137 } 138 139 static unsigned FixedToSub(SkFixed n) { 140 return (n >> (16 - kSubBits)) & kSubMask; 141 } 142 143 static SkFixed SubToFixed(unsigned sub) { 144 SkASSERT(sub <= kSubMask); 145 return sub << (16 - kSubBits); 146 } 147 148 static uint32_t MakeID(unsigned code) { 149 return code; 150 } 151 152 static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) { 153 SkASSERT(code <= kCodeMask); 154 x = FixedToSub(x); 155 y = FixedToSub(y); 156 return (x << (kSubShift + kSubShiftX)) | 157 (y << (kSubShift + kSubShiftY)) | 158 code; 159 } 160 161 void toMask(SkMask* mask) const; 162}; 163 164class SkScalerContext { 165public: 166 enum Flags { 167 kFrameAndFill_Flag = 0x0001, 168 kDevKernText_Flag = 0x0002, 169 kEmbeddedBitmapText_Flag = 0x0004, 170 kEmbolden_Flag = 0x0008, 171 kSubpixelPositioning_Flag = 0x0010, 172 kAutohinting_Flag = 0x0020, 173 kVertical_Flag = 0x0040, 174 175 // together, these two flags resulting in a two bit value which matches 176 // up with the SkPaint::Hinting enum. 177 kHinting_Shift = 7, // to shift into the other flags above 178 kHintingBit1_Flag = 0x0080, 179 kHintingBit2_Flag = 0x0100, 180 181 // these should only ever be set if fMaskFormat is LCD16 or LCD32 182 kLCD_Vertical_Flag = 0x0200, // else Horizontal 183 kLCD_BGROrder_Flag = 0x0400, // else RGB order 184 185 // Generate A8 from LCD source (for GDI), only meaningful if fMaskFormat is kA8 186 // Perhaps we can store this (instead) in fMaskFormat, in hight bit? 187 kGenA8FromLCD_Flag = 0x0800, 188 189#ifdef SK_USE_COLOR_LUMINANCE 190 kLuminance_Bits = 3, 191#else 192 // luminance : 0 for black text, kLuminance_Max for white text 193 kLuminance_Shift = 13, // shift to land in the high 3-bits of Flags 194 kLuminance_Bits = 3, // ensure Flags doesn't exceed 16bits 195#endif 196 }; 197 198 // computed values 199 enum { 200 kHinting_Mask = kHintingBit1_Flag | kHintingBit2_Flag, 201#ifdef SK_USE_COLOR_LUMINANCE 202#else 203 kLuminance_Max = (1 << kLuminance_Bits) - 1, 204 kLuminance_Mask = kLuminance_Max << kLuminance_Shift, 205#endif 206 }; 207 208 struct Rec { 209 uint32_t fOrigFontID; 210 uint32_t fFontID; 211 SkScalar fTextSize, fPreScaleX, fPreSkewX; 212 SkScalar fPost2x2[2][2]; 213 SkScalar fFrameWidth, fMiterLimit; 214#ifdef SK_USE_COLOR_LUMINANCE 215 uint32_t fLumBits; 216#endif 217#ifdef SK_BUILD_FOR_ANDROID 218 SkLanguage fLanguage; 219 SkPaint::FontVariant fFontVariant; 220#endif 221 uint8_t fMaskFormat; 222 uint8_t fStrokeJoin; 223 uint16_t fFlags; 224 // Warning: when adding members note that the size of this structure 225 // must be a multiple of 4. SkDescriptor requires that its arguments be 226 // multiples of four and this structure is put in an SkDescriptor in 227 // SkPaint::MakeRec. 228 229 void getMatrixFrom2x2(SkMatrix*) const; 230 void getLocalMatrix(SkMatrix*) const; 231 void getSingleMatrix(SkMatrix*) const; 232 233 SkPaint::Hinting getHinting() const { 234 unsigned hint = (fFlags & kHinting_Mask) >> kHinting_Shift; 235 return static_cast<SkPaint::Hinting>(hint); 236 } 237 238 void setHinting(SkPaint::Hinting hinting) { 239 fFlags = (fFlags & ~kHinting_Mask) | (hinting << kHinting_Shift); 240 } 241 242 SkMask::Format getFormat() const { 243 return static_cast<SkMask::Format>(fMaskFormat); 244 } 245#ifdef SK_USE_COLOR_LUMINANCE 246 SkColor getLuminanceColor() const { 247 return fLumBits; 248 } 249 250 void setLuminanceColor(SkColor c) { 251 fLumBits = c; 252 } 253#else 254 unsigned getLuminanceBits() const { 255 return (fFlags & kLuminance_Mask) >> kLuminance_Shift; 256 } 257 258 void setLuminanceBits(unsigned lum) { 259 SkASSERT(lum <= kLuminance_Max); 260 fFlags = (fFlags & ~kLuminance_Mask) | (lum << kLuminance_Shift); 261 } 262 263 U8CPU getLuminanceByte() const { 264 SkASSERT(3 == kLuminance_Bits); 265 unsigned lum = this->getLuminanceBits(); 266 lum |= (lum << kLuminance_Bits); 267 lum |= (lum << kLuminance_Bits*2); 268 return lum >> (4*kLuminance_Bits - 8); 269 } 270#endif 271 }; 272 273 SkScalerContext(const SkDescriptor* desc); 274 virtual ~SkScalerContext(); 275 276 SkMask::Format getMaskFormat() const { 277 return (SkMask::Format)fRec.fMaskFormat; 278 } 279 280 bool isSubpixel() const { 281 return SkToBool(fRec.fFlags & kSubpixelPositioning_Flag); 282 } 283 284 // remember our glyph offset/base 285 void setBaseGlyphCount(unsigned baseGlyphCount) { 286 fBaseGlyphCount = baseGlyphCount; 287 } 288 289 /** Return the corresponding glyph for the specified unichar. Since contexts 290 may be chained (under the hood), the glyphID that is returned may in 291 fact correspond to a different font/context. In that case, we use the 292 base-glyph-count to know how to translate back into local glyph space. 293 */ 294 uint16_t charToGlyphID(SkUnichar uni); 295 296 /** Map the glyphID to its glyph index, and then to its char code. Unmapped 297 glyphs return zero. 298 */ 299 SkUnichar glyphIDToChar(uint16_t glyphID); 300 301 unsigned getGlyphCount() { return this->generateGlyphCount(); } 302 void getAdvance(SkGlyph*); 303 void getMetrics(SkGlyph*); 304 void getImage(const SkGlyph&); 305 void getPath(const SkGlyph&, SkPath*); 306 void getFontMetrics(SkPaint::FontMetrics* mX, 307 SkPaint::FontMetrics* mY); 308 309#ifdef SK_BUILD_FOR_ANDROID 310 // This function must be public for SkTypeface_android.h, but should not be 311 // called by other callers 312 SkFontID findTypefaceIdForChar(SkUnichar uni); 313 314 unsigned getBaseGlyphCount(SkUnichar charCode); 315#endif 316 317 static inline void MakeRec(const SkPaint&, const SkMatrix*, Rec* rec); 318 static inline void PostMakeRec(Rec*); 319 320 static SkScalerContext* Create(const SkDescriptor*); 321 322protected: 323 Rec fRec; 324 unsigned fBaseGlyphCount; 325 326 virtual unsigned generateGlyphCount() = 0; 327 virtual uint16_t generateCharToGlyph(SkUnichar) = 0; 328 virtual void generateAdvance(SkGlyph*) = 0; 329 virtual void generateMetrics(SkGlyph*) = 0; 330 virtual void generateImage(const SkGlyph&) = 0; 331 virtual void generatePath(const SkGlyph&, SkPath*) = 0; 332 virtual void generateFontMetrics(SkPaint::FontMetrics* mX, 333 SkPaint::FontMetrics* mY) = 0; 334 // default impl returns 0, indicating failure. 335 virtual SkUnichar generateGlyphToChar(uint16_t); 336 337 void forceGenerateImageFromPath() { fGenerateImageFromPath = true; } 338 339private: 340 SkScalerContext* getContextFromChar(SkUnichar uni, unsigned& glyphID); 341 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