Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkScalerContext.h
1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #ifndef SkScalerContext_DEFINED
9 #define SkScalerContext_DEFINED
10
11 #include "SkMask.h"
12 #include "SkMaskGamma.h"
13 #include "SkMatrix.h"
14 #include "SkPaint.h"
15 #include "SkTypeface.h"
16
17 struct SkGlyph;
18 class SkDescriptor;
19 class SkMaskFilter;
20 class SkPathEffect;
21 class SkRasterizer;
22
23 /*
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).
26  */
27 struct SkScalerContextRec {
28     uint32_t    fOrigFontID;
29     uint32_t    fFontID;
30     SkScalar    fTextSize, fPreScaleX, fPreSkewX;
31     SkScalar    fPost2x2[2][2];
32     SkScalar    fFrameWidth, fMiterLimit;
33
34     //These describe the parameters to create (uniquely identify) the pre-blend.
35     uint32_t    fLumBits;
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;
40
41     SkScalar getDeviceGamma() const {
42         return SkIntToScalar(fDeviceGamma) / (1 << 6);
43     }
44     void setDeviceGamma(SkScalar dg) {
45         SkASSERT(0 <= dg && dg < SkIntToScalar(4));
46         fDeviceGamma = SkScalarFloorToInt(dg * (1 << 6));
47     }
48
49     SkScalar getPaintGamma() const {
50         return SkIntToScalar(fPaintGamma) / (1 << 6);
51     }
52     void setPaintGamma(SkScalar pg) {
53         SkASSERT(0 <= pg && pg < SkIntToScalar(4));
54         fPaintGamma = SkScalarFloorToInt(pg * (1 << 6));
55     }
56
57     SkScalar getContrast() const {
58         return SkIntToScalar(fContrast) / ((1 << 8) - 1);
59     }
60     void setContrast(SkScalar c) {
61         SkASSERT(0 <= c && c <= SK_Scalar1);
62         fContrast = SkScalarRoundToInt(c * ((1 << 8) - 1));
63     }
64
65     /**
66      *  Causes the luminance color and contrast to be ignored, and the
67      *  paint and device gamma to be effectively 1.0.
68      */
69     void ignorePreBlend() {
70         setLuminanceColor(SK_ColorTRANSPARENT);
71         setPaintGamma(SK_Scalar1);
72         setDeviceGamma(SK_Scalar1);
73         setContrast(0);
74     }
75
76     uint8_t     fMaskFormat;
77     uint8_t     fStrokeJoin;
78     uint16_t    fFlags;
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
82     // SkPaint::MakeRec.
83
84     void    getMatrixFrom2x2(SkMatrix*) const;
85     void    getLocalMatrix(SkMatrix*) const;
86     void    getSingleMatrix(SkMatrix*) const;
87
88     inline SkPaint::Hinting getHinting() const;
89     inline void setHinting(SkPaint::Hinting);
90
91     SkMask::Format getFormat() const {
92         return static_cast<SkMask::Format>(fMaskFormat);
93     }
94
95     SkColor getLuminanceColor() const {
96         return fLumBits;
97     }
98
99     void setLuminanceColor(SkColor c) {
100         fLumBits = c;
101     }
102 };
103
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;
110
111 class SkScalerContext {
112 public:
113     typedef SkScalerContextRec Rec;
114
115     enum Flags {
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,
123
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,
129
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
134
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)
138     };
139
140     // computed values
141     enum {
142         kHinting_Mask   = kHintingBit1_Flag | kHintingBit2_Flag,
143     };
144
145
146     SkScalerContext(SkTypeface*, const SkDescriptor*);
147     virtual ~SkScalerContext();
148
149     SkTypeface* getTypeface() const { return fTypeface.get(); }
150
151     SkMask::Format getMaskFormat() const {
152         return (SkMask::Format)fRec.fMaskFormat;
153     }
154
155     bool isSubpixel() const {
156         return SkToBool(fRec.fFlags & kSubpixelPositioning_Flag);
157     }
158
159     bool isVertical() const {
160         return SkToBool(fRec.fFlags & kVertical_Flag);
161     }
162
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.
167      */
168     uint16_t charToGlyphID(SkUnichar uni) {
169         return generateCharToGlyph(uni);
170     }
171
172     /** Map the glyphID to its glyph index, and then to its char code. Unmapped
173         glyphs return zero.
174     */
175     SkUnichar glyphIDToChar(uint16_t glyphID) {
176         return (glyphID < getGlyphCount()) ? generateGlyphToChar(glyphID) : 0;
177     }
178
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*);
185
186     /** Return the size in bytes of the associated gamma lookup table
187      */
188     static size_t GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
189                                   int* width, int* height);
190
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().
193      */
194     static void   GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
195                                   void* data);
196
197     static void MakeRec(const SkPaint&, const SkDeviceProperties* deviceProperties,
198                         const SkMatrix*, Rec* rec);
199     static inline void PostMakeRec(const SkPaint&, Rec*);
200
201     static SkMaskGamma::PreBlend GetMaskPreBlend(const Rec& rec);
202
203 protected:
204     Rec         fRec;
205
206     /** Generates the contents of glyph.fAdvanceX and glyph.fAdvanceY.
207      *  May call getMetrics if that would be just as fast.
208      */
209     virtual void generateAdvance(SkGlyph* glyph) = 0;
210
211     /** Generates the contents of glyph.fWidth, fHeight, fTop, fLeft,
212      *  as well as fAdvanceX and fAdvanceY if not already set.
213      *
214      *  TODO: fMaskFormat is set by getMetrics later; cannot be set here.
215      */
216     virtual void generateMetrics(SkGlyph* glyph) = 0;
217
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.
223      *
224      *  Because glyph.computeImageSize() will determine the size of fImage,
225      *  generateMetrics will be called before generateImage.
226      */
227     virtual void generateImage(const SkGlyph& glyph) = 0;
228
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.
233      *
234      *  TODO: path is always glyph.fPath, no reason to pass separately.
235      */
236     virtual void generatePath(const SkGlyph& glyph, SkPath* path) = 0;
237
238     /** Retrieves font metrics. */
239     virtual void generateFontMetrics(SkPaint::FontMetrics*) = 0;
240
241     /** Returns the number of glyphs in the font. */
242     virtual unsigned generateGlyphCount() = 0;
243
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.
246      */
247     virtual uint16_t generateCharToGlyph(SkUnichar unichar) = 0;
248
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.
252      */
253     virtual SkUnichar generateGlyphToChar(uint16_t glyphId);
254
255     void forceGenerateImageFromPath() { fGenerateImageFromPath = true; }
256
257 private:
258     // never null
259     SkAutoTUnref<SkTypeface> fTypeface;
260
261     // optional object, which may be null
262     SkPathEffect*   fPathEffect;
263     SkMaskFilter*   fMaskFilter;
264     SkRasterizer*   fRasterizer;
265
266     // if this is set, we draw the image from a path, rather than
267     // calling generateImage.
268     bool fGenerateImageFromPath;
269
270     void internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
271                          SkPath* devPath, SkMatrix* fillToDevMatrix);
272
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);
277
278     // SkMaskGamma::PreBlend converts linear masks to gamma correcting masks.
279 protected:
280     // Visible to subclasses so that generateImage can apply the pre-blend directly.
281     const SkMaskGamma::PreBlend fPreBlend;
282 private:
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;
286 };
287
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')
292
293 ///////////////////////////////////////////////////////////////////////////////
294
295 enum SkAxisAlignment {
296     kNone_SkAxisAlignment,
297     kX_SkAxisAlignment,
298     kY_SkAxisAlignment
299 };
300
301 /**
302  *  Return the axis (if any) that the baseline for horizontal text will land on
303  *  after running through the specified matrix.
304  *
305  *  As an example, the identity matrix will return kX_SkAxisAlignment
306  */
307 SkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix);
308
309 ///////////////////////////////////////////////////////////////////////////////
310
311 SkPaint::Hinting SkScalerContextRec::getHinting() const {
312     unsigned hint = (fFlags & SkScalerContext::kHinting_Mask) >>
313                                             SkScalerContext::kHinting_Shift;
314     return static_cast<SkPaint::Hinting>(hint);
315 }
316
317 void SkScalerContextRec::setHinting(SkPaint::Hinting hinting) {
318     fFlags = (fFlags & ~SkScalerContext::kHinting_Mask) |
319                                 (hinting << SkScalerContext::kHinting_Shift);
320 }
321
322
323 #endif