diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h index a931ccd96c..f4b325fea5 100644 --- a/include/core/SkPaint.h +++ b/include/core/SkPaint.h @@ -89,9 +89,7 @@ public: return static_cast(fHinting); } - void setHinting(Hinting hintingLevel) { - fHinting = hintingLevel; - } + void setHinting(Hinting hintingLevel); /** Specifies the bit values that are stored in the paint's flags. */ @@ -817,6 +815,13 @@ public: void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y, SkPath* path) const; +#ifdef ANDROID + const SkGlyph& getUnicharMetrics(SkUnichar); + const void* findImage(const SkGlyph&); + + uint32_t getGenerationID() const; +#endif + private: SkTypeface* fTypeface; SkScalar fTextSize; @@ -841,6 +846,9 @@ private: unsigned fStyle : 2; unsigned fTextEncoding : 2; // 3 values unsigned fHinting : 2; +#ifdef ANDROID + uint32_t fGenerationID; +#endif SkDrawCacheProc getDrawCacheProc() const; SkMeasureCacheProc getMeasureCacheProc(TextBufferDirection dir, diff --git a/include/core/SkPath.h b/include/core/SkPath.h index 34f30b10c4..d9a7093a81 100644 --- a/include/core/SkPath.h +++ b/include/core/SkPath.h @@ -20,6 +20,14 @@ #include "SkMatrix.h" #include "SkTDArray.h" +#ifdef ANDROID +#define GEN_ID_INC fGenerationID++ +#define GEN_ID_PTR_INC(ptr) ptr->fGenerationID++ +#else +#define GEN_ID_INC +#define GEN_ID_PTR_INC(ptr) +#endif + class SkFlattenableReadBuffer; class SkFlattenableWriteBuffer; class SkAutoPathBoundsUpdate; @@ -72,7 +80,10 @@ public: @param ft The new fill type for this path */ - void setFillType(FillType ft) { fFillType = SkToU8(ft); } + void setFillType(FillType ft) { + fFillType = SkToU8(ft); + GEN_ID_INC; + } /** Returns true if the filltype is one of the Inverse variants */ bool isInverseFillType() const { return (fFillType & 2) != 0; } @@ -80,7 +91,10 @@ public: /** Toggle between inverse and normal filltypes. This reverse the return value of isInverseFillType() */ - void toggleInverseFillType() { fFillType ^= 2; } + void toggleInverseFillType() { + fFillType ^= 2; + GEN_ID_INC; + } /** Returns true if the path is flagged as being convex. This is not a confirmed by any analysis, it is just the value set earlier. @@ -92,7 +106,10 @@ public: not convex can give undefined results when drawn. Paths default to isConvex == false */ - void setIsConvex(bool isConvex) { fIsConvex = (isConvex != 0); } + void setIsConvex(bool isConvex) { + fIsConvex = (isConvex != 0); + GEN_ID_INC; + } /** Clear any lines and curves from the path, making it empty. This frees up internal storage associated with those segments. @@ -571,6 +588,10 @@ public: */ void subdivide(SkScalar dist, bool bendLines, SkPath* dst = NULL) const; +#ifdef ANDROID + uint32_t getGenerationID() const; +#endif + SkDEBUGCODE(void validate() const;) private: @@ -580,6 +601,9 @@ private: mutable uint8_t fBoundsIsDirty; uint8_t fFillType; uint8_t fIsConvex; +#ifdef ANDROID + uint32_t fGenerationID; +#endif // called, if dirty, by getBounds() void computeBounds() const; diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index 1e406415b5..95b8ed3419 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -35,6 +35,14 @@ #define SK_DefaultFlags 0 //(kNativeHintsText_Flag) +#ifdef ANDROID +#define GEN_ID_INC fGenerationID++ +#define GEN_ID_INC_EVAL(expression) if (expression) { fGenerationID++; } +#else +#define GEN_ID_INC +#define GEN_ID_INC_EVAL(expression) +#endif + SkPaint::SkPaint() { // since we may have padding, we zero everything so that our memcmp() call // in operator== will work correctly. @@ -65,6 +73,9 @@ SkPaint::SkPaint() { fStyle = kFill_Style; fTextEncoding = kUTF8_TextEncoding; fHinting = kNormal_Hinting; +#ifdef ANDROID + fGenerationID = 0; +#endif } SkPaint::SkPaint(const SkPaint& src) { @@ -112,7 +123,13 @@ SkPaint& SkPaint::operator=(const SkPaint& src) { SkSafeUnref(fRasterizer); SkSafeUnref(fLooper); +#ifdef ANDROID + uint32_t oldGenerationID = fGenerationID; +#endif memcpy(this, &src, sizeof(src)); +#ifdef ANDROID + fGenerationID = oldGenerationID + 1; +#endif return *this; } @@ -124,109 +141,135 @@ int operator==(const SkPaint& a, const SkPaint& b) { void SkPaint::reset() { SkPaint init; +#ifdef ANDROID + uint32_t oldGenerationID = fGenerationID; +#endif *this = init; +#ifdef ANDROID + fGenerationID = oldGenerationID + 1; +#endif +} + +#ifdef ANDROID +uint32_t SkPaint::getGenerationID() const { + return fGenerationID; +} +#endif + +void SkPaint::setHinting(Hinting hintingLevel) { + GEN_ID_INC_EVAL((unsigned) hintingLevel != fHinting); + fHinting = hintingLevel; } void SkPaint::setFlags(uint32_t flags) { + GEN_ID_INC_EVAL(fFlags != flags); fFlags = flags; } void SkPaint::setAntiAlias(bool doAA) { + GEN_ID_INC_EVAL(doAA != isAntiAlias()); this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag)); } void SkPaint::setDither(bool doDither) { + GEN_ID_INC_EVAL(doDither != isDither()); this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag)); } void SkPaint::setSubpixelText(bool doSubpixel) { + GEN_ID_INC_EVAL(doSubpixel != isSubpixelText()); this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag)); } void SkPaint::setLCDRenderText(bool doLCDRender) { + GEN_ID_INC_EVAL(doLCDRender != isLCDRenderText()); this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag)); } void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) { + GEN_ID_INC_EVAL(doEmbeddedBitmapText != isEmbeddedBitmapText()); this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag)); } void SkPaint::setAutohinted(bool useAutohinter) { + GEN_ID_INC_EVAL(useAutohinter != isAutohinted()); this->setFlags(SkSetClearMask(fFlags, useAutohinter, kAutoHinting_Flag)); } void SkPaint::setLinearText(bool doLinearText) { + GEN_ID_INC_EVAL(doLinearText != isLinearText()); this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag)); } void SkPaint::setUnderlineText(bool doUnderline) { + GEN_ID_INC_EVAL(doUnderline != isUnderlineText()); this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag)); } void SkPaint::setStrikeThruText(bool doStrikeThru) { + GEN_ID_INC_EVAL(doStrikeThru != isStrikeThruText()); this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag)); } void SkPaint::setFakeBoldText(bool doFakeBold) { + GEN_ID_INC_EVAL(doFakeBold != isFakeBoldText()); this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag)); } void SkPaint::setDevKernText(bool doDevKern) { + GEN_ID_INC_EVAL(doDevKern != isDevKernText()); this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag)); } void SkPaint::setFilterBitmap(bool doFilter) { + GEN_ID_INC_EVAL(doFilter != isFilterBitmap()); this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag)); } void SkPaint::setStyle(Style style) { if ((unsigned)style < kStyleCount) { + GEN_ID_INC_EVAL((unsigned)style != fStyle); fStyle = style; + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setStyle(%d) out of range\n", style);) } -#ifdef SK_DEBUG - else { - SkDebugf("SkPaint::setStyle(%d) out of range\n", style); - } -#endif } void SkPaint::setColor(SkColor color) { + GEN_ID_INC_EVAL(color != fColor); fColor = color; } void SkPaint::setAlpha(U8CPU a) { - fColor = SkColorSetARGB(a, SkColorGetR(fColor), - SkColorGetG(fColor), SkColorGetB(fColor)); + this->setColor(SkColorSetARGB(a, SkColorGetR(fColor), + SkColorGetG(fColor), SkColorGetB(fColor))); } void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) { - fColor = SkColorSetARGB(a, r, g, b); + this->setColor(SkColorSetARGB(a, r, g, b)); } void SkPaint::setStrokeWidth(SkScalar width) { if (width >= 0) { + GEN_ID_INC_EVAL(width != fWidth); fWidth = width; + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");) } -#ifdef SK_DEBUG - else { - SkDebugf("SkPaint::setStrokeWidth() called with negative value\n"); - } -#endif } void SkPaint::setStrokeMiter(SkScalar limit) { if (limit >= 0) { + GEN_ID_INC_EVAL(limit != fMiterLimit); fMiterLimit = limit; + } else { + SkDEBUGCODE(SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");) } -#ifdef SK_DEBUG - else { - SkDebugf("SkPaint::setStrokeMiter() called with negative value\n"); - } -#endif } void SkPaint::setStrokeCap(Cap ct) { if ((unsigned)ct < kCapCount) { + GEN_ID_INC_EVAL((unsigned)ct != fCapType); fCapType = SkToU8(ct); } else { SkDEBUGCODE(SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);) @@ -235,6 +278,7 @@ void SkPaint::setStrokeCap(Cap ct) { void SkPaint::setStrokeJoin(Join jt) { if ((unsigned)jt < kJoinCount) { + GEN_ID_INC_EVAL((unsigned)jt != fJoinType); fJoinType = SkToU8(jt); } else { SkDEBUGCODE(SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);) @@ -245,6 +289,7 @@ void SkPaint::setStrokeJoin(Join jt) { void SkPaint::setTextAlign(Align align) { if ((unsigned)align < kAlignCount) { + GEN_ID_INC_EVAL((unsigned)align != fTextAlign); fTextAlign = SkToU8(align); } else { SkDEBUGCODE(SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);) @@ -252,7 +297,8 @@ void SkPaint::setTextAlign(Align align) { } void SkPaint::setTextSize(SkScalar ts) { - if (ts >= 0) { + if (ts > 0) { + GEN_ID_INC_EVAL(ts != fTextSize); fTextSize = ts; } else { SkDEBUGCODE(SkDebugf("SkPaint::setTextSize() called with negative value\n");) @@ -260,15 +306,18 @@ void SkPaint::setTextSize(SkScalar ts) { } void SkPaint::setTextScaleX(SkScalar scaleX) { + GEN_ID_INC_EVAL(scaleX != fTextScaleX); fTextScaleX = scaleX; } void SkPaint::setTextSkewX(SkScalar skewX) { + GEN_ID_INC_EVAL(skewX != fTextSkewX); fTextSkewX = skewX; } void SkPaint::setTextEncoding(TextEncoding encoding) { if ((unsigned)encoding <= kGlyphID_TextEncoding) { + GEN_ID_INC_EVAL((unsigned)encoding != fTextEncoding); fTextEncoding = encoding; } else { SkDEBUGCODE(SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);) @@ -279,16 +328,19 @@ void SkPaint::setTextEncoding(TextEncoding encoding) { SkTypeface* SkPaint::setTypeface(SkTypeface* font) { SkRefCnt_SafeAssign(fTypeface, font); + GEN_ID_INC; return font; } SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) { SkRefCnt_SafeAssign(fRasterizer, r); + GEN_ID_INC; return r; } SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) { SkRefCnt_SafeAssign(fLooper, looper); + GEN_ID_INC; return looper; } @@ -297,6 +349,33 @@ SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) { #include "SkGlyphCache.h" #include "SkUtils.h" +static void DetachDescProc(const SkDescriptor* desc, void* context) { + *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc); +} + +#ifdef ANDROID +const SkGlyph& SkPaint::getUnicharMetrics(SkUnichar text) { + SkGlyphCache* cache; + descriptorProc(NULL, DetachDescProc, &cache, true); + + const SkGlyph& glyph = cache->getUnicharMetrics(text); + + SkGlyphCache::AttachCache(cache); + return glyph; +} + +const void* SkPaint::findImage(const SkGlyph& glyph) { + // See ::detachCache() + SkGlyphCache* cache; + descriptorProc(NULL, DetachDescProc, &cache, true); + + const void* image = cache->findImage(glyph); + + SkGlyphCache::AttachCache(cache); + return image; +} +#endif + int SkPaint::textToGlyphs(const void* textData, size_t byteLength, uint16_t glyphs[]) const { if (byteLength == 0) { @@ -1300,10 +1379,6 @@ void SkPaint::descriptorProc(const SkMatrix* deviceMatrix, proc(desc, context); } -static void DetachDescProc(const SkDescriptor* desc, void* context) { - *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc); -} - SkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const { SkGlyphCache* cache; this->descriptorProc(deviceMatrix, DetachDescProc, &cache); @@ -1456,16 +1531,19 @@ void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) { /////////////////////////////////////////////////////////////////////////////// SkShader* SkPaint::setShader(SkShader* shader) { + GEN_ID_INC_EVAL(shader != fShader); SkRefCnt_SafeAssign(fShader, shader); return shader; } SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) { + GEN_ID_INC_EVAL(filter != fColorFilter); SkRefCnt_SafeAssign(fColorFilter, filter); return filter; } SkXfermode* SkPaint::setXfermode(SkXfermode* mode) { + GEN_ID_INC_EVAL(mode != fXfermode); SkRefCnt_SafeAssign(fXfermode, mode); return mode; } @@ -1473,15 +1551,18 @@ SkXfermode* SkPaint::setXfermode(SkXfermode* mode) { SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) { SkSafeUnref(fXfermode); fXfermode = SkXfermode::Create(mode); + GEN_ID_INC; return fXfermode; } SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) { + GEN_ID_INC_EVAL(effect != fPathEffect); SkRefCnt_SafeAssign(fPathEffect, effect); return effect; } SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) { + GEN_ID_INC_EVAL(filter != fMaskFilter); SkRefCnt_SafeAssign(fMaskFilter, filter); return filter; } diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp index 6aed6691c7..5ddc31ddad 100644 --- a/src/core/SkPath.cpp +++ b/src/core/SkPath.cpp @@ -97,11 +97,18 @@ static void compute_pt_bounds(SkRect* bounds, const SkTDArray& pts) { SkPath::SkPath() : fBoundsIsDirty(true), fFillType(kWinding_FillType) { fIsConvex = false; // really should be kUnknown +#ifdef ANDROID + fGenerationID = 0; +#endif } SkPath::SkPath(const SkPath& src) { SkDEBUGCODE(src.validate();) *this = src; +#ifdef ANDROID + // the assignment operator above increments the ID so correct for that here + fGenerationID--; +#endif } SkPath::~SkPath() { @@ -118,6 +125,7 @@ SkPath& SkPath::operator=(const SkPath& src) { fFillType = src.fFillType; fBoundsIsDirty = src.fBoundsIsDirty; fIsConvex = src.fIsConvex; + GEN_ID_INC; } SkDEBUGCODE(this->validate();) return *this; @@ -140,14 +148,22 @@ void SkPath::swap(SkPath& other) { SkTSwap(fFillType, other.fFillType); SkTSwap(fBoundsIsDirty, other.fBoundsIsDirty); SkTSwap(fIsConvex, other.fIsConvex); + GEN_ID_INC; } } +#ifdef ANDROID +uint32_t SkPath::getGenerationID() const { + return fGenerationID; +} +#endif + void SkPath::reset() { SkDEBUGCODE(this->validate();) fPts.reset(); fVerbs.reset(); + GEN_ID_INC; fBoundsIsDirty = true; fIsConvex = false; // really should be kUnknown } @@ -157,6 +173,7 @@ void SkPath::rewind() { fPts.rewind(); fVerbs.rewind(); + GEN_ID_INC; fBoundsIsDirty = true; fIsConvex = false; // really should be kUnknown } @@ -214,6 +231,7 @@ void SkPath::setLastPt(SkScalar x, SkScalar y) { this->moveTo(x, y); } else { fPts[count - 1].set(x, y); + GEN_ID_INC; } } @@ -251,6 +269,7 @@ void SkPath::moveTo(SkScalar x, SkScalar y) { } pt->set(x, y); + GEN_ID_INC; fBoundsIsDirty = true; } @@ -270,6 +289,7 @@ void SkPath::lineTo(SkScalar x, SkScalar y) { fPts.append()->set(x, y); *fVerbs.append() = kLine_Verb; + GEN_ID_INC; fBoundsIsDirty = true; } @@ -292,6 +312,7 @@ void SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) { pts[1].set(x2, y2); *fVerbs.append() = kQuad_Verb; + GEN_ID_INC; fBoundsIsDirty = true; } @@ -315,6 +336,7 @@ void SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, pts[2].set(x3, y3); *fVerbs.append() = kCubic_Verb; + GEN_ID_INC; fBoundsIsDirty = true; } @@ -336,6 +358,7 @@ void SkPath::close() { case kQuad_Verb: case kCubic_Verb: *fVerbs.append() = kClose_Verb; + GEN_ID_INC; break; default: // don't add a close if the prev wasn't a primitive @@ -953,6 +976,7 @@ void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const { matrix.mapRect(&dst->fBounds, fBounds); dst->fBoundsIsDirty = false; } else { + GEN_ID_PTR_INC(dst); dst->fBoundsIsDirty = true; } @@ -1260,6 +1284,7 @@ void SkPath::unflatten(SkFlattenableReadBuffer& buffer) { buffer.read(fPts.begin(), sizeof(SkPoint) * fPts.count()); buffer.read(fVerbs.begin(), fVerbs.count()); + GEN_ID_INC; fBoundsIsDirty = true; SkDEBUGCODE(this->validate();) diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp index ed220ea0ca..a7e2d165c0 100644 --- a/src/core/SkPicturePlayback.cpp +++ b/src/core/SkPicturePlayback.cpp @@ -528,6 +528,10 @@ void SkPicturePlayback::draw(SkCanvas& canvas) { SkipClipRec skipRect, skipRegion, skipPath; #endif +#ifdef ANDROID + SkAutoMutexAcquire autoMutex(fDrawMutex); +#endif + TextContainer text; fReader.rewind(); diff --git a/src/core/SkPicturePlayback.h b/src/core/SkPicturePlayback.h index ae9641a189..350df78363 100644 --- a/src/core/SkPicturePlayback.h +++ b/src/core/SkPicturePlayback.h @@ -13,6 +13,10 @@ #include "SkPictureFlat.h" #include "SkShape.h" +#ifdef ANDROID +#include "SkThread.h" +#endif + class SkPictureRecord; class SkStream; class SkWStream; @@ -172,6 +176,9 @@ private: SkRefCntPlayback fRCPlayback; SkTypefacePlayback fTFPlayback; SkFactoryPlayback* fFactoryPlayback; +#ifdef ANDROID + SkMutex fDrawMutex; +#endif }; #endif diff --git a/src/effects/SkBlurDrawLooper.cpp b/src/effects/SkBlurDrawLooper.cpp index 9290ead766..bde04edf50 100644 --- a/src/effects/SkBlurDrawLooper.cpp +++ b/src/effects/SkBlurDrawLooper.cpp @@ -73,7 +73,16 @@ bool SkBlurDrawLooper::next(SkCanvas* canvas, SkPaint* paint) { fState = kDone; return false; } +#ifdef ANDROID + SkColor blurColor; + blurColor = fBlurColor; + if (SkColorGetA(blurColor) == 255) { + blurColor = SkColorSetA(blurColor, paint->getAlpha()); + } + paint->setColor(blurColor); +#else paint->setColor(fBlurColor); +#endif paint->setMaskFilter(fBlur); paint->setColorFilter(fColorFilter); canvas->save(SkCanvas::kMatrix_SaveFlag); diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp index e058a362bb..280e0a10a5 100644 --- a/src/ports/SkFontHost_FreeType.cpp +++ b/src/ports/SkFontHost_FreeType.cpp @@ -39,10 +39,7 @@ // In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file. #include FT_SYNTHESIS_H #include FT_XFREE86_H - -#if defined(SK_SUPPORT_LCDTEXT) || true #include FT_LCD_FILTER_H -#endif #ifdef FT_ADVANCES_H #include FT_ADVANCES_H