2 * Copyright 2006 The Android Open Source Project
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef SkScalerContext_DEFINED
9 #define SkScalerContext_DEFINED
12 #include "SkMaskGamma.h"
15 #include "SkTypeface.h"
24 * To allow this to be forward-declared, it must be its own typename, rather
25 * than a nested struct inside SkScalerContext (where it started).
27 struct SkScalerContextRec {
29 SkScalar fTextSize, fPreScaleX, fPreSkewX;
30 SkScalar fPost2x2[2][2];
31 SkScalar fFrameWidth, fMiterLimit;
33 //These describe the parameters to create (uniquely identify) the pre-blend.
35 uint8_t fDeviceGamma; //2.6, (0.0, 4.0) gamma, 0.0 for sRGB
36 uint8_t fPaintGamma; //2.6, (0.0, 4.0) gamma, 0.0 for sRGB
37 uint8_t fContrast; //0.8+1, [0.0, 1.0] artificial contrast
38 uint8_t fReservedAlign;
40 SkScalar getDeviceGamma() const {
41 return SkIntToScalar(fDeviceGamma) / (1 << 6);
43 void setDeviceGamma(SkScalar dg) {
44 SkASSERT(0 <= dg && dg < SkIntToScalar(4));
45 fDeviceGamma = SkScalarFloorToInt(dg * (1 << 6));
48 SkScalar getPaintGamma() const {
49 return SkIntToScalar(fPaintGamma) / (1 << 6);
51 void setPaintGamma(SkScalar pg) {
52 SkASSERT(0 <= pg && pg < SkIntToScalar(4));
53 fPaintGamma = SkScalarFloorToInt(pg * (1 << 6));
56 SkScalar getContrast() const {
57 return SkIntToScalar(fContrast) / ((1 << 8) - 1);
59 void setContrast(SkScalar c) {
60 SkASSERT(0 <= c && c <= SK_Scalar1);
61 fContrast = SkScalarRoundToInt(c * ((1 << 8) - 1));
65 * Causes the luminance color and contrast to be ignored, and the
66 * paint and device gamma to be effectively 1.0.
68 void ignorePreBlend() {
69 setLuminanceColor(SK_ColorTRANSPARENT);
70 setPaintGamma(SK_Scalar1);
71 setDeviceGamma(SK_Scalar1);
78 // Warning: when adding members note that the size of this structure
79 // must be a multiple of 4. SkDescriptor requires that its arguments be
80 // multiples of four and this structure is put in an SkDescriptor in
83 void getMatrixFrom2x2(SkMatrix*) const;
84 void getLocalMatrix(SkMatrix*) const;
85 void getSingleMatrix(SkMatrix*) const;
87 inline SkPaint::Hinting getHinting() const;
88 inline void setHinting(SkPaint::Hinting);
90 SkMask::Format getFormat() const {
91 return static_cast<SkMask::Format>(fMaskFormat);
94 SkColor getLuminanceColor() const {
98 void setLuminanceColor(SkColor c) {
103 //The following typedef hides from the rest of the implementation the number of
104 //most significant bits to consider when creating mask gamma tables. Two bits
105 //per channel was chosen as a balance between fidelity (more bits) and cache
106 //sizes (fewer bits). Three bits per channel was chosen when #303942; (used by
107 //the Chrome UI) turned out too green.
108 typedef SkTMaskGamma<3, 3, 3> SkMaskGamma;
110 class SkScalerContext {
112 typedef SkScalerContextRec Rec;
115 kFrameAndFill_Flag = 0x0001,
116 kDevKernText_Flag = 0x0002,
117 kEmbeddedBitmapText_Flag = 0x0004,
118 kEmbolden_Flag = 0x0008,
119 kSubpixelPositioning_Flag = 0x0010,
120 kForceAutohinting_Flag = 0x0020, // Use auto instead of bytcode hinting if hinting.
121 kVertical_Flag = 0x0040,
123 // together, these two flags resulting in a two bit value which matches
124 // up with the SkPaint::Hinting enum.
125 kHinting_Shift = 7, // to shift into the other flags above
126 kHintingBit1_Flag = 0x0080,
127 kHintingBit2_Flag = 0x0100,
129 // Pixel geometry information.
130 // only meaningful if fMaskFormat is LCD16 or LCD32
131 kLCD_Vertical_Flag = 0x0200, // else Horizontal
132 kLCD_BGROrder_Flag = 0x0400, // else RGB order
134 // Generate A8 from LCD source (for GDI and CoreGraphics).
135 // only meaningful if fMaskFormat is kA8
136 kGenA8FromLCD_Flag = 0x0800, // could be 0x200 (bit meaning dependent on fMaskFormat)
141 kHinting_Mask = kHintingBit1_Flag | kHintingBit2_Flag,
145 SkScalerContext(SkTypeface*, const SkDescriptor*);
146 virtual ~SkScalerContext();
148 SkTypeface* getTypeface() const { return fTypeface.get(); }
150 SkMask::Format getMaskFormat() const {
151 return (SkMask::Format)fRec.fMaskFormat;
154 bool isSubpixel() const {
155 return SkToBool(fRec.fFlags & kSubpixelPositioning_Flag);
158 bool isVertical() const {
159 return SkToBool(fRec.fFlags & kVertical_Flag);
162 /** Return the corresponding glyph for the specified unichar. Since contexts
163 may be chained (under the hood), the glyphID that is returned may in
164 fact correspond to a different font/context. In that case, we use the
165 base-glyph-count to know how to translate back into local glyph space.
167 uint16_t charToGlyphID(SkUnichar uni) {
168 return generateCharToGlyph(uni);
171 /** Map the glyphID to its glyph index, and then to its char code. Unmapped
174 SkUnichar glyphIDToChar(uint16_t glyphID) {
175 return (glyphID < getGlyphCount()) ? generateGlyphToChar(glyphID) : 0;
178 unsigned getGlyphCount() { return this->generateGlyphCount(); }
179 void getAdvance(SkGlyph*);
180 void getMetrics(SkGlyph*);
181 void getImage(const SkGlyph&);
182 void getPath(const SkGlyph&, SkPath*);
183 void getFontMetrics(SkPaint::FontMetrics*);
185 /** Return the size in bytes of the associated gamma lookup table
187 static size_t GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
188 int* width, int* height);
190 /** Get the associated gamma lookup table. The 'data' pointer must point to pre-allocated
191 memory, with size in bytes greater than or equal to the return value of getGammaLUTSize().
193 static void GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
196 static void MakeRec(const SkPaint&, const SkDeviceProperties* deviceProperties,
197 const SkMatrix*, Rec* rec);
198 static inline void PostMakeRec(const SkPaint&, Rec*);
200 static SkMaskGamma::PreBlend GetMaskPreBlend(const Rec& rec);
205 /** Generates the contents of glyph.fAdvanceX and glyph.fAdvanceY.
206 * May call getMetrics if that would be just as fast.
208 virtual void generateAdvance(SkGlyph* glyph) = 0;
210 /** Generates the contents of glyph.fWidth, fHeight, fTop, fLeft,
211 * as well as fAdvanceX and fAdvanceY if not already set.
213 * TODO: fMaskFormat is set by getMetrics later; cannot be set here.
215 virtual void generateMetrics(SkGlyph* glyph) = 0;
217 /** Generates the contents of glyph.fImage.
218 * When called, glyph.fImage will be pointing to a pre-allocated,
219 * uninitialized region of memory of size glyph.computeImageSize().
220 * This method may change glyph.fMaskFormat if the new image size is
221 * less than or equal to the old image size.
223 * Because glyph.computeImageSize() will determine the size of fImage,
224 * generateMetrics will be called before generateImage.
226 virtual void generateImage(const SkGlyph& glyph) = 0;
228 /** Sets the passed path to the glyph outline.
229 * If this cannot be done the path is set to empty;
230 * this is indistinguishable from a glyph with an empty path.
231 * This does not set glyph.fPath.
233 * TODO: path is always glyph.fPath, no reason to pass separately.
235 virtual void generatePath(const SkGlyph& glyph, SkPath* path) = 0;
237 /** Retrieves font metrics. */
238 virtual void generateFontMetrics(SkPaint::FontMetrics*) = 0;
240 /** Returns the number of glyphs in the font. */
241 virtual unsigned generateGlyphCount() = 0;
243 /** Returns the glyph id for the given unichar.
244 * If there is no 1:1 mapping from the unichar to a glyph id, returns 0.
246 virtual uint16_t generateCharToGlyph(SkUnichar unichar) = 0;
248 /** Returns the unichar for the given glyph id.
249 * If there is no 1:1 mapping from the glyph id to a unichar, returns 0.
250 * The default implementation always returns 0, indicating failure.
252 virtual SkUnichar generateGlyphToChar(uint16_t glyphId);
254 void forceGenerateImageFromPath() { fGenerateImageFromPath = true; }
258 SkAutoTUnref<SkTypeface> fTypeface;
260 // optional object, which may be null
261 SkPathEffect* fPathEffect;
262 SkMaskFilter* fMaskFilter;
263 SkRasterizer* fRasterizer;
265 // if this is set, we draw the image from a path, rather than
266 // calling generateImage.
267 bool fGenerateImageFromPath;
269 void internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
270 SkPath* devPath, SkMatrix* fillToDevMatrix);
272 // returns the right context from our link-list for this char. If no match
273 // is found it returns NULL. If a match is found then the glyphID param is
274 // set to the glyphID that maps to the provided char.
275 SkScalerContext* getContextFromChar(SkUnichar uni, uint16_t* glyphID);
277 // SkMaskGamma::PreBlend converts linear masks to gamma correcting masks.
279 // Visible to subclasses so that generateImage can apply the pre-blend directly.
280 const SkMaskGamma::PreBlend fPreBlend;
282 // When there is a filter, previous steps must create a linear mask
283 // and the pre-blend applied as a final step.
284 const SkMaskGamma::PreBlend fPreBlendForFilter;
287 #define kRec_SkDescriptorTag SkSetFourByteTag('s', 'r', 'e', 'c')
288 #define kPathEffect_SkDescriptorTag SkSetFourByteTag('p', 't', 'h', 'e')
289 #define kMaskFilter_SkDescriptorTag SkSetFourByteTag('m', 's', 'k', 'f')
290 #define kRasterizer_SkDescriptorTag SkSetFourByteTag('r', 'a', 's', 't')
292 ///////////////////////////////////////////////////////////////////////////////
294 enum SkAxisAlignment {
295 kNone_SkAxisAlignment,
301 * Return the axis (if any) that the baseline for horizontal text will land on
302 * after running through the specified matrix.
304 * As an example, the identity matrix will return kX_SkAxisAlignment
306 SkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix);
308 ///////////////////////////////////////////////////////////////////////////////
310 SkPaint::Hinting SkScalerContextRec::getHinting() const {
311 unsigned hint = (fFlags & SkScalerContext::kHinting_Mask) >>
312 SkScalerContext::kHinting_Shift;
313 return static_cast<SkPaint::Hinting>(hint);
316 void SkScalerContextRec::setHinting(SkPaint::Hinting hinting) {
317 fFlags = (fFlags & ~SkScalerContext::kHinting_Mask) |
318 (hinting << SkScalerContext::kHinting_Shift);