Home | History | Annotate | Download | only in core
      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 SkPaint_DEFINED
      9 #define SkPaint_DEFINED
     10 
     11 #include "SkBlendMode.h"
     12 #include "SkColor.h"
     13 #include "SkFilterQuality.h"
     14 #include "SkMatrix.h"
     15 #include "SkRefCnt.h"
     16 
     17 class SkAutoDescriptor;
     18 class SkAutoGlyphCache;
     19 class SkColorFilter;
     20 class SkData;
     21 class SkDescriptor;
     22 class SkDrawLooper;
     23 class SkReadBuffer;
     24 class SkWriteBuffer;
     25 class SkGlyph;
     26 struct SkRect;
     27 class SkGlyphCache;
     28 class SkImageFilter;
     29 class SkMaskFilter;
     30 class SkPath;
     31 class SkPathEffect;
     32 struct SkPoint;
     33 class SkRasterizer;
     34 struct SkScalerContextEffects;
     35 class SkShader;
     36 class SkSurfaceProps;
     37 class SkTextBlob;
     38 class SkTypeface;
     39 
     40 /** \class SkPaint
     41 
     42     The SkPaint class holds the style and color information about how to draw
     43     geometries, text and bitmaps.
     44 */
     45 class SK_API SkPaint {
     46 public:
     47     SkPaint();
     48     SkPaint(const SkPaint& paint);
     49     SkPaint(SkPaint&& paint);
     50     ~SkPaint();
     51 
     52     SkPaint& operator=(const SkPaint& paint);
     53     SkPaint& operator=(SkPaint&& paint);
     54 
     55     /** operator== may give false negatives: two paints that draw equivalently
     56         may return false.  It will never give false positives: two paints that
     57         are not equivalent always return false.
     58     */
     59     // cc_unittests requires SK_API to make operator== visible
     60     SK_API friend bool operator==(const SkPaint& a, const SkPaint& b);
     61     friend bool operator!=(const SkPaint& a, const SkPaint& b) {
     62         return !(a == b);
     63     }
     64 
     65     /** getHash() is a shallow hash, with the same limitations as operator==.
     66      *  If operator== returns true for two paints, getHash() returns the same value for each.
     67      */
     68     uint32_t getHash() const;
     69 
     70     void flatten(SkWriteBuffer& buffer) const;
     71     void unflatten(SkReadBuffer& buffer);
     72 
     73     /** Restores the paint to its initial settings.
     74     */
     75     void reset();
     76 
     77     /** Specifies the level of hinting to be performed. These names are taken
     78         from the Gnome/Cairo names for the same. They are translated into
     79         Freetype concepts the same as in cairo-ft-font.c:
     80            kNo_Hinting     -> FT_LOAD_NO_HINTING
     81            kSlight_Hinting -> FT_LOAD_TARGET_LIGHT
     82            kNormal_Hinting -> <default, no option>
     83            kFull_Hinting   -> <same as kNormalHinting, unless we are rendering
     84                               subpixel glyphs, in which case TARGET_LCD or
     85                               TARGET_LCD_V is used>
     86     */
     87     enum Hinting {
     88         kNo_Hinting            = 0,
     89         kSlight_Hinting        = 1,
     90         kNormal_Hinting        = 2,     //!< this is the default
     91         kFull_Hinting          = 3
     92     };
     93 
     94     Hinting getHinting() const {
     95         return static_cast<Hinting>(fBitfields.fHinting);
     96     }
     97 
     98     void setHinting(Hinting hintingLevel);
     99 
    100     /** Specifies the bit values that are stored in the paint's flags.
    101     */
    102     enum Flags {
    103         kAntiAlias_Flag       = 0x01,   //!< mask to enable antialiasing
    104         kDither_Flag          = 0x04,   //!< mask to enable dithering. see setDither()
    105         kFakeBoldText_Flag    = 0x20,   //!< mask to enable fake-bold text
    106         kLinearText_Flag      = 0x40,   //!< mask to enable linear-text
    107         kSubpixelText_Flag    = 0x80,   //!< mask to enable subpixel text positioning
    108         kDevKernText_Flag     = 0x100,  //!< mask to enable device kerning text
    109         kLCDRenderText_Flag   = 0x200,  //!< mask to enable subpixel glyph renderering
    110         kEmbeddedBitmapText_Flag = 0x400, //!< mask to enable embedded bitmap strikes
    111         kAutoHinting_Flag     = 0x800,  //!< mask to force Freetype's autohinter
    112         kVerticalText_Flag    = 0x1000,
    113         kGenA8FromLCD_Flag    = 0x2000, // hack for GDI -- do not use if you can help it
    114         // when adding extra flags, note that the fFlags member is specified
    115         // with a bit-width and you'll have to expand it.
    116 
    117         kAllFlags = 0xFFFF,
    118     };
    119 
    120 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    121     enum ReserveFlags {
    122         // These are not used by paint, but the bits are reserved for private use by the
    123         // android framework.
    124         kUnderlineText_ReserveFlag   = 0x08,   //!< mask to enable underline text
    125         kStrikeThruText_ReserveFlag  = 0x10,   //!< mask to enable strike-thru text
    126     };
    127 #endif
    128 
    129     /** Return the paint's flags. Use the Flag enum to test flag values.
    130         @return the paint's flags (see enums ending in _Flag for bit masks)
    131     */
    132     uint32_t getFlags() const { return fBitfields.fFlags; }
    133 
    134     /** Set the paint's flags. Use the Flag enum to specific flag values.
    135         @param flags    The new flag bits for the paint (see Flags enum)
    136     */
    137     void setFlags(uint32_t flags);
    138 
    139     /** Helper for getFlags(), returning true if kAntiAlias_Flag bit is set
    140         @return true if the antialias bit is set in the paint's flags.
    141         */
    142     bool isAntiAlias() const {
    143         return SkToBool(this->getFlags() & kAntiAlias_Flag);
    144     }
    145 
    146     /** Helper for setFlags(), setting or clearing the kAntiAlias_Flag bit
    147         @param aa   true to enable antialiasing, false to disable it
    148         */
    149     void setAntiAlias(bool aa);
    150 
    151     /** Helper for getFlags(), returning true if kDither_Flag bit is set
    152         @return true if the dithering bit is set in the paint's flags.
    153         */
    154     bool isDither() const {
    155         return SkToBool(this->getFlags() & kDither_Flag);
    156     }
    157 
    158     /**
    159      *  Helper for setFlags(), setting or clearing the kDither_Flag bit
    160      *  @param dither   true to enable dithering, false to disable it
    161      *
    162      *  Note: gradients ignore this setting and always dither.
    163      */
    164     void setDither(bool dither);
    165 
    166     /** Helper for getFlags(), returning true if kLinearText_Flag bit is set
    167         @return true if the lineartext bit is set in the paint's flags
    168     */
    169     bool isLinearText() const {
    170         return SkToBool(this->getFlags() & kLinearText_Flag);
    171     }
    172 
    173     /** Helper for setFlags(), setting or clearing the kLinearText_Flag bit
    174         @param linearText true to set the linearText bit in the paint's flags,
    175                           false to clear it.
    176     */
    177     void setLinearText(bool linearText);
    178 
    179     /** Helper for getFlags(), returning true if kSubpixelText_Flag bit is set
    180         @return true if the lineartext bit is set in the paint's flags
    181     */
    182     bool isSubpixelText() const {
    183         return SkToBool(this->getFlags() & kSubpixelText_Flag);
    184     }
    185 
    186     /**
    187      *  Helper for setFlags(), setting or clearing the kSubpixelText_Flag.
    188      *  @param subpixelText true to set the subpixelText bit in the paint's
    189      *                      flags, false to clear it.
    190      */
    191     void setSubpixelText(bool subpixelText);
    192 
    193     bool isLCDRenderText() const {
    194         return SkToBool(this->getFlags() & kLCDRenderText_Flag);
    195     }
    196 
    197     /**
    198      *  Helper for setFlags(), setting or clearing the kLCDRenderText_Flag.
    199      *  Note: antialiasing must also be on for lcd rendering
    200      *  @param lcdText true to set the LCDRenderText bit in the paint's flags,
    201      *                 false to clear it.
    202      */
    203     void setLCDRenderText(bool lcdText);
    204 
    205     bool isEmbeddedBitmapText() const {
    206         return SkToBool(this->getFlags() & kEmbeddedBitmapText_Flag);
    207     }
    208 
    209     /** Helper for setFlags(), setting or clearing the kEmbeddedBitmapText_Flag bit
    210         @param useEmbeddedBitmapText true to set the kEmbeddedBitmapText bit in the paint's flags,
    211                                      false to clear it.
    212     */
    213     void setEmbeddedBitmapText(bool useEmbeddedBitmapText);
    214 
    215     bool isAutohinted() const {
    216         return SkToBool(this->getFlags() & kAutoHinting_Flag);
    217     }
    218 
    219     /** Helper for setFlags(), setting or clearing the kAutoHinting_Flag bit
    220         @param useAutohinter true to set the kEmbeddedBitmapText bit in the
    221                                   paint's flags,
    222                              false to clear it.
    223     */
    224     void setAutohinted(bool useAutohinter);
    225 
    226     bool isVerticalText() const {
    227         return SkToBool(this->getFlags() & kVerticalText_Flag);
    228     }
    229 
    230     /**
    231      *  Helper for setting or clearing the kVerticalText_Flag bit in
    232      *  setFlags(...).
    233      *
    234      *  If this bit is set, then advances are treated as Y values rather than
    235      *  X values, and drawText will places its glyphs vertically rather than
    236      *  horizontally.
    237      */
    238     void setVerticalText(bool verticalText);
    239 
    240     /** Helper for getFlags(), returns true if kFakeBoldText_Flag bit is set
    241         @return true if the kFakeBoldText_Flag bit is set in the paint's flags.
    242     */
    243     bool isFakeBoldText() const {
    244         return SkToBool(this->getFlags() & kFakeBoldText_Flag);
    245     }
    246 
    247     /** Helper for setFlags(), setting or clearing the kFakeBoldText_Flag bit
    248         @param fakeBoldText true to set the kFakeBoldText_Flag bit in the paint's
    249                             flags, false to clear it.
    250     */
    251     void setFakeBoldText(bool fakeBoldText);
    252 
    253     /** Helper for getFlags(), returns true if kDevKernText_Flag bit is set
    254         @return true if the kernText bit is set in the paint's flags.
    255     */
    256     bool isDevKernText() const {
    257         return SkToBool(this->getFlags() & kDevKernText_Flag);
    258     }
    259 
    260     /** Helper for setFlags(), setting or clearing the kKernText_Flag bit
    261         @param kernText true to set the kKernText_Flag bit in the paint's
    262                             flags, false to clear it.
    263     */
    264     void setDevKernText(bool devKernText);
    265 
    266     /**
    267      *  Return the filter level. This affects the quality (and performance) of
    268      *  drawing scaled images.
    269      */
    270     SkFilterQuality getFilterQuality() const {
    271         return (SkFilterQuality)fBitfields.fFilterQuality;
    272     }
    273 
    274     /**
    275      *  Set the filter quality. This affects the quality (and performance) of
    276      *  drawing scaled images.
    277      */
    278     void setFilterQuality(SkFilterQuality quality);
    279 
    280     /** Styles apply to rect, oval, path, and text.
    281         Bitmaps are always drawn in "fill", and lines are always drawn in
    282         "stroke".
    283 
    284         Note: strokeandfill implicitly draws the result with
    285         SkPath::kWinding_FillType, so if the original path is even-odd, the
    286         results may not appear the same as if it was drawn twice, filled and
    287         then stroked.
    288     */
    289     enum Style {
    290         kFill_Style,            //!< fill the geometry
    291         kStroke_Style,          //!< stroke the geometry
    292         kStrokeAndFill_Style,   //!< fill and stroke the geometry
    293     };
    294     enum {
    295         kStyleCount = kStrokeAndFill_Style + 1
    296     };
    297 
    298     /** Return the paint's style, used for controlling how primitives'
    299         geometries are interpreted (except for drawBitmap, which always assumes
    300         kFill_Style).
    301         @return the paint's Style
    302     */
    303     Style getStyle() const { return (Style)fBitfields.fStyle; }
    304 
    305     /** Set the paint's style, used for controlling how primitives'
    306         geometries are interpreted (except for drawBitmap, which always assumes
    307         Fill).
    308         @param style    The new style to set in the paint
    309     */
    310     void setStyle(Style style);
    311 
    312     /** Return the paint's color. Note that the color is a 32bit value
    313         containing alpha as well as r,g,b. This 32bit value is not
    314         premultiplied, meaning that its alpha can be any value, regardless of
    315         the values of r,g,b.
    316         @return the paint's color (and alpha).
    317     */
    318     SkColor getColor() const { return fColor; }
    319 
    320     /** Set the paint's color. Note that the color is a 32bit value containing
    321         alpha as well as r,g,b. This 32bit value is not premultiplied, meaning
    322         that its alpha can be any value, regardless of the values of r,g,b.
    323         @param color    The new color (including alpha) to set in the paint.
    324     */
    325     void setColor(SkColor color);
    326 
    327     /** Helper to getColor() that just returns the color's alpha value.
    328         @return the alpha component of the paint's color.
    329         */
    330     uint8_t getAlpha() const { return SkToU8(SkColorGetA(fColor)); }
    331 
    332     /** Helper to setColor(), that only assigns the color's alpha value,
    333         leaving its r,g,b values unchanged.
    334         @param a    set the alpha component (0..255) of the paint's color.
    335     */
    336     void setAlpha(U8CPU a);
    337 
    338     /** Helper to setColor(), that takes a,r,g,b and constructs the color value
    339         using SkColorSetARGB()
    340         @param a    The new alpha component (0..255) of the paint's color.
    341         @param r    The new red component (0..255) of the paint's color.
    342         @param g    The new green component (0..255) of the paint's color.
    343         @param b    The new blue component (0..255) of the paint's color.
    344     */
    345     void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
    346 
    347     /** Return the width for stroking.
    348         <p />
    349         A value of 0 strokes in hairline mode.
    350         Hairlines always draw 1-pixel wide, regardless of the matrix.
    351         @return the paint's stroke width, used whenever the paint's style is
    352                 Stroke or StrokeAndFill.
    353     */
    354     SkScalar getStrokeWidth() const { return fWidth; }
    355 
    356     /** Set the width for stroking.
    357         Pass 0 to stroke in hairline mode.
    358         Hairlines always draw 1-pixel wide, regardless of the matrix.
    359         @param width set the paint's stroke width, used whenever the paint's
    360                      style is Stroke or StrokeAndFill.
    361     */
    362     void setStrokeWidth(SkScalar width);
    363 
    364     /** Return the paint's stroke miter value. This is used to control the
    365         behavior of miter joins when the joins angle is sharp.
    366         @return the paint's miter limit, used whenever the paint's style is
    367                 Stroke or StrokeAndFill.
    368     */
    369     SkScalar getStrokeMiter() const { return fMiterLimit; }
    370 
    371     /** Set the paint's stroke miter value. This is used to control the
    372         behavior of miter joins when the joins angle is sharp. This value must
    373         be >= 0.
    374         @param miter    set the miter limit on the paint, used whenever the
    375                         paint's style is Stroke or StrokeAndFill.
    376     */
    377     void setStrokeMiter(SkScalar miter);
    378 
    379     /** Cap enum specifies the settings for the paint's strokecap. This is the
    380         treatment that is applied to the beginning and end of each non-closed
    381         contour (e.g. lines).
    382 
    383         If the cap is round or square, the caps are drawn when the contour has
    384         a zero length. Zero length contours can be created by following moveTo
    385         with a lineTo at the same point, or a moveTo followed by a close.
    386 
    387         A dash with an on interval of zero also creates a zero length contour.
    388 
    389         The zero length contour draws the square cap without rotation, since
    390         the no direction can be inferred.
    391     */
    392     enum Cap {
    393         kButt_Cap,      //!< begin/end contours with no extension
    394         kRound_Cap,     //!< begin/end contours with a semi-circle extension
    395         kSquare_Cap,    //!< begin/end contours with a half square extension
    396 
    397         kLast_Cap = kSquare_Cap,
    398         kDefault_Cap = kButt_Cap
    399     };
    400     static constexpr int kCapCount = kLast_Cap + 1;
    401 
    402     /** Join enum specifies the settings for the paint's strokejoin. This is
    403         the treatment that is applied to corners in paths and rectangles.
    404     */
    405     enum Join {
    406         kMiter_Join,    //!< connect path segments with a sharp join
    407         kRound_Join,    //!< connect path segments with a round join
    408         kBevel_Join,    //!< connect path segments with a flat bevel join
    409 
    410         kLast_Join = kBevel_Join,
    411         kDefault_Join = kMiter_Join
    412     };
    413     static constexpr int kJoinCount = kLast_Join + 1;
    414 
    415     /** Return the paint's stroke cap type, controlling how the start and end
    416         of stroked lines and paths are treated.
    417         @return the line cap style for the paint, used whenever the paint's
    418                 style is Stroke or StrokeAndFill.
    419     */
    420     Cap getStrokeCap() const { return (Cap)fBitfields.fCapType; }
    421 
    422     /** Set the paint's stroke cap type.
    423         @param cap  set the paint's line cap style, used whenever the paint's
    424                     style is Stroke or StrokeAndFill.
    425     */
    426     void setStrokeCap(Cap cap);
    427 
    428     /** Return the paint's stroke join type.
    429         @return the paint's line join style, used whenever the paint's style is
    430                 Stroke or StrokeAndFill.
    431     */
    432     Join getStrokeJoin() const { return (Join)fBitfields.fJoinType; }
    433 
    434     /** Set the paint's stroke join type.
    435         @param join set the paint's line join style, used whenever the paint's
    436                     style is Stroke or StrokeAndFill.
    437     */
    438     void setStrokeJoin(Join join);
    439 
    440     /**
    441      *  Applies any/all effects (patheffect, stroking) to src, returning the
    442      *  result in dst. The result is that drawing src with this paint will be
    443      *  the same as drawing dst with a default paint (at least from the
    444      *  geometric perspective).
    445      *
    446      *  @param src  input path
    447      *  @param dst  output path (may be the same as src)
    448      *  @param cullRect If not null, the dst path may be culled to this rect.
    449      *  @param resScale If > 1, increase precision, else if (0 < res < 1) reduce precision
    450      *              in favor of speed/size.
    451      *  @return     true if the path should be filled, or false if it should be
    452      *              drawn with a hairline (width == 0)
    453      */
    454     bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
    455                      SkScalar resScale = 1) const;
    456 
    457     bool getFillPath(const SkPath& src, SkPath* dst) const {
    458         return this->getFillPath(src, dst, NULL, 1);
    459     }
    460 
    461     /** Get the paint's shader object.
    462         <p />
    463       The shader's reference count is not affected.
    464         @return the paint's shader (or NULL)
    465     */
    466     SkShader* getShader() const { return fShader.get(); }
    467     sk_sp<SkShader> refShader() const;
    468 
    469     /** Set or clear the shader object.
    470      *  Shaders specify the source color(s) for what is being drawn. If a paint
    471      *  has no shader, then the paint's color is used. If the paint has a
    472      *  shader, then the shader's color(s) are use instead, but they are
    473      *  modulated by the paint's alpha. This makes it easy to create a shader
    474      *  once (e.g. bitmap tiling or gradient) and then change its transparency
    475      *  w/o having to modify the original shader... only the paint's alpha needs
    476      *  to be modified.
    477      *
    478      *  There is an exception to this only-respect-paint's-alpha rule: If the shader only generates
    479      *  alpha (e.g. SkShader::CreateBitmapShader(bitmap, ...) where bitmap's colortype is kAlpha_8)
    480      *  then the shader will use the paint's entire color to "colorize" its output (modulating the
    481      *  bitmap's alpha with the paint's color+alpha).
    482      *
    483      *  Pass NULL to clear any previous shader.
    484      *  As a convenience, the parameter passed is also returned.
    485      *  If a previous shader exists, its reference count is decremented.
    486      *  If shader is not NULL, its reference count is incremented.
    487      *  @param shader   May be NULL. The shader to be installed in the paint
    488      */
    489     void setShader(sk_sp<SkShader> shader);
    490 
    491     /** Get the paint's colorfilter. If there is a colorfilter, its reference
    492         count is not changed.
    493         @return the paint's colorfilter (or NULL)
    494     */
    495     SkColorFilter* getColorFilter() const { return fColorFilter.get(); }
    496     sk_sp<SkColorFilter> refColorFilter() const;
    497 
    498     /** Set or clear the paint's colorfilter.
    499         <p />
    500         If the paint already has a filter, its reference count is decremented.
    501         If filter is not NULL, its reference count is incremented.
    502         @param filter   May be NULL. The filter to be installed in the paint
    503     */
    504     void setColorFilter(sk_sp<SkColorFilter> colorFilter);
    505 
    506     SkBlendMode getBlendMode() const { return (SkBlendMode)fBlendMode; }
    507     bool isSrcOver() const { return (SkBlendMode)fBlendMode == SkBlendMode::kSrcOver; }
    508     void setBlendMode(SkBlendMode mode) { fBlendMode = (unsigned)mode; }
    509 
    510     /** Get the paint's patheffect object.
    511         <p />
    512       The patheffect reference count is not affected.
    513         @return the paint's patheffect (or NULL)
    514     */
    515     SkPathEffect* getPathEffect() const { return fPathEffect.get(); }
    516     sk_sp<SkPathEffect> refPathEffect() const;
    517 
    518     /** Set or clear the patheffect object.
    519         <p />
    520         Pass NULL to clear any previous patheffect.
    521         As a convenience, the parameter passed is also returned.
    522         If a previous patheffect exists, its reference count is decremented.
    523         If patheffect is not NULL, its reference count is incremented.
    524         @param effect   May be NULL. The new patheffect to be installed in the
    525                         paint
    526         @return         effect
    527     */
    528     void setPathEffect(sk_sp<SkPathEffect> pathEffect);
    529 
    530     /** Get the paint's maskfilter object.
    531         <p />
    532       The maskfilter reference count is not affected.
    533         @return the paint's maskfilter (or NULL)
    534     */
    535     SkMaskFilter* getMaskFilter() const { return fMaskFilter.get(); }
    536     sk_sp<SkMaskFilter> refMaskFilter() const;
    537 
    538     /** Set or clear the maskfilter object.
    539         <p />
    540         Pass NULL to clear any previous maskfilter.
    541         As a convenience, the parameter passed is also returned.
    542         If a previous maskfilter exists, its reference count is decremented.
    543         If maskfilter is not NULL, its reference count is incremented.
    544         @param maskfilter   May be NULL. The new maskfilter to be installed in
    545                             the paint
    546         @return             maskfilter
    547     */
    548     void setMaskFilter(sk_sp<SkMaskFilter> maskFilter);
    549 
    550     // These attributes are for text/fonts
    551 
    552     /** Get the paint's typeface object.
    553         <p />
    554         The typeface object identifies which font to use when drawing or
    555         measuring text. The typeface reference count is not affected.
    556         @return the paint's typeface (or NULL)
    557     */
    558     SkTypeface* getTypeface() const { return fTypeface.get(); }
    559     sk_sp<SkTypeface> refTypeface() const;
    560 
    561     /** Set or clear the typeface object.
    562         <p />
    563         Pass NULL to clear any previous typeface.
    564         As a convenience, the parameter passed is also returned.
    565         If a previous typeface exists, its reference count is decremented.
    566         If typeface is not NULL, its reference count is incremented.
    567         @param typeface May be NULL. The new typeface to be installed in the
    568                         paint
    569         @return         typeface
    570     */
    571     void setTypeface(sk_sp<SkTypeface> typeface);
    572 
    573     /** Get the paint's rasterizer (or NULL).
    574         <p />
    575         The raster controls how paths/text are turned into alpha masks.
    576         @return the paint's rasterizer (or NULL)
    577     */
    578     SkRasterizer* getRasterizer() const { return fRasterizer.get(); }
    579     sk_sp<SkRasterizer> refRasterizer() const;
    580 
    581     /** Set or clear the rasterizer object.
    582         <p />
    583         Pass NULL to clear any previous rasterizer.
    584         As a convenience, the parameter passed is also returned.
    585         If a previous rasterizer exists in the paint, its reference count is
    586         decremented. If rasterizer is not NULL, its reference count is
    587         incremented.
    588         @param rasterizer May be NULL. The new rasterizer to be installed in
    589                           the paint.
    590         @return           rasterizer
    591     */
    592     void setRasterizer(sk_sp<SkRasterizer> rasterizer);
    593 
    594     SkImageFilter* getImageFilter() const { return fImageFilter.get(); }
    595     sk_sp<SkImageFilter> refImageFilter() const;
    596     void setImageFilter(sk_sp<SkImageFilter> imageFilter);
    597 
    598     /**
    599      *  Return the paint's SkDrawLooper (if any). Does not affect the looper's
    600      *  reference count.
    601      */
    602     SkDrawLooper* getDrawLooper() const { return fDrawLooper.get(); }
    603     sk_sp<SkDrawLooper> refDrawLooper() const;
    604 
    605     SkDrawLooper* getLooper() const { return fDrawLooper.get(); }
    606     /**
    607      *  Set or clear the looper object.
    608      *  <p />
    609      *  Pass NULL to clear any previous looper.
    610      *  If a previous looper exists in the paint, its reference count is
    611      *  decremented. If looper is not NULL, its reference count is
    612      *  incremented.
    613      *  @param looper May be NULL. The new looper to be installed in the paint.
    614      */
    615     void setDrawLooper(sk_sp<SkDrawLooper> drawLooper);
    616 
    617     void setLooper(sk_sp<SkDrawLooper> drawLooper);
    618 
    619     enum Align {
    620         kLeft_Align,
    621         kCenter_Align,
    622         kRight_Align,
    623     };
    624     enum {
    625         kAlignCount = 3
    626     };
    627 
    628     /** Return the paint's Align value for drawing text.
    629         @return the paint's Align value for drawing text.
    630     */
    631     Align   getTextAlign() const { return (Align)fBitfields.fTextAlign; }
    632 
    633     /** Set the paint's text alignment.
    634         @param align set the paint's Align value for drawing text.
    635     */
    636     void    setTextAlign(Align align);
    637 
    638     /** Return the paint's text size.
    639         @return the paint's text size.
    640     */
    641     SkScalar getTextSize() const { return fTextSize; }
    642 
    643     /** Set the paint's text size. This value must be > 0
    644         @param textSize set the paint's text size.
    645     */
    646     void setTextSize(SkScalar textSize);
    647 
    648     /** Return the paint's horizontal scale factor for text. The default value
    649         is 1.0.
    650         @return the paint's scale factor in X for drawing/measuring text
    651     */
    652     SkScalar getTextScaleX() const { return fTextScaleX; }
    653 
    654     /** Set the paint's horizontal scale factor for text. The default value
    655         is 1.0. Values > 1.0 will stretch the text wider. Values < 1.0 will
    656         stretch the text narrower.
    657         @param scaleX   set the paint's scale factor in X for drawing/measuring
    658                         text.
    659     */
    660     void setTextScaleX(SkScalar scaleX);
    661 
    662     /** Return the paint's horizontal skew factor for text. The default value
    663         is 0.
    664         @return the paint's skew factor in X for drawing text.
    665     */
    666     SkScalar getTextSkewX() const { return fTextSkewX; }
    667 
    668     /** Set the paint's horizontal skew factor for text. The default value
    669         is 0. For approximating oblique text, use values around -0.25.
    670         @param skewX set the paint's skew factor in X for drawing text.
    671     */
    672     void setTextSkewX(SkScalar skewX);
    673 
    674     /** Describes how to interpret the text parameters that are passed to paint
    675         methods like measureText() and getTextWidths().
    676     */
    677     enum TextEncoding {
    678         kUTF8_TextEncoding,     //!< the text parameters are UTF8
    679         kUTF16_TextEncoding,    //!< the text parameters are UTF16
    680         kUTF32_TextEncoding,    //!< the text parameters are UTF32
    681         kGlyphID_TextEncoding   //!< the text parameters are glyph indices
    682     };
    683 
    684     TextEncoding getTextEncoding() const {
    685       return (TextEncoding)fBitfields.fTextEncoding;
    686     }
    687 
    688     void setTextEncoding(TextEncoding encoding);
    689 
    690     struct FontMetrics {
    691         /** Flags which indicate the confidence level of various metrics.
    692             A set flag indicates that the metric may be trusted.
    693         */
    694         enum FontMetricsFlags {
    695             kUnderlineThicknessIsValid_Flag = 1 << 0,
    696             kUnderlinePositionIsValid_Flag = 1 << 1,
    697         };
    698 
    699         uint32_t    fFlags;       //!< Bit field to identify which values are unknown
    700         SkScalar    fTop;       //!< The greatest distance above the baseline for any glyph (will be <= 0)
    701         SkScalar    fAscent;    //!< The recommended distance above the baseline (will be <= 0)
    702         SkScalar    fDescent;   //!< The recommended distance below the baseline (will be >= 0)
    703         SkScalar    fBottom;    //!< The greatest distance below the baseline for any glyph (will be >= 0)
    704         SkScalar    fLeading;   //!< The recommended distance to add between lines of text (will be >= 0)
    705         SkScalar    fAvgCharWidth;  //!< the average character width (>= 0)
    706         SkScalar    fMaxCharWidth;  //!< the max character width (>= 0)
    707         SkScalar    fXMin;      //!< The minimum bounding box x value for all glyphs
    708         SkScalar    fXMax;      //!< The maximum bounding box x value for all glyphs
    709         SkScalar    fXHeight;   //!< The height of an 'x' in px, or 0 if no 'x' in face
    710         SkScalar    fCapHeight;  //!< The cap height (> 0), or 0 if cannot be determined.
    711         SkScalar    fUnderlineThickness; //!< underline thickness, or 0 if cannot be determined
    712 
    713         /**  Underline Position - position of the top of the Underline stroke
    714                 relative to the baseline, this can have following values
    715                 - Negative - means underline should be drawn above baseline.
    716                 - Positive - means below baseline.
    717                 - Zero     - mean underline should be drawn on baseline.
    718          */
    719         SkScalar    fUnderlinePosition; //!< underline position, or 0 if cannot be determined
    720 
    721         /**  If the fontmetrics has a valid underline thickness, return true, and set the
    722                 thickness param to that value. If it doesn't return false and ignore the
    723                 thickness param.
    724         */
    725         bool hasUnderlineThickness(SkScalar* thickness) const {
    726             if (SkToBool(fFlags & kUnderlineThicknessIsValid_Flag)) {
    727                 *thickness = fUnderlineThickness;
    728                 return true;
    729             }
    730             return false;
    731         }
    732 
    733         /**  If the fontmetrics has a valid underline position, return true, and set the
    734                 position param to that value. If it doesn't return false and ignore the
    735                 position param.
    736         */
    737         bool hasUnderlinePosition(SkScalar* position) const {
    738             if (SkToBool(fFlags & kUnderlinePositionIsValid_Flag)) {
    739                 *position = fUnderlinePosition;
    740                 return true;
    741             }
    742             return false;
    743         }
    744 
    745     };
    746 
    747     /** Return the recommend spacing between lines (which will be
    748         fDescent - fAscent + fLeading).
    749         If metrics is not null, return in it the font metrics for the
    750         typeface/pointsize/etc. currently set in the paint.
    751         @param metrics      If not null, returns the font metrics for the
    752                             current typeface/pointsize/etc setting in this
    753                             paint.
    754         @param scale        If not 0, return width as if the canvas were scaled
    755                             by this value
    756         @param return the recommended spacing between lines
    757     */
    758     SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const;
    759 
    760     /** Return the recommend line spacing. This will be
    761         fDescent - fAscent + fLeading
    762     */
    763     SkScalar getFontSpacing() const { return this->getFontMetrics(NULL, 0); }
    764 
    765     /** Convert the specified text into glyph IDs, returning the number of
    766         glyphs ID written. If glyphs is NULL, it is ignore and only the count
    767         is returned.
    768     */
    769     int textToGlyphs(const void* text, size_t byteLength,
    770                      SkGlyphID glyphs[]) const;
    771 
    772     /** Return true if all of the specified text has a corresponding non-zero
    773         glyph ID. If any of the code-points in the text are not supported in
    774         the typeface (i.e. the glyph ID would be zero), then return false.
    775 
    776         If the text encoding for the paint is kGlyph_TextEncoding, then this
    777         returns true if all of the specified glyph IDs are non-zero.
    778      */
    779     bool containsText(const void* text, size_t byteLength) const;
    780 
    781     /** Convert the glyph array into Unichars. Unconvertable glyphs are mapped
    782         to zero. Note: this does not look at the text-encoding setting in the
    783         paint, only at the typeface.
    784     */
    785     void glyphsToUnichars(const SkGlyphID glyphs[], int count, SkUnichar text[]) const;
    786 
    787     /** Return the number of drawable units in the specified text buffer.
    788         This looks at the current TextEncoding field of the paint. If you also
    789         want to have the text converted into glyph IDs, call textToGlyphs
    790         instead.
    791     */
    792     int countText(const void* text, size_t byteLength) const {
    793         return this->textToGlyphs(text, byteLength, NULL);
    794     }
    795 
    796     /** Return the width of the text. This will return the vertical measure
    797      *  if isVerticalText() is true, in which case the returned value should
    798      *  be treated has a height instead of a width.
    799      *
    800      *  @param text         The text to be measured
    801      *  @param length       Number of bytes of text to measure
    802      *  @param bounds       If not NULL, returns the bounds of the text,
    803      *                      relative to (0, 0).
    804      *  @return             The advance width of the text
    805      */
    806     SkScalar measureText(const void* text, size_t length, SkRect* bounds) const;
    807 
    808     /** Return the width of the text. This will return the vertical measure
    809      *  if isVerticalText() is true, in which case the returned value should
    810      *  be treated has a height instead of a width.
    811      *
    812      *  @param text     Address of the text
    813      *  @param length   Number of bytes of text to measure
    814      *  @return         The advance width of the text
    815      */
    816     SkScalar measureText(const void* text, size_t length) const {
    817         return this->measureText(text, length, NULL);
    818     }
    819 
    820     /** Return the number of bytes of text that were measured. If
    821      *  isVerticalText() is true, then the vertical advances are used for
    822      *  the measurement.
    823      *
    824      *  @param text     The text to be measured
    825      *  @param length   Number of bytes of text to measure
    826      *  @param maxWidth Maximum width. Only the subset of text whose accumulated
    827      *                  widths are <= maxWidth are measured.
    828      *  @param measuredWidth Optional. If non-null, this returns the actual
    829      *                  width of the measured text.
    830      *  @return         The number of bytes of text that were measured. Will be
    831      *                  <= length.
    832      */
    833     size_t  breakText(const void* text, size_t length, SkScalar maxWidth,
    834                       SkScalar* measuredWidth = NULL) const;
    835 
    836     /** Return the advances for the text. These will be vertical advances if
    837      *  isVerticalText() returns true.
    838      *
    839      *  @param text         the text
    840      *  @param byteLength   number of bytes to of text
    841      *  @param widths       If not null, returns the array of advances for
    842      *                      the glyphs. If not NULL, must be at least a large
    843      *                      as the number of unichars in the specified text.
    844      *  @param bounds       If not null, returns the bounds for each of
    845      *                      character, relative to (0, 0)
    846      *  @return the number of unichars in the specified text.
    847      */
    848     int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
    849                       SkRect bounds[] = NULL) const;
    850 
    851     /** Return the path (outline) for the specified text.
    852      *  Note: just like SkCanvas::drawText, this will respect the Align setting
    853      *        in the paint.
    854      *
    855      *  @param text         the text
    856      *  @param length       number of bytes of text
    857      *  @param x            The x-coordinate of the origin of the text.
    858      *  @param y            The y-coordinate of the origin of the text.
    859      *  @param path         The outline of the text.
    860      */
    861     void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
    862                      SkPath* path) const;
    863 
    864     /** Return the path (outline) for the specified text.
    865      *  Note: just like SkCanvas::drawText, this will respect the Align setting
    866      *        in the paint.
    867      *
    868      *  @param text         the text
    869      *  @param length       number of bytes of text
    870      *  @param pos          array of positions, used to position each character
    871      *  @param path         The outline of the text.
    872      */
    873     void getPosTextPath(const void* text, size_t length,
    874                         const SkPoint pos[], SkPath* path) const;
    875 
    876     /** Return the number of intervals that intersect the intercept along the axis of the advance.
    877      *  The return count is zero or a multiple of two, and is at most the number of glyphs * 2 in
    878      *  the string. The caller may pass nullptr for intervals to determine the size of the interval
    879      *  array, or may conservatively pre-allocate an array with length * 2 entries. The computed
    880      *  intervals are cached by glyph to improve performance for multiple calls.
    881      *  This permits constructing an underline that skips the descenders.
    882      *
    883      *  @param text         the text
    884      *  @param length       number of bytes of text
    885      *  @param x            The x-coordinate of the origin of the text.
    886      *  @param y            The y-coordinate of the origin of the text.
    887      *  @param bounds       The lower and upper line parallel to the advance.
    888      *  @param array        If not null, the found intersections.
    889      *
    890      *  @return             The number of intersections, which may be zero.
    891      */
    892     int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
    893                           const SkScalar bounds[2], SkScalar* intervals) const;
    894 
    895     /** Return the number of intervals that intersect the intercept along the axis of the advance.
    896      *  The return count is zero or a multiple of two, and is at most the number of glyphs * 2 in
    897      *  string. The caller may pass nullptr for intervals to determine the size of the interval
    898      *  array, or may conservatively pre-allocate an array with length * 2 entries. The computed
    899      *  intervals are cached by glyph to improve performance for multiple calls.
    900      *  This permits constructing an underline that skips the descenders.
    901      *
    902      *  @param text         the text
    903      *  @param length       number of bytes of text
    904      *  @param pos          array of positions, used to position each character
    905      *  @param bounds       The lower and upper line parallel to the advance.
    906      *  @param array        If not null, the glyph bounds contained by the advance parallel lines.
    907      *
    908      *  @return             The number of intersections, which may be zero.
    909      */
    910     int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
    911                              const SkScalar bounds[2], SkScalar* intervals) const;
    912 
    913     /** Return the number of intervals that intersect the intercept along the axis of the advance.
    914      *  The return count is zero or a multiple of two, and is at most the number of glyphs * 2 in
    915      *  string. The caller may pass nullptr for intervals to determine the size of the interval
    916      *  array, or may conservatively pre-allocate an array with length * 2 entries. The computed
    917      *  intervals are cached by glyph to improve performance for multiple calls.
    918      *  This permits constructing an underline that skips the descenders.
    919      *
    920      *  @param text         The text.
    921      *  @param length       Number of bytes of text.
    922      *  @param xpos         Array of x-positions, used to position each character.
    923      *  @param constY       The shared Y coordinate for all of the positions.
    924      *  @param bounds       The lower and upper line parallel to the advance.
    925      *  @param array        If not null, the glyph bounds contained by the advance parallel lines.
    926      *
    927      *  @return             The number of intersections, which may be zero.
    928      */
    929     int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
    930                               SkScalar constY, const SkScalar bounds[2], SkScalar* intervals) const;
    931 
    932     /** Return the number of intervals that intersect the intercept along the axis of the advance.
    933      *  The return count is zero or a multiple of two, and is at most the number of glyphs * 2 in
    934      *  text blob. The caller may pass nullptr for intervals to determine the size of the interval
    935      *  array. The computed intervals are cached by glyph to improve performance for multiple calls.
    936      *  This permits constructing an underline that skips the descenders.
    937      *
    938      *  @param blob         The text blob.
    939      *  @param bounds       The lower and upper line parallel to the advance.
    940      *  @param array        If not null, the glyph bounds contained by the advance parallel lines.
    941      *
    942      *  @return             The number of intersections, which may be zero.
    943      */
    944     int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
    945                               SkScalar* intervals) const;
    946 
    947     /**
    948      *  Return a rectangle that represents the union of the bounds of all
    949      *  of the glyphs, but each one positioned at (0,0). This may be conservatively large, and
    950      *  will not take into account any hinting, but will respect any text-scale-x or text-skew-x
    951      *  on this paint.
    952      */
    953     SkRect getFontBounds() const;
    954 
    955     // returns true if the paint's settings (e.g. xfermode + alpha) resolve to
    956     // mean that we need not draw at all (e.g. SrcOver + 0-alpha)
    957     bool nothingToDraw() const;
    958 
    959     ///////////////////////////////////////////////////////////////////////////
    960     // would prefer to make these private...
    961 
    962     /** Returns true if the current paint settings allow for fast computation of
    963      bounds (i.e. there is nothing complex like a patheffect that would make
    964      the bounds computation expensive.
    965      */
    966     bool canComputeFastBounds() const;
    967 
    968     /** Only call this if canComputeFastBounds() returned true. This takes a
    969      raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
    970      effects in the paint (e.g. stroking). If needed, it uses the storage
    971      rect parameter. It returns the adjusted bounds that can then be used
    972      for quickReject tests.
    973 
    974      The returned rect will either be orig or storage, thus the caller
    975      should not rely on storage being set to the result, but should always
    976      use the retured value. It is legal for orig and storage to be the same
    977      rect.
    978 
    979      e.g.
    980      if (paint.canComputeFastBounds()) {
    981      SkRect r, storage;
    982      path.computeBounds(&r, SkPath::kFast_BoundsType);
    983      const SkRect& fastR = paint.computeFastBounds(r, &storage);
    984      if (canvas->quickReject(fastR, ...)) {
    985      // don't draw the path
    986      }
    987      }
    988      */
    989     const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const {
    990         // Things like stroking, etc... will do math on the bounds rect, assuming that it's sorted.
    991         SkASSERT(orig.isSorted());
    992         SkPaint::Style style = this->getStyle();
    993         // ultra fast-case: filling with no effects that affect geometry
    994         if (kFill_Style == style) {
    995             uintptr_t effects = reinterpret_cast<uintptr_t>(this->getLooper());
    996             effects |= reinterpret_cast<uintptr_t>(this->getMaskFilter());
    997             effects |= reinterpret_cast<uintptr_t>(this->getPathEffect());
    998             effects |= reinterpret_cast<uintptr_t>(this->getImageFilter());
    999             if (!effects) {
   1000                 return orig;
   1001             }
   1002         }
   1003 
   1004         return this->doComputeFastBounds(orig, storage, style);
   1005     }
   1006 
   1007     const SkRect& computeFastStrokeBounds(const SkRect& orig,
   1008                                           SkRect* storage) const {
   1009         return this->doComputeFastBounds(orig, storage, kStroke_Style);
   1010     }
   1011 
   1012     // Take the style explicitly, so the caller can force us to be stroked
   1013     // without having to make a copy of the paint just to change that field.
   1014     const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
   1015                                       Style style) const;
   1016 
   1017 
   1018 
   1019     SK_TO_STRING_NONVIRT()
   1020 
   1021 private:
   1022     typedef const SkGlyph& (*GlyphCacheProc)(SkGlyphCache*, const char**);
   1023 
   1024     sk_sp<SkTypeface>     fTypeface;
   1025     sk_sp<SkPathEffect>   fPathEffect;
   1026     sk_sp<SkShader>       fShader;
   1027     sk_sp<SkMaskFilter>   fMaskFilter;
   1028     sk_sp<SkColorFilter>  fColorFilter;
   1029     sk_sp<SkRasterizer>   fRasterizer;
   1030     sk_sp<SkDrawLooper>   fDrawLooper;
   1031     sk_sp<SkImageFilter>  fImageFilter;
   1032 
   1033     SkScalar        fTextSize;
   1034     SkScalar        fTextScaleX;
   1035     SkScalar        fTextSkewX;
   1036     SkColor         fColor;
   1037     SkScalar        fWidth;
   1038     SkScalar        fMiterLimit;
   1039     uint32_t        fBlendMode; // just need 5-6 bits
   1040     union {
   1041         struct {
   1042             // all of these bitfields should add up to 32
   1043             unsigned        fFlags : 16;
   1044             unsigned        fTextAlign : 2;
   1045             unsigned        fCapType : 2;
   1046             unsigned        fJoinType : 2;
   1047             unsigned        fStyle : 2;
   1048             unsigned        fTextEncoding : 2;  // 3 values
   1049             unsigned        fHinting : 2;
   1050             unsigned        fFilterQuality : 2;
   1051             //unsigned      fFreeBits : 2;
   1052         } fBitfields;
   1053         uint32_t fBitfieldsUInt;
   1054     };
   1055 
   1056     static GlyphCacheProc GetGlyphCacheProc(TextEncoding encoding,
   1057                                             bool isDevKern,
   1058                                             bool needFullMetrics);
   1059 
   1060     SkScalar measure_text(SkGlyphCache*, const char* text, size_t length,
   1061                           int* count, SkRect* bounds) const;
   1062 
   1063     enum ScalerContextFlags : uint32_t {
   1064         kNone_ScalerContextFlags = 0,
   1065 
   1066         kFakeGamma_ScalerContextFlag = 1 << 0,
   1067         kBoostContrast_ScalerContextFlag = 1 << 1,
   1068 
   1069         kFakeGammaAndBoostContrast_ScalerContextFlags =
   1070             kFakeGamma_ScalerContextFlag | kBoostContrast_ScalerContextFlag,
   1071     };
   1072 
   1073     /*
   1074      * Allocs an SkDescriptor on the heap and return it to the caller as a refcnted
   1075      * SkData.  Caller is responsible for managing the lifetime of this object.
   1076      */
   1077     void getScalerContextDescriptor(SkScalerContextEffects*, SkAutoDescriptor*,
   1078                                     const SkSurfaceProps& surfaceProps,
   1079                                     uint32_t scalerContextFlags, const SkMatrix*) const;
   1080 
   1081     SkGlyphCache* detachCache(const SkSurfaceProps* surfaceProps, uint32_t scalerContextFlags,
   1082                               const SkMatrix*) const;
   1083 
   1084     void descriptorProc(const SkSurfaceProps* surfaceProps, uint32_t scalerContextFlags,
   1085                         const SkMatrix* deviceMatrix,
   1086                         void (*proc)(SkTypeface*, const SkScalerContextEffects&,
   1087                                      const SkDescriptor*, void*),
   1088                         void* context) const;
   1089 
   1090     /*
   1091      * The luminance color is used to determine which Gamma Canonical color to map to.  This is
   1092      * really only used by backends which want to cache glyph masks, and need some way to know if
   1093      * they need to generate new masks based off a given color.
   1094      */
   1095     SkColor computeLuminanceColor() const;
   1096 
   1097     enum {
   1098         /*  This is the size we use when we ask for a glyph's path. We then
   1099          *  post-transform it as we draw to match the request.
   1100          *  This is done to try to re-use cache entries for the path.
   1101          *
   1102          *  This value is somewhat arbitrary. In theory, it could be 1, since
   1103          *  we store paths as floats. However, we get the path from the font
   1104          *  scaler, and it may represent its paths as fixed-point (or 26.6),
   1105          *  so we shouldn't ask for something too big (might overflow 16.16)
   1106          *  or too small (underflow 26.6).
   1107          *
   1108          *  This value could track kMaxSizeForGlyphCache, assuming the above
   1109          *  constraints, but since we ask for unhinted paths, the two values
   1110          *  need not match per-se.
   1111          */
   1112         kCanonicalTextSizeForPaths  = 64,
   1113     };
   1114 
   1115     static bool TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM);
   1116 
   1117     // Set flags/hinting/textSize up to use for drawing text as paths.
   1118     // Returns scale factor to restore the original textSize, since will will
   1119     // have change it to kCanonicalTextSizeForPaths.
   1120     SkScalar setupForAsPaths();
   1121 
   1122     static SkScalar MaxCacheSize2();
   1123 
   1124     friend class SkAutoGlyphCache;
   1125     friend class SkAutoGlyphCacheNoGamma;
   1126     friend class SkCanvas;
   1127     friend class SkDraw;
   1128     friend class SkPDFDevice;
   1129     friend class GrAtlasTextBlob;
   1130     friend class GrAtlasTextContext;
   1131     friend class GrStencilAndCoverTextContext;
   1132     friend class GrPathRendering;
   1133     friend class GrTextUtils;
   1134     friend class GrGLPathRendering;
   1135     friend class SkScalerContext;
   1136     friend class SkTextBaseIter;
   1137     friend class SkCanonicalizePaint;
   1138 };
   1139 
   1140 #endif
   1141