• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     /** 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     };
158 private:
159     enum {
160         kHintingMask = kHintingBit1_Flag | kHintingBit2_Flag
161     };
162 public:
163     struct Rec {
164         uint32_t    fFontID;
165         SkScalar    fTextSize, fPreScaleX, fPreSkewX;
166         SkScalar    fPost2x2[2][2];
167         SkScalar    fFrameWidth, fMiterLimit;
168         bool        fSubpixelPositioning;
169         uint8_t     fMaskFormat;
170         uint8_t     fStrokeJoin;
171         uint8_t     fFlags;
172 
173         void    getMatrixFrom2x2(SkMatrix*) const;
174         void    getLocalMatrix(SkMatrix*) const;
175         void    getSingleMatrix(SkMatrix*) const;
176 
getHintingRec177         SkPaint::Hinting getHinting() const {
178             return static_cast<SkPaint::Hinting>((fFlags & kHintingMask) >> 4);
179         }
180 
setHintingRec181         void setHinting(SkPaint::Hinting hinting) {
182             fFlags = (fFlags & ~kHintingMask) | (hinting << 4);
183         }
184 
getFormatRec185         SkMask::Format getFormat() const {
186             return static_cast<SkMask::Format>(fMaskFormat);
187         }
188 
isLCDRec189         bool isLCD() const {
190             return SkMask::FormatIsLCD(this->getFormat());
191         }
192     };
193 
194     SkScalerContext(const SkDescriptor* desc);
195     virtual ~SkScalerContext();
196 
197     // remember our glyph offset/base
setBaseGlyphCount(unsigned baseGlyphCount)198     void setBaseGlyphCount(unsigned baseGlyphCount) {
199         fBaseGlyphCount = baseGlyphCount;
200     }
201 
202     /** Return the corresponding glyph for the specified unichar. Since contexts
203         may be chained (under the hood), the glyphID that is returned may in
204         fact correspond to a different font/context. In that case, we use the
205         base-glyph-count to know how to translate back into local glyph space.
206      */
207     uint16_t    charToGlyphID(SkUnichar uni);
208 
getGlyphCount()209     unsigned    getGlyphCount() const { return this->generateGlyphCount(); }
210     void        getAdvance(SkGlyph*);
211     void        getMetrics(SkGlyph*);
212     void        getImage(const SkGlyph&);
213     void        getPath(const SkGlyph&, SkPath*);
214     void        getFontMetrics(SkPaint::FontMetrics* mX,
215                                SkPaint::FontMetrics* mY);
216 
217     static inline void MakeRec(const SkPaint&, const SkMatrix*, Rec* rec);
218     static SkScalerContext* Create(const SkDescriptor*);
219 
220 protected:
221     Rec         fRec;
222     unsigned    fBaseGlyphCount;
223 
224     virtual unsigned generateGlyphCount() const = 0;
225     virtual uint16_t generateCharToGlyph(SkUnichar) = 0;
226     virtual void generateAdvance(SkGlyph*) = 0;
227     virtual void generateMetrics(SkGlyph*) = 0;
228     virtual void generateImage(const SkGlyph&) = 0;
229     virtual void generatePath(const SkGlyph&, SkPath*) = 0;
230     virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
231                                      SkPaint::FontMetrics* mY) = 0;
232 
233 private:
234     SkPathEffect*   fPathEffect;
235     SkMaskFilter*   fMaskFilter;
236     SkRasterizer*   fRasterizer;
237     SkScalar        fDevFrameWidth;
238 
239     void internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
240                          SkPath* devPath, SkMatrix* fillToDevMatrix);
241 
242     // return the next context, treating fNextContext as a cache of the answer
243     SkScalerContext* getNextContext();
244 
245     // returns the right context from our link-list for this glyph. If no match
246     // is found, just returns the original context (this)
247     SkScalerContext* getGlyphContext(const SkGlyph& glyph);
248 
249     // link-list of context, to handle missing chars. null-terminated.
250     SkScalerContext* fNextContext;
251 };
252 
253 #define kRec_SkDescriptorTag            SkSetFourByteTag('s', 'r', 'e', 'c')
254 #define kPathEffect_SkDescriptorTag     SkSetFourByteTag('p', 't', 'h', 'e')
255 #define kMaskFilter_SkDescriptorTag     SkSetFourByteTag('m', 's', 'k', 'f')
256 #define kRasterizer_SkDescriptorTag     SkSetFourByteTag('r', 'a', 's', 't')
257 
258 #endif
259 
260