• 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 
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