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_JUST_ADVANCE (0xFF) 33 34 struct SkGlyph { 35 void* fImage; 36 SkPath* fPath; 37 SkFixed fAdvanceX, fAdvanceY; 38 39 uint32_t fID; 40 uint16_t fWidth, fHeight; 41 int16_t fTop, fLeft; 42 43 uint8_t fMaskFormat; 44 int8_t fRsbDelta, fLsbDelta; // used by auto-kerning 45 46 unsigned rowBytes() const { 47 unsigned rb = fWidth; 48 if (SkMask::kBW_Format == fMaskFormat) { 49 rb = (rb + 7) >> 3; 50 } else { 51 rb = SkAlign4(rb); 52 } 53 return rb; 54 } 55 56 bool isJustAdvance() const { 57 return MASK_FORMAT_JUST_ADVANCE == fMaskFormat; 58 } 59 60 bool isFullMetrics() const { 61 return MASK_FORMAT_JUST_ADVANCE != fMaskFormat; 62 } 63 64 uint16_t getGlyphID() const { 65 return ID2Code(fID); 66 } 67 68 unsigned getGlyphID(unsigned baseGlyphCount) const { 69 unsigned code = ID2Code(fID); 70 SkASSERT(code >= baseGlyphCount); 71 return code - baseGlyphCount; 72 } 73 74 unsigned getSubX() const { 75 return ID2SubX(fID); 76 } 77 78 SkFixed getSubXFixed() const { 79 return SubToFixed(ID2SubX(fID)); 80 } 81 82 SkFixed getSubYFixed() const { 83 return SubToFixed(ID2SubY(fID)); 84 } 85 86 size_t computeImageSize() const; 87 88 /** Call this to set all of the metrics fields to 0 (e.g. if the scaler 89 encounters an error measuring a glyph). Note: this does not alter the 90 fImage, fPath, fID, fMaskFormat fields. 91 */ 92 void zeroMetrics(); 93 94 enum { 95 kSubBits = 2, 96 kSubMask = ((1 << kSubBits) - 1), 97 kSubShift = 24, // must be large enough for glyphs and unichars 98 kCodeMask = ((1 << kSubShift) - 1), 99 // relative offsets for X and Y subpixel bits 100 kSubShiftX = kSubBits, 101 kSubShiftY = 0 102 }; 103 104 static unsigned ID2Code(uint32_t id) { 105 return id & kCodeMask; 106 } 107 108 static unsigned ID2SubX(uint32_t id) { 109 return id >> (kSubShift + kSubShiftX); 110 } 111 112 static unsigned ID2SubY(uint32_t id) { 113 return (id >> (kSubShift + kSubShiftY)) & kSubMask; 114 } 115 116 static unsigned FixedToSub(SkFixed n) { 117 return (n >> (16 - kSubBits)) & kSubMask; 118 } 119 120 static SkFixed SubToFixed(unsigned sub) { 121 SkASSERT(sub <= kSubMask); 122 return sub << (16 - kSubBits); 123 } 124 125 static uint32_t MakeID(unsigned code) { 126 return code; 127 } 128 129 static uint32_t MakeID(unsigned code, SkFixed x, SkFixed y) { 130 SkASSERT(code <= kCodeMask); 131 x = FixedToSub(x); 132 y = FixedToSub(y); 133 return (x << (kSubShift + kSubShiftX)) | 134 (y << (kSubShift + kSubShiftY)) | 135 code; 136 } 137 138 void toMask(SkMask* mask) const; 139 140 /** Given a glyph which is has a mask format of LCD or VerticalLCD, take 141 the A8 plane in fImage and produce a valid LCD plane from it. 142 */ 143 void expandA8ToLCD() const; 144 }; 145 146 class SkScalerContext { 147 public: 148 enum Flags { 149 kFrameAndFill_Flag = 0x01, 150 kDevKernText_Flag = 0x02, 151 kGammaForBlack_Flag = 0x04, // illegal to set both Gamma flags 152 kGammaForWhite_Flag = 0x08, // illegal to set both Gamma flags 153 // together, these two flags resulting in a two bit value which matches 154 // up with the SkPaint::Hinting enum. 155 kHintingBit1_Flag = 0x10, 156 kHintingBit2_Flag = 0x20, 157 kEmbeddedBitmapText_Flag = 0x40, 158 kEmbolden_Flag = 0x80, 159 }; 160 private: 161 enum { 162 kHintingMask = kHintingBit1_Flag | kHintingBit2_Flag 163 }; 164 public: 165 struct Rec { 166 uint32_t fFontID; 167 SkScalar fTextSize, fPreScaleX, fPreSkewX; 168 SkScalar fPost2x2[2][2]; 169 SkScalar fFrameWidth, fMiterLimit; 170 bool fSubpixelPositioning; 171 uint8_t fMaskFormat; 172 uint8_t fStrokeJoin; 173 uint8_t fFlags; 174 // Warning: when adding members note that the size of this structure 175 // must be a multiple of 4. SkDescriptor requires that its arguments be 176 // multiples of four and this structure is put in an SkDescriptor in 177 // SkPaint::MakeRec. 178 179 void getMatrixFrom2x2(SkMatrix*) const; 180 void getLocalMatrix(SkMatrix*) const; 181 void getSingleMatrix(SkMatrix*) const; 182 183 SkPaint::Hinting getHinting() const { 184 return static_cast<SkPaint::Hinting>((fFlags & kHintingMask) >> 4); 185 } 186 187 void setHinting(SkPaint::Hinting hinting) { 188 fFlags = (fFlags & ~kHintingMask) | (hinting << 4); 189 } 190 191 SkMask::Format getFormat() const { 192 return static_cast<SkMask::Format>(fMaskFormat); 193 } 194 195 bool isLCD() const { 196 return SkMask::FormatIsLCD(this->getFormat()); 197 } 198 }; 199 200 SkScalerContext(const SkDescriptor* desc); 201 virtual ~SkScalerContext(); 202 203 // remember our glyph offset/base 204 void setBaseGlyphCount(unsigned baseGlyphCount) { 205 fBaseGlyphCount = baseGlyphCount; 206 } 207 208 /** Return the corresponding glyph for the specified unichar. Since contexts 209 may be chained (under the hood), the glyphID that is returned may in 210 fact correspond to a different font/context. In that case, we use the 211 base-glyph-count to know how to translate back into local glyph space. 212 */ 213 uint16_t charToGlyphID(SkUnichar uni); 214 215 /** Map the glyphID to its glyph index, and then to its char code. Unmapped 216 glyphs return zero. 217 */ 218 SkUnichar glyphIDToChar(uint16_t glyphID); 219 220 unsigned getGlyphCount() const { return this->generateGlyphCount(); } 221 void getAdvance(SkGlyph*); 222 void getMetrics(SkGlyph*); 223 void getImage(const SkGlyph&); 224 void getPath(const SkGlyph&, SkPath*); 225 void getFontMetrics(SkPaint::FontMetrics* mX, 226 SkPaint::FontMetrics* mY); 227 228 static inline void MakeRec(const SkPaint&, const SkMatrix*, Rec* rec); 229 static SkScalerContext* Create(const SkDescriptor*); 230 231 protected: 232 Rec fRec; 233 unsigned fBaseGlyphCount; 234 235 virtual unsigned generateGlyphCount() const = 0; 236 virtual uint16_t generateCharToGlyph(SkUnichar) = 0; 237 virtual void generateAdvance(SkGlyph*) = 0; 238 virtual void generateMetrics(SkGlyph*) = 0; 239 virtual void generateImage(const SkGlyph&) = 0; 240 virtual void generatePath(const SkGlyph&, SkPath*) = 0; 241 virtual void generateFontMetrics(SkPaint::FontMetrics* mX, 242 SkPaint::FontMetrics* mY) = 0; 243 // default impl returns 0, indicating failure. 244 virtual SkUnichar generateGlyphToChar(uint16_t); 245 246 private: 247 SkPathEffect* fPathEffect; 248 SkMaskFilter* fMaskFilter; 249 SkRasterizer* fRasterizer; 250 SkScalar fDevFrameWidth; 251 252 void internalGetPath(const SkGlyph& glyph, SkPath* fillPath, 253 SkPath* devPath, SkMatrix* fillToDevMatrix); 254 255 // return the next context, treating fNextContext as a cache of the answer 256 SkScalerContext* getNextContext(); 257 258 // returns the right context from our link-list for this glyph. If no match 259 // is found, just returns the original context (this) 260 SkScalerContext* getGlyphContext(const SkGlyph& glyph); 261 262 // link-list of context, to handle missing chars. null-terminated. 263 SkScalerContext* fNextContext; 264 }; 265 266 #define kRec_SkDescriptorTag SkSetFourByteTag('s', 'r', 'e', 'c') 267 #define kPathEffect_SkDescriptorTag SkSetFourByteTag('p', 't', 'h', 'e') 268 #define kMaskFilter_SkDescriptorTag SkSetFourByteTag('m', 's', 'k', 'f') 269 #define kRasterizer_SkDescriptorTag SkSetFourByteTag('r', 'a', 's', 't') 270 271 #endif 272 273