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 {
30 SkScalar fTextSize, fPreScaleX, fPreSkewX;
31 SkScalar fPost2x2[2][2];
32 SkScalar fFrameWidth, fMiterLimit;
34 //These describe the parameters to create (uniquely identify) the pre-blend.
36 uint8_t fDeviceGamma; //2.6, (0.0, 4.0) gamma, 0.0 for sRGB
37 uint8_t fPaintGamma; //2.6, (0.0, 4.0) gamma, 0.0 for sRGB
38 uint8_t fContrast; //0.8+1, [0.0, 1.0] artificial contrast
39 uint8_t fReservedAlign;
41 SkScalar getDeviceGamma() const {
42 return SkIntToScalar(fDeviceGamma) / (1 << 6);
44 void setDeviceGamma(SkScalar dg) {
45 SkASSERT(0 <= dg && dg < SkIntToScalar(4));
46 fDeviceGamma = SkScalarFloorToInt(dg * (1 << 6));
49 SkScalar getPaintGamma() const {
50 return SkIntToScalar(fPaintGamma) / (1 << 6);
52 void setPaintGamma(SkScalar pg) {
53 SkASSERT(0 <= pg && pg < SkIntToScalar(4));
54 fPaintGamma = SkScalarFloorToInt(pg * (1 << 6));
57 SkScalar getContrast() const {
58 return SkIntToScalar(fContrast) / ((1 << 8) - 1);
60 void setContrast(SkScalar c) {
61 SkASSERT(0 <= c && c <= SK_Scalar1);
62 fContrast = SkScalarRoundToInt(c * ((1 << 8) - 1));
66 * Causes the luminance color and contrast to be ignored, and the
67 * paint and device gamma to be effectively 1.0.
69 void ignorePreBlend() {
70 setLuminanceColor(SK_ColorTRANSPARENT);
71 setPaintGamma(SK_Scalar1);
72 setDeviceGamma(SK_Scalar1);
79 // Warning: when adding members note that the size of this structure
80 // must be a multiple of 4. SkDescriptor requires that its arguments be
81 // multiples of four and this structure is put in an SkDescriptor in
84 void getMatrixFrom2x2(SkMatrix*) const;
85 void getLocalMatrix(SkMatrix*) const;
86 void getSingleMatrix(SkMatrix*) const;
88 inline SkPaint::Hinting getHinting() const;
89 inline void setHinting(SkPaint::Hinting);
91 SkMask::Format getFormat() const {
92 return static_cast<SkMask::Format>(fMaskFormat);
95 SkColor getLuminanceColor() const {
99 void setLuminanceColor(SkColor c) {
104 //The following typedef hides from the rest of the implementation the number of
105 //most significant bits to consider when creating mask gamma tables. Two bits
106 //per channel was chosen as a balance between fidelity (more bits) and cache
107 //sizes (fewer bits). Three bits per channel was chosen when #303942; (used by
108 //the Chrome UI) turned out too green.
109 typedef SkTMaskGamma<3, 3, 3> SkMaskGamma;
111 class SkScalerContext {
113 typedef SkScalerContextRec Rec;
116 kFrameAndFill_Flag = 0x0001,
117 kDevKernText_Flag = 0x0002,
118 kEmbeddedBitmapText_Flag = 0x0004,
119 kEmbolden_Flag = 0x0008,
120 kSubpixelPositioning_Flag = 0x0010,
121 kForceAutohinting_Flag = 0x0020, // Use auto instead of bytcode hinting if hinting.
122 kVertical_Flag = 0x0040,
124 // together, these two flags resulting in a two bit value which matches
125 // up with the SkPaint::Hinting enum.
126 kHinting_Shift = 7, // to shift into the other flags above
127 kHintingBit1_Flag = 0x0080,
128 kHintingBit2_Flag = 0x0100,
130 // Pixel geometry information.
131 // only meaningful if fMaskFormat is LCD16 or LCD32
132 kLCD_Vertical_Flag = 0x0200, // else Horizontal
133 kLCD_BGROrder_Flag = 0x0400, // else RGB order
135 // Generate A8 from LCD source (for GDI and CoreGraphics).
136 // only meaningful if fMaskFormat is kA8
137 kGenA8FromLCD_Flag = 0x0800, // could be 0x200 (bit meaning dependent on fMaskFormat)
142 kHinting_Mask = kHintingBit1_Flag | kHintingBit2_Flag,
146 SkScalerContext(SkTypeface*, const SkDescriptor*);
147 virtual ~SkScalerContext();
149 SkTypeface* getTypeface() const { return fTypeface.get(); }
151 SkMask::Format getMaskFormat() const {
152 return (SkMask::Format)fRec.fMaskFormat;
155 bool isSubpixel() const {
156 return SkToBool(fRec.fFlags & kSubpixelPositioning_Flag);
159 bool isVertical() const {
160 return SkToBool(fRec.fFlags & kVertical_Flag);
163 /** Return the corresponding glyph for the specified unichar. Since contexts
164 may be chained (under the hood), the glyphID that is returned may in
165 fact correspond to a different font/context. In that case, we use the
166 base-glyph-count to know how to translate back into local glyph space.
168 uint16_t charToGlyphID(SkUnichar uni) {
169 return generateCharToGlyph(uni);
172 /** Map the glyphID to its glyph index, and then to its char code. Unmapped
175 SkUnichar glyphIDToChar(uint16_t glyphID) {
176 return (glyphID < getGlyphCount()) ? generateGlyphToChar(glyphID) : 0;
179 unsigned getGlyphCount() { return this->generateGlyphCount(); }
180 void getAdvance(SkGlyph*);
181 void getMetrics(SkGlyph*);
182 void getImage(const SkGlyph&);
183 void getPath(const SkGlyph&, SkPath*);
184 void getFontMetrics(SkPaint::FontMetrics*);
186 /** Return the size in bytes of the associated gamma lookup table
188 static size_t GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
189 int* width, int* height);
191 /** Get the associated gamma lookup table. The 'data' pointer must point to pre-allocated
192 memory, with size in bytes greater than or equal to the return value of getGammaLUTSize().
194 static void GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
197 static void MakeRec(const SkPaint&, const SkDeviceProperties* deviceProperties,
198 const SkMatrix*, Rec* rec);
199 static inline void PostMakeRec(const SkPaint&, Rec*);
201 static SkMaskGamma::PreBlend GetMaskPreBlend(const Rec& rec);
206 /** Generates the contents of glyph.fAdvanceX and glyph.fAdvanceY.
207 * May call getMetrics if that would be just as fast.
209 virtual void generateAdvance(SkGlyph* glyph) = 0;
211 /** Generates the contents of glyph.fWidth, fHeight, fTop, fLeft,
212 * as well as fAdvanceX and fAdvanceY if not already set.
214 * TODO: fMaskFormat is set by getMetrics later; cannot be set here.
216 virtual void generateMetrics(SkGlyph* glyph) = 0;
218 /** Generates the contents of glyph.fImage.
219 * When called, glyph.fImage will be pointing to a pre-allocated,
220 * uninitialized region of memory of size glyph.computeImageSize().
221 * This method may change glyph.fMaskFormat if the new image size is
222 * less than or equal to the old image size.
224 * Because glyph.computeImageSize() will determine the size of fImage,
225 * generateMetrics will be called before generateImage.
227 virtual void generateImage(const SkGlyph& glyph) = 0;
229 /** Sets the passed path to the glyph outline.
230 * If this cannot be done the path is set to empty;
231 * this is indistinguishable from a glyph with an empty path.
232 * This does not set glyph.fPath.
234 * TODO: path is always glyph.fPath, no reason to pass separately.
236 virtual void generatePath(const SkGlyph& glyph, SkPath* path) = 0;
238 /** Retrieves font metrics. */
239 virtual void generateFontMetrics(SkPaint::FontMetrics*) = 0;
241 /** Returns the number of glyphs in the font. */
242 virtual unsigned generateGlyphCount() = 0;
244 /** Returns the glyph id for the given unichar.
245 * If there is no 1:1 mapping from the unichar to a glyph id, returns 0.
247 virtual uint16_t generateCharToGlyph(SkUnichar unichar) = 0;
249 /** Returns the unichar for the given glyph id.
250 * If there is no 1:1 mapping from the glyph id to a unichar, returns 0.
251 * The default implementation always returns 0, indicating failure.
253 virtual SkUnichar generateGlyphToChar(uint16_t glyphId);
255 void forceGenerateImageFromPath() { fGenerateImageFromPath = true; }
259 SkAutoTUnref<SkTypeface> fTypeface;
261 // optional object, which may be null
262 SkPathEffect* fPathEffect;
263 SkMaskFilter* fMaskFilter;
264 SkRasterizer* fRasterizer;
266 // if this is set, we draw the image from a path, rather than
267 // calling generateImage.
268 bool fGenerateImageFromPath;
270 void internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
271 SkPath* devPath, SkMatrix* fillToDevMatrix);
273 // returns the right context from our link-list for this char. If no match
274 // is found it returns NULL. If a match is found then the glyphID param is
275 // set to the glyphID that maps to the provided char.
276 SkScalerContext* getContextFromChar(SkUnichar uni, uint16_t* glyphID);
278 // SkMaskGamma::PreBlend converts linear masks to gamma correcting masks.
280 // Visible to subclasses so that generateImage can apply the pre-blend directly.
281 const SkMaskGamma::PreBlend fPreBlend;
283 // When there is a filter, previous steps must create a linear mask
284 // and the pre-blend applied as a final step.
285 const SkMaskGamma::PreBlend fPreBlendForFilter;
288 #define kRec_SkDescriptorTag SkSetFourByteTag('s', 'r', 'e', 'c')
289 #define kPathEffect_SkDescriptorTag SkSetFourByteTag('p', 't', 'h', 'e')
290 #define kMaskFilter_SkDescriptorTag SkSetFourByteTag('m', 's', 'k', 'f')
291 #define kRasterizer_SkDescriptorTag SkSetFourByteTag('r', 'a', 's', 't')
293 ///////////////////////////////////////////////////////////////////////////////
295 enum SkAxisAlignment {
296 kNone_SkAxisAlignment,
302 * Return the axis (if any) that the baseline for horizontal text will land on
303 * after running through the specified matrix.
305 * As an example, the identity matrix will return kX_SkAxisAlignment
307 SkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix);
309 ///////////////////////////////////////////////////////////////////////////////
311 SkPaint::Hinting SkScalerContextRec::getHinting() const {
312 unsigned hint = (fFlags & SkScalerContext::kHinting_Mask) >>
313 SkScalerContext::kHinting_Shift;
314 return static_cast<SkPaint::Hinting>(hint);
317 void SkScalerContextRec::setHinting(SkPaint::Hinting hinting) {
318 fFlags = (fFlags & ~SkScalerContext::kHinting_Mask) |
319 (hinting << SkScalerContext::kHinting_Shift);