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 #include "SkPaint.h"
      9 
     10 #include "SkColorFilter.h"
     11 #include "SkColorSpacePriv.h"
     12 #include "SkColorSpaceXformSteps.h"
     13 #include "SkData.h"
     14 #include "SkDraw.h"
     15 #include "SkGraphics.h"
     16 #include "SkImageFilter.h"
     17 #include "SkMaskFilter.h"
     18 #include "SkMaskGamma.h"
     19 #include "SkMutex.h"
     20 #include "SkOpts.h"
     21 #include "SkPaintDefaults.h"
     22 #include "SkPaintPriv.h"
     23 #include "SkPathEffect.h"
     24 #include "SkReadBuffer.h"
     25 #include "SkSafeRange.h"
     26 #include "SkScalar.h"
     27 #include "SkShader.h"
     28 #include "SkShaderBase.h"
     29 #include "SkStringUtils.h"
     30 #include "SkStroke.h"
     31 #include "SkStrokeRec.h"
     32 #include "SkSurfacePriv.h"
     33 #include "SkTLazy.h"
     34 #include "SkTo.h"
     35 #include "SkTypeface.h"
     36 #include "SkWriteBuffer.h"
     37 
     38 // define this to get a printf for out-of-range parameter in setters
     39 // e.g. setTextSize(-1)
     40 //#define SK_REPORT_API_RANGE_CHECK
     41 
     42 
     43 SkPaint::SkPaint()
     44     : fColor4f{0, 0, 0, 1}  // opaque black
     45     , fWidth{0}
     46     , fMiterLimit{SkPaintDefaults_MiterLimit}
     47     , fBitfields{(unsigned)false,                   // fAntiAlias
     48                  (unsigned)false,                   // fDither
     49                  (unsigned)SkPaint::kDefault_Cap,   // fCapType
     50                  (unsigned)SkPaint::kDefault_Join,  // fJoinType
     51                  (unsigned)SkPaint::kFill_Style,    // fStyle
     52                  (unsigned)kNone_SkFilterQuality,   // fFilterQuality
     53                  (unsigned)SkBlendMode::kSrcOver,   // fBlendMode
     54                  0}                                 // fPadding
     55 {
     56     static_assert(sizeof(fBitfields) == sizeof(fBitfieldsUInt), "");
     57 }
     58 
     59 SkPaint::SkPaint(const SkPaint& src) = default;
     60 
     61 SkPaint::SkPaint(SkPaint&& src) = default;
     62 
     63 SkPaint::~SkPaint() = default;
     64 
     65 SkPaint& SkPaint::operator=(const SkPaint& src) = default;
     66 
     67 SkPaint& SkPaint::operator=(SkPaint&& src) = default;
     68 
     69 bool operator==(const SkPaint& a, const SkPaint& b) {
     70 #define EQUAL(field) (a.field == b.field)
     71     return EQUAL(fPathEffect)
     72         && EQUAL(fShader)
     73         && EQUAL(fMaskFilter)
     74         && EQUAL(fColorFilter)
     75         && EQUAL(fDrawLooper)
     76         && EQUAL(fImageFilter)
     77         && EQUAL(fColor4f)
     78         && EQUAL(fWidth)
     79         && EQUAL(fMiterLimit)
     80         && EQUAL(fBitfieldsUInt)
     81         ;
     82 #undef EQUAL
     83 }
     84 
     85 #define DEFINE_REF_FOO(type)    sk_sp<Sk##type> SkPaint::ref##type() const { return f##type; }
     86 DEFINE_REF_FOO(ColorFilter)
     87 DEFINE_REF_FOO(DrawLooper)
     88 DEFINE_REF_FOO(ImageFilter)
     89 DEFINE_REF_FOO(MaskFilter)
     90 DEFINE_REF_FOO(PathEffect)
     91 DEFINE_REF_FOO(Shader)
     92 #undef DEFINE_REF_FOO
     93 
     94 void SkPaint::reset() { *this = SkPaint(); }
     95 
     96 void SkPaint::setFilterQuality(SkFilterQuality quality) {
     97     fBitfields.fFilterQuality = quality;
     98 }
     99 
    100 void SkPaint::setStyle(Style style) {
    101     if ((unsigned)style < kStyleCount) {
    102         fBitfields.fStyle = style;
    103     } else {
    104 #ifdef SK_REPORT_API_RANGE_CHECK
    105         SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
    106 #endif
    107     }
    108 }
    109 
    110 void SkPaint::setColor(SkColor color) {
    111     fColor4f = SkColor4f::FromColor(color);
    112 }
    113 
    114 void SkPaint::setColor4f(const SkColor4f& color, SkColorSpace* colorSpace) {
    115     SkASSERT(fColor4f.fA >= 0 && fColor4f.fA <= 1.0f);
    116 
    117     SkColorSpaceXformSteps steps{colorSpace,          kUnpremul_SkAlphaType,
    118                                  sk_srgb_singleton(), kUnpremul_SkAlphaType};
    119     fColor4f = color;
    120     steps.apply(fColor4f.vec());
    121 }
    122 
    123 void SkPaint::setAlphaf(float a) {
    124     SkASSERT(a >= 0 && a <= 1.0f);
    125     fColor4f.fA = a;
    126 }
    127 
    128 void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
    129     this->setColor(SkColorSetARGB(a, r, g, b));
    130 }
    131 
    132 void SkPaint::setStrokeWidth(SkScalar width) {
    133     if (width >= 0) {
    134         fWidth = width;
    135     } else {
    136 #ifdef SK_REPORT_API_RANGE_CHECK
    137         SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
    138 #endif
    139     }
    140 }
    141 
    142 void SkPaint::setStrokeMiter(SkScalar limit) {
    143     if (limit >= 0) {
    144         fMiterLimit = limit;
    145     } else {
    146 #ifdef SK_REPORT_API_RANGE_CHECK
    147         SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
    148 #endif
    149     }
    150 }
    151 
    152 void SkPaint::setStrokeCap(Cap ct) {
    153     if ((unsigned)ct < kCapCount) {
    154         fBitfields.fCapType = SkToU8(ct);
    155     } else {
    156 #ifdef SK_REPORT_API_RANGE_CHECK
    157         SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
    158 #endif
    159     }
    160 }
    161 
    162 void SkPaint::setStrokeJoin(Join jt) {
    163     if ((unsigned)jt < kJoinCount) {
    164         fBitfields.fJoinType = SkToU8(jt);
    165     } else {
    166 #ifdef SK_REPORT_API_RANGE_CHECK
    167         SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
    168 #endif
    169     }
    170 }
    171 
    172 ///////////////////////////////////////////////////////////////////////////////
    173 
    174 #define MOVE_FIELD(Field) void SkPaint::set##Field(sk_sp<Sk##Field> f) { f##Field = std::move(f); }
    175 MOVE_FIELD(ImageFilter)
    176 MOVE_FIELD(Shader)
    177 MOVE_FIELD(ColorFilter)
    178 MOVE_FIELD(PathEffect)
    179 MOVE_FIELD(MaskFilter)
    180 MOVE_FIELD(DrawLooper)
    181 #undef MOVE_FIELD
    182 void SkPaint::setLooper(sk_sp<SkDrawLooper> looper) { fDrawLooper = std::move(looper); }
    183 
    184 ///////////////////////////////////////////////////////////////////////////////
    185 
    186 #include "SkStream.h"
    187 
    188 #ifdef SK_DEBUG
    189     static void ASSERT_FITS_IN(uint32_t value, int bitCount) {
    190         SkASSERT(bitCount > 0 && bitCount <= 32);
    191         uint32_t mask = ~0U;
    192         mask >>= (32 - bitCount);
    193         SkASSERT(0 == (value & ~mask));
    194     }
    195 #else
    196     #define ASSERT_FITS_IN(value, bitcount)
    197 #endif
    198 
    199 enum FlatFlags {
    200     kHasTypeface_FlatFlag = 0x1,
    201     kHasEffects_FlatFlag  = 0x2,
    202 
    203     kFlatFlagMask         = 0x3,
    204 };
    205 
    206 enum BitsPerField {
    207     kFlags_BPF  = 16,
    208     kHint_BPF   = 2,
    209     kFilter_BPF = 2,
    210     kFlatFlags_BPF  = 3,
    211 };
    212 
    213 static inline int BPF_Mask(int bits) {
    214     return (1 << bits) - 1;
    215 }
    216 
    217 // SkPaint originally defined flags, some of which now apply to SkFont. These are renames
    218 // of those flags, split into categories depending on which objects they (now) apply to.
    219 
    220 enum PaintFlagsForPaint {
    221     kAA_PaintFlagForPaint     = 0x01,
    222     kDither_PaintFlagForPaint = 0x04,
    223 };
    224 
    225 enum PaintFlagsForFont {
    226     kFakeBold_PaintFlagForFont       = 0x20,
    227     kLinear_PaintFlagForFont         = 0x40,
    228     kSubpixel_PaintFlagForFont       = 0x80,
    229     kLCD_PaintFlagForFont            = 0x200,
    230     kEmbeddedBitmap_PaintFlagForFont = 0x400,
    231     kAutoHinting_PaintFlagForFont    = 0x800,
    232 };
    233 
    234 static FlatFlags unpack_paint_flags(SkPaint* paint, uint32_t packed, SkFont* font) {
    235     uint32_t f = packed >> 16;
    236     paint->setAntiAlias((f & kAA_PaintFlagForPaint) != 0);
    237     paint->setDither((f & kDither_PaintFlagForPaint) != 0);
    238     if (font) {
    239         font->setEmbolden((f & kFakeBold_PaintFlagForFont) != 0);
    240         font->setLinearMetrics((f & kLinear_PaintFlagForFont) != 0);
    241         font->setSubpixel((f & kSubpixel_PaintFlagForFont) != 0);
    242         font->setEmbeddedBitmaps((f & kEmbeddedBitmap_PaintFlagForFont) != 0);
    243         font->setForceAutoHinting((f & kAutoHinting_PaintFlagForFont) != 0);
    244 
    245         font->setHinting((SkFontHinting)((packed >> 14) & BPF_Mask(kHint_BPF)));
    246 
    247         if (f & kAA_PaintFlagForPaint) {
    248             if (f & kLCD_PaintFlagForFont) {
    249                 font->setEdging(SkFont::Edging::kSubpixelAntiAlias);
    250             } else {
    251                 font->setEdging(SkFont::Edging::kAntiAlias);
    252             }
    253         } else {
    254             font->setEdging(SkFont::Edging::kAlias);
    255         }
    256     }
    257 
    258     paint->setFilterQuality((SkFilterQuality)((packed >> 10) & BPF_Mask(kFilter_BPF)));
    259     return (FlatFlags)(packed & kFlatFlagMask);
    260 }
    261 
    262 template <typename T> uint32_t shift_bits(T value, unsigned shift, unsigned bits) {
    263     SkASSERT(shift + bits <= 32);
    264     uint32_t v = static_cast<uint32_t>(value);
    265     ASSERT_FITS_IN(v, bits);
    266     return v << shift;
    267 }
    268 
    269 /*  Packing the paint
    270  flags :  8  // 2...
    271  blend :  8  // 30+
    272  cap   :  2  // 3
    273  join  :  2  // 3
    274  style :  2  // 3
    275  filter:  2  // 4
    276  flat  :  8  // 1...
    277  total : 32
    278  */
    279 static uint32_t pack_v68(const SkPaint& paint, unsigned flatFlags) {
    280     uint32_t packed = 0;
    281     packed |= shift_bits(((unsigned)paint.isDither() << 1) |
    282                           (unsigned)paint.isAntiAlias(), 0, 8);
    283     packed |= shift_bits(paint.getBlendMode(),      8, 8);
    284     packed |= shift_bits(paint.getStrokeCap(),     16, 2);
    285     packed |= shift_bits(paint.getStrokeJoin(),    18, 2);
    286     packed |= shift_bits(paint.getStyle(),         20, 2);
    287     packed |= shift_bits(paint.getFilterQuality(), 22, 2);
    288     packed |= shift_bits(flatFlags,                24, 8);
    289     return packed;
    290 }
    291 
    292 static uint32_t unpack_v68(SkPaint* paint, uint32_t packed, SkSafeRange& safe) {
    293     paint->setAntiAlias((packed & 1) != 0);
    294     paint->setDither((packed & 2) != 0);
    295     packed >>= 8;
    296     paint->setBlendMode(safe.checkLE(packed & 0xFF, SkBlendMode::kLastMode));
    297     packed >>= 8;
    298     paint->setStrokeCap(safe.checkLE(packed & 0x3, SkPaint::kLast_Cap));
    299     packed >>= 2;
    300     paint->setStrokeJoin(safe.checkLE(packed & 0x3, SkPaint::kLast_Join));
    301     packed >>= 2;
    302     paint->setStyle(safe.checkLE(packed & 0x3, SkPaint::kStrokeAndFill_Style));
    303     packed >>= 2;
    304     paint->setFilterQuality(safe.checkLE(packed & 0x3, kLast_SkFilterQuality));
    305     packed >>= 2;
    306     return packed;
    307 }
    308 
    309 /*  To save space/time, we analyze the paint, and write a truncated version of
    310     it if there are not tricky elements like shaders, etc.
    311  */
    312 void SkPaintPriv::Flatten(const SkPaint& paint, SkWriteBuffer& buffer) {
    313     uint8_t flatFlags = 0;
    314 
    315     if (paint.getPathEffect() ||
    316         paint.getShader() ||
    317         paint.getMaskFilter() ||
    318         paint.getColorFilter() ||
    319         paint.getLooper() ||
    320         paint.getImageFilter()) {
    321         flatFlags |= kHasEffects_FlatFlag;
    322     }
    323 
    324     buffer.writeScalar(paint.getStrokeWidth());
    325     buffer.writeScalar(paint.getStrokeMiter());
    326     buffer.writeColor4f(paint.getColor4f());
    327 
    328     buffer.write32(pack_v68(paint, flatFlags));
    329 
    330     if (flatFlags & kHasEffects_FlatFlag) {
    331         buffer.writeFlattenable(paint.getPathEffect());
    332         buffer.writeFlattenable(paint.getShader());
    333         buffer.writeFlattenable(paint.getMaskFilter());
    334         buffer.writeFlattenable(paint.getColorFilter());
    335         buffer.writeFlattenable(paint.getLooper());
    336         buffer.writeFlattenable(paint.getImageFilter());
    337     }
    338 }
    339 
    340 SkReadPaintResult SkPaintPriv::Unflatten_PreV68(SkPaint* paint, SkReadBuffer& buffer, SkFont* font) {
    341     SkSafeRange safe;
    342 
    343     {
    344         SkScalar sz = buffer.readScalar();
    345         SkScalar sx = buffer.readScalar();
    346         SkScalar kx = buffer.readScalar();
    347         if (font) {
    348             font->setSize(sz);
    349             font->setScaleX(sx);
    350             font->setSkewX(kx);
    351         }
    352     }
    353 
    354     paint->setStrokeWidth(buffer.readScalar());
    355     paint->setStrokeMiter(buffer.readScalar());
    356     if (buffer.isVersionLT(SkReadBuffer::kFloat4PaintColor_Version)) {
    357         paint->setColor(buffer.readColor());
    358     } else {
    359         SkColor4f color;
    360         buffer.readColor4f(&color);
    361         paint->setColor4f(color, sk_srgb_singleton());
    362     }
    363 
    364     unsigned flatFlags = unpack_paint_flags(paint, buffer.readUInt(), font);
    365 
    366     uint32_t tmp = buffer.readUInt();
    367     paint->setStrokeCap(safe.checkLE((tmp >> 24) & 0xFF, SkPaint::kLast_Cap));
    368     paint->setStrokeJoin(safe.checkLE((tmp >> 16) & 0xFF, SkPaint::kLast_Join));
    369     paint->setStyle(safe.checkLE((tmp >> 12) & 0xF, SkPaint::kStrokeAndFill_Style));
    370     paint->setBlendMode(safe.checkLE(tmp & 0xFF, SkBlendMode::kLastMode));
    371 
    372     sk_sp<SkTypeface> tf;
    373     if (flatFlags & kHasTypeface_FlatFlag) {
    374         tf = buffer.readTypeface();
    375     }
    376     if (font) {
    377         font->setTypeface(tf);
    378     }
    379 
    380     if (flatFlags & kHasEffects_FlatFlag) {
    381         paint->setPathEffect(buffer.readPathEffect());
    382         paint->setShader(buffer.readShader());
    383         paint->setMaskFilter(buffer.readMaskFilter());
    384         paint->setColorFilter(buffer.readColorFilter());
    385         (void)buffer.read32();  // use to be SkRasterizer
    386         paint->setLooper(buffer.readDrawLooper());
    387         paint->setImageFilter(buffer.readImageFilter());
    388     } else {
    389         paint->setPathEffect(nullptr);
    390         paint->setShader(nullptr);
    391         paint->setMaskFilter(nullptr);
    392         paint->setColorFilter(nullptr);
    393         paint->setLooper(nullptr);
    394         paint->setImageFilter(nullptr);
    395     }
    396 
    397     if (!buffer.validate(safe)) {
    398         paint->reset();
    399         return kFailed_ReadPaint;
    400     }
    401     return kSuccess_PaintAndFont;
    402 }
    403 
    404 SkReadPaintResult SkPaintPriv::Unflatten(SkPaint* paint, SkReadBuffer& buffer, SkFont* font) {
    405     if (buffer.isVersionLT(SkReadBuffer::kPaintDoesntSerializeFonts_Version)) {
    406         return Unflatten_PreV68(paint, buffer, font);
    407     }
    408 
    409     SkSafeRange safe;
    410 
    411     paint->setStrokeWidth(buffer.readScalar());
    412     paint->setStrokeMiter(buffer.readScalar());
    413     {
    414         SkColor4f color;
    415         buffer.readColor4f(&color);
    416         paint->setColor4f(color, sk_srgb_singleton());
    417     }
    418 
    419     unsigned flatFlags = unpack_v68(paint, buffer.readUInt(), safe);
    420 
    421     if (flatFlags & kHasEffects_FlatFlag) {
    422         paint->setPathEffect(buffer.readPathEffect());
    423         paint->setShader(buffer.readShader());
    424         paint->setMaskFilter(buffer.readMaskFilter());
    425         paint->setColorFilter(buffer.readColorFilter());
    426         paint->setLooper(buffer.readDrawLooper());
    427         paint->setImageFilter(buffer.readImageFilter());
    428     } else {
    429         paint->setPathEffect(nullptr);
    430         paint->setShader(nullptr);
    431         paint->setMaskFilter(nullptr);
    432         paint->setColorFilter(nullptr);
    433         paint->setLooper(nullptr);
    434         paint->setImageFilter(nullptr);
    435     }
    436 
    437     if (!buffer.validate(safe)) {
    438         paint->reset();
    439         return kFailed_ReadPaint;
    440     }
    441     return kSuccess_JustPaint;
    442 }
    443 
    444 ///////////////////////////////////////////////////////////////////////////////
    445 
    446 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
    447                           SkScalar resScale) const {
    448     if (!src.isFinite()) {
    449         dst->reset();
    450         return false;
    451     }
    452 
    453     SkStrokeRec rec(*this, resScale);
    454 
    455     const SkPath* srcPtr = &src;
    456     SkPath tmpPath;
    457 
    458     if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec, cullRect)) {
    459         srcPtr = &tmpPath;
    460     }
    461 
    462     if (!rec.applyToPath(dst, *srcPtr)) {
    463         if (srcPtr == &tmpPath) {
    464             // If path's were copy-on-write, this trick would not be needed.
    465             // As it is, we want to save making a deep-copy from tmpPath -> dst
    466             // since we know we're just going to delete tmpPath when we return,
    467             // so the swap saves that copy.
    468             dst->swap(tmpPath);
    469         } else {
    470             *dst = *srcPtr;
    471         }
    472     }
    473 
    474     if (!dst->isFinite()) {
    475         dst->reset();
    476         return false;
    477     }
    478     return !rec.isHairlineStyle();
    479 }
    480 
    481 bool SkPaint::canComputeFastBounds() const {
    482     if (this->getLooper()) {
    483         return this->getLooper()->canComputeFastBounds(*this);
    484     }
    485     if (this->getImageFilter() && !this->getImageFilter()->canComputeFastBounds()) {
    486         return false;
    487     }
    488     return true;
    489 }
    490 
    491 const SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
    492                                            SkRect* storage,
    493                                            Style style) const {
    494     SkASSERT(storage);
    495 
    496     const SkRect* src = &origSrc;
    497 
    498     if (this->getLooper()) {
    499         SkASSERT(this->getLooper()->canComputeFastBounds(*this));
    500         this->getLooper()->computeFastBounds(*this, *src, storage);
    501         return *storage;
    502     }
    503 
    504     SkRect tmpSrc;
    505     if (this->getPathEffect()) {
    506         this->getPathEffect()->computeFastBounds(&tmpSrc, origSrc);
    507         src = &tmpSrc;
    508     }
    509 
    510     SkScalar radius = SkStrokeRec::GetInflationRadius(*this, style);
    511     *storage = src->makeOutset(radius, radius);
    512 
    513     if (this->getMaskFilter()) {
    514         as_MFB(this->getMaskFilter())->computeFastBounds(*storage, storage);
    515     }
    516 
    517     if (this->getImageFilter()) {
    518         *storage = this->getImageFilter()->computeFastBounds(*storage);
    519     }
    520 
    521     return *storage;
    522 }
    523 
    524 ///////////////////////////////////////////////////////////////////////////////
    525 
    526 // return true if the filter exists, and may affect alpha
    527 static bool affects_alpha(const SkColorFilter* cf) {
    528     return cf && !(cf->getFlags() & SkColorFilter::kAlphaUnchanged_Flag);
    529 }
    530 
    531 // return true if the filter exists, and may affect alpha
    532 static bool affects_alpha(const SkImageFilter* imf) {
    533     // TODO: check if we should allow imagefilters to broadcast that they don't affect alpha
    534     // ala colorfilters
    535     return imf != nullptr;
    536 }
    537 
    538 bool SkPaint::nothingToDraw() const {
    539     if (fDrawLooper) {
    540         return false;
    541     }
    542     switch (this->getBlendMode()) {
    543         case SkBlendMode::kSrcOver:
    544         case SkBlendMode::kSrcATop:
    545         case SkBlendMode::kDstOut:
    546         case SkBlendMode::kDstOver:
    547         case SkBlendMode::kPlus:
    548             if (0 == this->getAlpha()) {
    549                 return !affects_alpha(fColorFilter.get()) && !affects_alpha(fImageFilter.get());
    550             }
    551             break;
    552         case SkBlendMode::kDst:
    553             return true;
    554         default:
    555             break;
    556     }
    557     return false;
    558 }
    559 
    560 uint32_t SkPaint::getHash() const {
    561     // We're going to hash 6 pointers and 6 floats, finishing up with fBitfields,
    562     // so fBitfields should be 6 pointers and 6 floats from the start.
    563     static_assert(offsetof(SkPaint, fBitfieldsUInt) == 6 * sizeof(void*) + 6 * sizeof(float),
    564                   "SkPaint_notPackedTightly");
    565     return SkOpts::hash(reinterpret_cast<const uint32_t*>(this),
    566                         offsetof(SkPaint, fBitfieldsUInt) + sizeof(fBitfieldsUInt));
    567 }
    568