reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 1 | /* |
epoger@google.com | ec3ed6a | 2011-07-28 14:26:00 +0000 | [diff] [blame] | 2 | * Copyright 2006 The Android Open Source Project |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 3 | * |
epoger@google.com | ec3ed6a | 2011-07-28 14:26:00 +0000 | [diff] [blame] | 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 6 | */ |
| 7 | |
| 8 | #ifndef SkScalerContext_DEFINED |
| 9 | #define SkScalerContext_DEFINED |
| 10 | |
| 11 | #include "SkMask.h" |
| 12 | #include "SkMatrix.h" |
| 13 | #include "SkPaint.h" |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 14 | |
bungeman@google.com | 6e502fe | 2012-07-24 21:18:54 +0000 | [diff] [blame^] | 15 | #ifdef SK_BUILD_FOR_ANDROID |
| 16 | //For SkFontID |
| 17 | #include "SkTypeface.h" |
| 18 | #endif |
| 19 | |
reed@google.com | ce6dbb6 | 2012-02-10 22:01:45 +0000 | [diff] [blame] | 20 | //#define SK_USE_COLOR_LUMINANCE |
reed@google.com | ce6dbb6 | 2012-02-10 22:01:45 +0000 | [diff] [blame] | 21 | |
bungeman@google.com | bbe5013 | 2012-07-24 20:33:21 +0000 | [diff] [blame] | 22 | struct SkGlyph; |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 23 | class SkDescriptor; |
| 24 | class SkMaskFilter; |
| 25 | class SkPathEffect; |
| 26 | class SkRasterizer; |
| 27 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 28 | class SkScalerContext { |
| 29 | public: |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 30 | enum Flags { |
reed@google.com | b6bb5cb | 2011-11-21 19:32:29 +0000 | [diff] [blame] | 31 | kFrameAndFill_Flag = 0x0001, |
| 32 | kDevKernText_Flag = 0x0002, |
| 33 | kEmbeddedBitmapText_Flag = 0x0004, |
| 34 | kEmbolden_Flag = 0x0008, |
| 35 | kSubpixelPositioning_Flag = 0x0010, |
| 36 | kAutohinting_Flag = 0x0020, |
| 37 | kVertical_Flag = 0x0040, |
reed@google.com | ffe49f5 | 2011-11-22 19:42:41 +0000 | [diff] [blame] | 38 | |
agl@chromium.org | 309485b | 2009-07-21 17:41:32 +0000 | [diff] [blame] | 39 | // together, these two flags resulting in a two bit value which matches |
| 40 | // up with the SkPaint::Hinting enum. |
reed@google.com | ffe49f5 | 2011-11-22 19:42:41 +0000 | [diff] [blame] | 41 | kHinting_Shift = 7, // to shift into the other flags above |
reed@google.com | b6bb5cb | 2011-11-21 19:32:29 +0000 | [diff] [blame] | 42 | kHintingBit1_Flag = 0x0080, |
| 43 | kHintingBit2_Flag = 0x0100, |
reed@google.com | ffe49f5 | 2011-11-22 19:42:41 +0000 | [diff] [blame] | 44 | |
reed@google.com | effc501 | 2011-06-27 16:44:46 +0000 | [diff] [blame] | 45 | // these should only ever be set if fMaskFormat is LCD16 or LCD32 |
reed@google.com | b6bb5cb | 2011-11-21 19:32:29 +0000 | [diff] [blame] | 46 | kLCD_Vertical_Flag = 0x0200, // else Horizontal |
| 47 | kLCD_BGROrder_Flag = 0x0400, // else RGB order |
reed@google.com | ffe49f5 | 2011-11-22 19:42:41 +0000 | [diff] [blame] | 48 | |
reed@google.com | 8351aab | 2012-01-18 17:06:35 +0000 | [diff] [blame] | 49 | // Generate A8 from LCD source (for GDI), only meaningful if fMaskFormat is kA8 |
| 50 | // Perhaps we can store this (instead) in fMaskFormat, in hight bit? |
| 51 | kGenA8FromLCD_Flag = 0x0800, |
| 52 | |
reed@google.com | ce6dbb6 | 2012-02-10 22:01:45 +0000 | [diff] [blame] | 53 | #ifdef SK_USE_COLOR_LUMINANCE |
tomhudson@google.com | 1f90287 | 2012-06-01 13:15:47 +0000 | [diff] [blame] | 54 | kLuminance_Bits = 3 |
reed@google.com | e7a0a16 | 2012-02-07 21:25:33 +0000 | [diff] [blame] | 55 | #else |
reed@google.com | ffe49f5 | 2011-11-22 19:42:41 +0000 | [diff] [blame] | 56 | // luminance : 0 for black text, kLuminance_Max for white text |
reed@google.com | 8351aab | 2012-01-18 17:06:35 +0000 | [diff] [blame] | 57 | kLuminance_Shift = 13, // shift to land in the high 3-bits of Flags |
tomhudson@google.com | 1f90287 | 2012-06-01 13:15:47 +0000 | [diff] [blame] | 58 | kLuminance_Bits = 3 // ensure Flags doesn't exceed 16bits |
reed@google.com | e7a0a16 | 2012-02-07 21:25:33 +0000 | [diff] [blame] | 59 | #endif |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 60 | }; |
reed@google.com | ffe49f5 | 2011-11-22 19:42:41 +0000 | [diff] [blame] | 61 | |
| 62 | // computed values |
reed@android.com | e2ca207 | 2009-07-27 16:39:38 +0000 | [diff] [blame] | 63 | enum { |
reed@google.com | ffe49f5 | 2011-11-22 19:42:41 +0000 | [diff] [blame] | 64 | kHinting_Mask = kHintingBit1_Flag | kHintingBit2_Flag, |
reed@google.com | ce6dbb6 | 2012-02-10 22:01:45 +0000 | [diff] [blame] | 65 | #ifdef SK_USE_COLOR_LUMINANCE |
| 66 | #else |
reed@google.com | ffe49f5 | 2011-11-22 19:42:41 +0000 | [diff] [blame] | 67 | kLuminance_Max = (1 << kLuminance_Bits) - 1, |
tomhudson@google.com | 1f90287 | 2012-06-01 13:15:47 +0000 | [diff] [blame] | 68 | kLuminance_Mask = kLuminance_Max << kLuminance_Shift |
reed@google.com | e7a0a16 | 2012-02-07 21:25:33 +0000 | [diff] [blame] | 69 | #endif |
reed@android.com | e2ca207 | 2009-07-27 16:39:38 +0000 | [diff] [blame] | 70 | }; |
reed@google.com | ffe49f5 | 2011-11-22 19:42:41 +0000 | [diff] [blame] | 71 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 72 | struct Rec { |
reed@google.com | 7d26c59 | 2011-06-13 13:01:10 +0000 | [diff] [blame] | 73 | uint32_t fOrigFontID; |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 74 | uint32_t fFontID; |
| 75 | SkScalar fTextSize, fPreScaleX, fPreSkewX; |
| 76 | SkScalar fPost2x2[2][2]; |
| 77 | SkScalar fFrameWidth, fMiterLimit; |
reed@google.com | ce6dbb6 | 2012-02-10 22:01:45 +0000 | [diff] [blame] | 78 | #ifdef SK_USE_COLOR_LUMINANCE |
reed@google.com | e7a0a16 | 2012-02-07 21:25:33 +0000 | [diff] [blame] | 79 | uint32_t fLumBits; |
| 80 | #endif |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 81 | uint8_t fMaskFormat; |
| 82 | uint8_t fStrokeJoin; |
agl@chromium.org | a2c71cb | 2010-06-17 20:49:17 +0000 | [diff] [blame] | 83 | uint16_t fFlags; |
agl@chromium.org | 13c8558 | 2010-01-04 23:56:43 +0000 | [diff] [blame] | 84 | // Warning: when adding members note that the size of this structure |
| 85 | // must be a multiple of 4. SkDescriptor requires that its arguments be |
| 86 | // multiples of four and this structure is put in an SkDescriptor in |
| 87 | // SkPaint::MakeRec. |
agl@chromium.org | 309485b | 2009-07-21 17:41:32 +0000 | [diff] [blame] | 88 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 89 | void getMatrixFrom2x2(SkMatrix*) const; |
| 90 | void getLocalMatrix(SkMatrix*) const; |
| 91 | void getSingleMatrix(SkMatrix*) const; |
agl@chromium.org | 309485b | 2009-07-21 17:41:32 +0000 | [diff] [blame] | 92 | |
| 93 | SkPaint::Hinting getHinting() const { |
reed@google.com | ffe49f5 | 2011-11-22 19:42:41 +0000 | [diff] [blame] | 94 | unsigned hint = (fFlags & kHinting_Mask) >> kHinting_Shift; |
reed@google.com | f788feb | 2011-11-21 19:46:00 +0000 | [diff] [blame] | 95 | return static_cast<SkPaint::Hinting>(hint); |
agl@chromium.org | 309485b | 2009-07-21 17:41:32 +0000 | [diff] [blame] | 96 | } |
| 97 | |
| 98 | void setHinting(SkPaint::Hinting hinting) { |
reed@google.com | ffe49f5 | 2011-11-22 19:42:41 +0000 | [diff] [blame] | 99 | fFlags = (fFlags & ~kHinting_Mask) | (hinting << kHinting_Shift); |
| 100 | } |
reed@google.com | e7a0a16 | 2012-02-07 21:25:33 +0000 | [diff] [blame] | 101 | |
| 102 | SkMask::Format getFormat() const { |
| 103 | return static_cast<SkMask::Format>(fMaskFormat); |
| 104 | } |
| 105 | |
reed@google.com | ce6dbb6 | 2012-02-10 22:01:45 +0000 | [diff] [blame] | 106 | #ifdef SK_USE_COLOR_LUMINANCE |
reed@google.com | ce6dbb6 | 2012-02-10 22:01:45 +0000 | [diff] [blame] | 107 | SkColor getLuminanceColor() const { |
reed@google.com | e7a0a16 | 2012-02-07 21:25:33 +0000 | [diff] [blame] | 108 | return fLumBits; |
| 109 | } |
| 110 | |
reed@google.com | ce6dbb6 | 2012-02-10 22:01:45 +0000 | [diff] [blame] | 111 | void setLuminanceColor(SkColor c) { |
reed@google.com | ce6dbb6 | 2012-02-10 22:01:45 +0000 | [diff] [blame] | 112 | fLumBits = c; |
reed@google.com | e7a0a16 | 2012-02-07 21:25:33 +0000 | [diff] [blame] | 113 | } |
| 114 | #else |
reed@google.com | ffe49f5 | 2011-11-22 19:42:41 +0000 | [diff] [blame] | 115 | unsigned getLuminanceBits() const { |
| 116 | return (fFlags & kLuminance_Mask) >> kLuminance_Shift; |
| 117 | } |
| 118 | |
| 119 | void setLuminanceBits(unsigned lum) { |
| 120 | SkASSERT(lum <= kLuminance_Max); |
| 121 | fFlags = (fFlags & ~kLuminance_Mask) | (lum << kLuminance_Shift); |
| 122 | } |
| 123 | |
| 124 | U8CPU getLuminanceByte() const { |
| 125 | SkASSERT(3 == kLuminance_Bits); |
| 126 | unsigned lum = this->getLuminanceBits(); |
| 127 | lum |= (lum << kLuminance_Bits); |
| 128 | lum |= (lum << kLuminance_Bits*2); |
| 129 | return lum >> (4*kLuminance_Bits - 8); |
agl@chromium.org | 309485b | 2009-07-21 17:41:32 +0000 | [diff] [blame] | 130 | } |
reed@google.com | ce6dbb6 | 2012-02-10 22:01:45 +0000 | [diff] [blame] | 131 | #endif |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 132 | }; |
| 133 | |
| 134 | SkScalerContext(const SkDescriptor* desc); |
| 135 | virtual ~SkScalerContext(); |
| 136 | |
reed@google.com | 98539c6 | 2011-03-15 15:40:16 +0000 | [diff] [blame] | 137 | SkMask::Format getMaskFormat() const { |
| 138 | return (SkMask::Format)fRec.fMaskFormat; |
| 139 | } |
| 140 | |
reed@google.com | abf00aa | 2012-01-03 19:43:20 +0000 | [diff] [blame] | 141 | bool isSubpixel() const { |
| 142 | return SkToBool(fRec.fFlags & kSubpixelPositioning_Flag); |
| 143 | } |
| 144 | |
reed@android.com | a14ea0e | 2009-03-17 17:59:53 +0000 | [diff] [blame] | 145 | // remember our glyph offset/base |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 146 | void setBaseGlyphCount(unsigned baseGlyphCount) { |
| 147 | fBaseGlyphCount = baseGlyphCount; |
| 148 | } |
| 149 | |
reed@android.com | a14ea0e | 2009-03-17 17:59:53 +0000 | [diff] [blame] | 150 | /** Return the corresponding glyph for the specified unichar. Since contexts |
| 151 | may be chained (under the hood), the glyphID that is returned may in |
| 152 | fact correspond to a different font/context. In that case, we use the |
| 153 | base-glyph-count to know how to translate back into local glyph space. |
| 154 | */ |
reed@google.com | ffe49f5 | 2011-11-22 19:42:41 +0000 | [diff] [blame] | 155 | uint16_t charToGlyphID(SkUnichar uni); |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 156 | |
reed@android.com | 9d3a985 | 2010-01-08 14:07:42 +0000 | [diff] [blame] | 157 | /** Map the glyphID to its glyph index, and then to its char code. Unmapped |
| 158 | glyphs return zero. |
| 159 | */ |
| 160 | SkUnichar glyphIDToChar(uint16_t glyphID); |
| 161 | |
ctguil@chromium.org | 0bc7bf5 | 2011-03-04 19:04:57 +0000 | [diff] [blame] | 162 | unsigned getGlyphCount() { return this->generateGlyphCount(); } |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 163 | void getAdvance(SkGlyph*); |
| 164 | void getMetrics(SkGlyph*); |
| 165 | void getImage(const SkGlyph&); |
| 166 | void getPath(const SkGlyph&, SkPath*); |
| 167 | void getFontMetrics(SkPaint::FontMetrics* mX, |
| 168 | SkPaint::FontMetrics* mY); |
| 169 | |
djsollen@google.com | 60abb07 | 2012-02-15 18:49:15 +0000 | [diff] [blame] | 170 | #ifdef SK_BUILD_FOR_ANDROID |
| 171 | unsigned getBaseGlyphCount(SkUnichar charCode); |
djsollen@google.com | 15eeca0 | 2012-06-01 12:52:26 +0000 | [diff] [blame] | 172 | |
| 173 | // This function must be public for SkTypeface_android.h, but should not be |
| 174 | // called by other callers |
| 175 | SkFontID findTypefaceIdForChar(SkUnichar uni) { |
| 176 | SkScalerContext* ctx = this; |
| 177 | while (NULL != ctx) { |
| 178 | if (ctx->generateCharToGlyph(uni)) { |
| 179 | return ctx->fRec.fFontID; |
| 180 | } |
| 181 | ctx = ctx->getNextContext(); |
| 182 | } |
| 183 | return 0; |
| 184 | } |
djsollen@google.com | 60abb07 | 2012-02-15 18:49:15 +0000 | [diff] [blame] | 185 | #endif |
| 186 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 187 | static inline void MakeRec(const SkPaint&, const SkMatrix*, Rec* rec); |
reed@google.com | 10d2d4d | 2012-03-01 22:32:51 +0000 | [diff] [blame] | 188 | static inline void PostMakeRec(Rec*); |
| 189 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 190 | static SkScalerContext* Create(const SkDescriptor*); |
| 191 | |
| 192 | protected: |
| 193 | Rec fRec; |
| 194 | unsigned fBaseGlyphCount; |
| 195 | |
ctguil@chromium.org | 0bc7bf5 | 2011-03-04 19:04:57 +0000 | [diff] [blame] | 196 | virtual unsigned generateGlyphCount() = 0; |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 197 | virtual uint16_t generateCharToGlyph(SkUnichar) = 0; |
| 198 | virtual void generateAdvance(SkGlyph*) = 0; |
| 199 | virtual void generateMetrics(SkGlyph*) = 0; |
| 200 | virtual void generateImage(const SkGlyph&) = 0; |
| 201 | virtual void generatePath(const SkGlyph&, SkPath*) = 0; |
| 202 | virtual void generateFontMetrics(SkPaint::FontMetrics* mX, |
| 203 | SkPaint::FontMetrics* mY) = 0; |
reed@android.com | 9d3a985 | 2010-01-08 14:07:42 +0000 | [diff] [blame] | 204 | // default impl returns 0, indicating failure. |
| 205 | virtual SkUnichar generateGlyphToChar(uint16_t); |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 206 | |
reed@google.com | a767fa0 | 2011-08-05 21:40:26 +0000 | [diff] [blame] | 207 | void forceGenerateImageFromPath() { fGenerateImageFromPath = true; } |
| 208 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 209 | private: |
| 210 | SkPathEffect* fPathEffect; |
| 211 | SkMaskFilter* fMaskFilter; |
| 212 | SkRasterizer* fRasterizer; |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 213 | |
reed@google.com | a767fa0 | 2011-08-05 21:40:26 +0000 | [diff] [blame] | 214 | // if this is set, we draw the image from a path, rather than |
| 215 | // calling generateImage. |
| 216 | bool fGenerateImageFromPath; |
| 217 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 218 | void internalGetPath(const SkGlyph& glyph, SkPath* fillPath, |
| 219 | SkPath* devPath, SkMatrix* fillToDevMatrix); |
| 220 | |
reed@android.com | a14ea0e | 2009-03-17 17:59:53 +0000 | [diff] [blame] | 221 | // return the next context, treating fNextContext as a cache of the answer |
| 222 | SkScalerContext* getNextContext(); |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 223 | |
reed@android.com | a14ea0e | 2009-03-17 17:59:53 +0000 | [diff] [blame] | 224 | // returns the right context from our link-list for this glyph. If no match |
| 225 | // is found, just returns the original context (this) |
| 226 | SkScalerContext* getGlyphContext(const SkGlyph& glyph); |
| 227 | |
| 228 | // link-list of context, to handle missing chars. null-terminated. |
| 229 | SkScalerContext* fNextContext; |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 230 | }; |
| 231 | |
| 232 | #define kRec_SkDescriptorTag SkSetFourByteTag('s', 'r', 'e', 'c') |
| 233 | #define kPathEffect_SkDescriptorTag SkSetFourByteTag('p', 't', 'h', 'e') |
| 234 | #define kMaskFilter_SkDescriptorTag SkSetFourByteTag('m', 's', 'k', 'f') |
| 235 | #define kRasterizer_SkDescriptorTag SkSetFourByteTag('r', 'a', 's', 't') |
| 236 | |
reed@google.com | cb6ccdd | 2011-08-23 21:30:47 +0000 | [diff] [blame] | 237 | /////////////////////////////////////////////////////////////////////////////// |
| 238 | |
| 239 | enum SkAxisAlignment { |
| 240 | kNone_SkAxisAlignment, |
| 241 | kX_SkAxisAlignment, |
| 242 | kY_SkAxisAlignment |
| 243 | }; |
| 244 | |
| 245 | /** |
| 246 | * Return the axis (if any) that the baseline for horizontal text will land on |
| 247 | * after running through the specified matrix. |
| 248 | * |
| 249 | * As an example, the identity matrix will return kX_SkAxisAlignment |
| 250 | */ |
reed@google.com | 2e68478 | 2011-08-24 15:38:46 +0000 | [diff] [blame] | 251 | SkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix); |
reed@google.com | cb6ccdd | 2011-08-23 21:30:47 +0000 | [diff] [blame] | 252 | |
reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame] | 253 | #endif |
| 254 | |