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 rowBytesSkGlyph46 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 isJustAdvanceSkGlyph56 bool isJustAdvance() const { 57 return MASK_FORMAT_JUST_ADVANCE == fMaskFormat; 58 } 59 isFullMetricsSkGlyph60 bool isFullMetrics() const { 61 return MASK_FORMAT_JUST_ADVANCE != fMaskFormat; 62 } 63 getGlyphIDSkGlyph64 uint16_t getGlyphID() const { 65 return ID2Code(fID); 66 } 67 getGlyphIDSkGlyph68 unsigned getGlyphID(unsigned baseGlyphCount) const { 69 unsigned code = ID2Code(fID); 70 SkASSERT(code >= baseGlyphCount); 71 return code - baseGlyphCount; 72 } 73 getSubXSkGlyph74 unsigned getSubX() const { 75 return ID2SubX(fID); 76 } 77 getSubXFixedSkGlyph78 SkFixed getSubXFixed() const { 79 return SubToFixed(ID2SubX(fID)); 80 } 81 getSubYFixedSkGlyph82 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 ID2CodeSkGlyph104 static unsigned ID2Code(uint32_t id) { 105 return id & kCodeMask; 106 } 107 ID2SubXSkGlyph108 static unsigned ID2SubX(uint32_t id) { 109 return id >> (kSubShift + kSubShiftX); 110 } 111 ID2SubYSkGlyph112 static unsigned ID2SubY(uint32_t id) { 113 return (id >> (kSubShift + kSubShiftY)) & kSubMask; 114 } 115 FixedToSubSkGlyph116 static unsigned FixedToSub(SkFixed n) { 117 return (n >> (16 - kSubBits)) & kSubMask; 118 } 119 SubToFixedSkGlyph120 static SkFixed SubToFixed(unsigned sub) { 121 SkASSERT(sub <= kSubMask); 122 return sub << (16 - kSubBits); 123 } 124 MakeIDSkGlyph125 static uint32_t MakeID(unsigned code) { 126 return code; 127 } 128 MakeIDSkGlyph129 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 141 class SkScalerContext { 142 public: 143 enum Hints { 144 kNo_Hints, 145 kSubpixel_Hints, 146 kNormal_Hints 147 }; 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 }; 154 struct Rec { 155 uint32_t fFontID; 156 SkScalar fTextSize, fPreScaleX, fPreSkewX; 157 SkScalar fPost2x2[2][2]; 158 SkScalar fFrameWidth, fMiterLimit; 159 uint8_t fHints; 160 uint8_t fMaskFormat; 161 uint8_t fStrokeJoin; 162 uint8_t fFlags; 163 164 void getMatrixFrom2x2(SkMatrix*) const; 165 void getLocalMatrix(SkMatrix*) const; 166 void getSingleMatrix(SkMatrix*) const; 167 }; 168 169 SkScalerContext(const SkDescriptor* desc); 170 virtual ~SkScalerContext(); 171 172 // remember our glyph offset/base setBaseGlyphCount(unsigned baseGlyphCount)173 void setBaseGlyphCount(unsigned baseGlyphCount) { 174 fBaseGlyphCount = baseGlyphCount; 175 } 176 177 /** Return the corresponding glyph for the specified unichar. Since contexts 178 may be chained (under the hood), the glyphID that is returned may in 179 fact correspond to a different font/context. In that case, we use the 180 base-glyph-count to know how to translate back into local glyph space. 181 */ 182 uint16_t charToGlyphID(SkUnichar uni); 183 getGlyphCount()184 unsigned getGlyphCount() const { return this->generateGlyphCount(); } 185 void getAdvance(SkGlyph*); 186 void getMetrics(SkGlyph*); 187 void getImage(const SkGlyph&); 188 void getPath(const SkGlyph&, SkPath*); 189 void getFontMetrics(SkPaint::FontMetrics* mX, 190 SkPaint::FontMetrics* mY); 191 192 static inline void MakeRec(const SkPaint&, const SkMatrix*, Rec* rec); 193 static SkScalerContext* Create(const SkDescriptor*); 194 195 protected: 196 Rec fRec; 197 unsigned fBaseGlyphCount; 198 199 virtual unsigned generateGlyphCount() const = 0; 200 virtual uint16_t generateCharToGlyph(SkUnichar) = 0; 201 virtual void generateAdvance(SkGlyph*) = 0; 202 virtual void generateMetrics(SkGlyph*) = 0; 203 virtual void generateImage(const SkGlyph&) = 0; 204 virtual void generatePath(const SkGlyph&, SkPath*) = 0; 205 virtual void generateFontMetrics(SkPaint::FontMetrics* mX, 206 SkPaint::FontMetrics* mY) = 0; 207 208 private: 209 SkPathEffect* fPathEffect; 210 SkMaskFilter* fMaskFilter; 211 SkRasterizer* fRasterizer; 212 SkScalar fDevFrameWidth; 213 214 void internalGetPath(const SkGlyph& glyph, SkPath* fillPath, 215 SkPath* devPath, SkMatrix* fillToDevMatrix); 216 217 // return the next context, treating fNextContext as a cache of the answer 218 SkScalerContext* getNextContext(); 219 220 // returns the right context from our link-list for this glyph. If no match 221 // is found, just returns the original context (this) 222 SkScalerContext* getGlyphContext(const SkGlyph& glyph); 223 224 // link-list of context, to handle missing chars. null-terminated. 225 SkScalerContext* fNextContext; 226 }; 227 228 #define kRec_SkDescriptorTag SkSetFourByteTag('s', 'r', 'e', 'c') 229 #define kPathEffect_SkDescriptorTag SkSetFourByteTag('p', 't', 'h', 'e') 230 #define kMaskFilter_SkDescriptorTag SkSetFourByteTag('m', 's', 'k', 'f') 231 #define kRasterizer_SkDescriptorTag SkSetFourByteTag('r', 'a', 's', 't') 232 233 #endif 234 235