don/t modify const paint, since it could be used in different threads

git-svn-id: http://skia.googlecode.com/svn/trunk@1953 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2011-07-25 19:41:22 +00:00
parent aab1fd921c
commit 40c2ba27b6

View File

@ -67,17 +67,12 @@ private:
SkBounder* fBounder; SkBounder* fBounder;
}; };
static SkPoint* rect_points(SkRect& r, int index) {
SkASSERT((unsigned)index < 2);
return &((SkPoint*)(void*)&r)[index];
}
/** Helper for allocating small blitters on the stack. /** Helper for allocating small blitters on the stack.
*/ */
#define kBlitterStorageLongCount (sizeof(SkBitmapProcShader) >> 2) #define kBlitterStorageLongCount (sizeof(SkBitmapProcShader) >> 2)
class SkAutoBlitterChoose { class SkAutoBlitterChoose : SkNoncopyable {
public: public:
SkAutoBlitterChoose() { SkAutoBlitterChoose() {
fBlitter = NULL; fBlitter = NULL;
@ -113,23 +108,30 @@ SkAutoBlitterChoose::~SkAutoBlitterChoose() {
} }
} }
class SkAutoBitmapShaderInstall { /**
* Since we are providing the storage for the shader (to avoid the perf cost
* of calling new) we insist that in our destructor we can account for all
* owners of the shader.
*/
class SkAutoBitmapShaderInstall : SkNoncopyable {
public: public:
SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint* paint) SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint)
: fPaint((SkPaint*)paint) { : fPaint(paint) /* makes a copy of the paint */ {
fPrevShader = paint->getShader(); fPaint.setShader(SkShader::CreateBitmapShader(src,
SkSafeRef(fPrevShader);
fPaint->setShader(SkShader::CreateBitmapShader( src,
SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
fStorage, sizeof(fStorage))); fStorage, sizeof(fStorage)));
// we deliberately left the shader with an owner-count of 2
SkASSERT(2 == fPaint.getShader()->getRefCnt());
} }
~SkAutoBitmapShaderInstall() { ~SkAutoBitmapShaderInstall() {
SkShader* shader = fPaint->getShader(); SkShader* shader = fPaint.getShader();
// since we manually destroy shader, we insist that owners == 2
SkASSERT(2 == shader->getRefCnt());
fPaint->setShader(fPrevShader); fPaint.setShader(NULL); // unref the shader by 1
SkSafeUnref(fPrevShader);
// now destroy to take care of the 2nd owner-count
if ((void*)shader == (void*)fStorage) { if ((void*)shader == (void*)fStorage) {
shader->~SkShader(); shader->~SkShader();
} else { } else {
@ -137,33 +139,14 @@ public:
} }
} }
// return the new paint that has the shader applied
const SkPaint& paintWithShader() const { return fPaint; }
private: private:
SkPaint* fPaint; SkPaint fPaint; // copy of caller's paint (which we then modify)
SkShader* fPrevShader;
uint32_t fStorage[kBlitterStorageLongCount]; uint32_t fStorage[kBlitterStorageLongCount];
}; };
class SkAutoPaintStyleRestore {
public:
SkAutoPaintStyleRestore(const SkPaint& paint, SkPaint::Style style)
: fPaint((SkPaint&)paint) {
fStyle = paint.getStyle(); // record the old
fPaint.setStyle(style); // change it to the specified style
}
~SkAutoPaintStyleRestore() {
fPaint.setStyle(fStyle); // restore the old
}
private:
SkPaint& fPaint;
SkPaint::Style fStyle;
// illegal
SkAutoPaintStyleRestore(const SkAutoPaintStyleRestore&);
SkAutoPaintStyleRestore& operator=(const SkAutoPaintStyleRestore&);
};
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
SkDraw::SkDraw() { SkDraw::SkDraw() {
@ -628,12 +611,13 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
switch (mode) { switch (mode) {
case SkCanvas::kPoints_PointMode: { case SkCanvas::kPoints_PointMode: {
// temporarily mark the paint as filling. // temporarily mark the paint as filling.
SkAutoPaintStyleRestore restore(paint, SkPaint::kFill_Style); SkPaint newPaint(paint);
newPaint.setStyle(SkPaint::kFill_Style);
SkScalar width = paint.getStrokeWidth(); SkScalar width = newPaint.getStrokeWidth();
SkScalar radius = SkScalarHalf(width); SkScalar radius = SkScalarHalf(width);
if (paint.getStrokeCap() == SkPaint::kRound_Cap) { if (newPaint.getStrokeCap() == SkPaint::kRound_Cap) {
SkPath path; SkPath path;
SkMatrix preMatrix; SkMatrix preMatrix;
@ -643,10 +627,11 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
// pass true for the last point, since we can modify // pass true for the last point, since we can modify
// then path then // then path then
if (fDevice) { if (fDevice) {
fDevice->drawPath(*this, path, paint, &preMatrix, fDevice->drawPath(*this, path, newPaint, &preMatrix,
(count-1) == i); (count-1) == i);
} else { } else {
this->drawPath(path, paint, &preMatrix, (count-1) == i); this->drawPath(path, newPaint, &preMatrix,
(count-1) == i);
} }
} }
} else { } else {
@ -658,9 +643,9 @@ void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
r.fRight = r.fLeft + width; r.fRight = r.fLeft + width;
r.fBottom = r.fTop + width; r.fBottom = r.fTop + width;
if (fDevice) { if (fDevice) {
fDevice->drawRect(*this, r, paint); fDevice->drawRect(*this, r, newPaint);
} else { } else {
this->drawRect(r, paint); this->drawRect(r, newPaint);
} }
} }
} }
@ -740,6 +725,11 @@ SkDraw::RectType SkDraw::ComputeRectType(const SkPaint& paint,
return rtype; return rtype;
} }
static SkPoint* rect_points(SkRect& r, int index) {
SkASSERT((unsigned)index < 2);
return &((SkPoint*)(void*)&r)[index];
}
void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const { void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const {
SkDEBUGCODE(this->validate();) SkDEBUGCODE(this->validate();)
@ -1097,11 +1087,11 @@ void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap,
// we manually build a shader and draw that into our new mask // we manually build a shader and draw that into our new mask
SkPaint tmpPaint; SkPaint tmpPaint;
tmpPaint.setFlags(paint.getFlags()); tmpPaint.setFlags(paint.getFlags());
SkAutoBitmapShaderInstall install(bitmap, &tmpPaint); SkAutoBitmapShaderInstall install(bitmap, tmpPaint);
SkRect rr; SkRect rr;
rr.set(0, 0, SkIntToScalar(bitmap.width()), rr.set(0, 0, SkIntToScalar(bitmap.width()),
SkIntToScalar(bitmap.height())); SkIntToScalar(bitmap.height()));
c.drawRect(rr, tmpPaint); c.drawRect(rr, install.paintWithShader());
} }
this->drawDevMask(mask, paint); this->drawDevMask(mask, paint);
} }
@ -1125,14 +1115,14 @@ static bool clipped_out(const SkMatrix& matrix, const SkRegion& clip,
} }
void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
const SkPaint& paint) const { const SkPaint& origPaint) const {
SkDEBUGCODE(this->validate();) SkDEBUGCODE(this->validate();)
// nothing to draw // nothing to draw
if (fClip->isEmpty() || if (fClip->isEmpty() ||
bitmap.width() == 0 || bitmap.height() == 0 || bitmap.width() == 0 || bitmap.height() == 0 ||
bitmap.getConfig() == SkBitmap::kNo_Config || bitmap.getConfig() == SkBitmap::kNo_Config ||
(paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { (origPaint.getAlpha() == 0 && origPaint.getXfermode() == NULL)) {
return; return;
} }
@ -1143,7 +1133,8 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
} }
#endif #endif
SkAutoPaintStyleRestore restore(paint, SkPaint::kFill_Style); SkPaint paint(origPaint);
paint.setStyle(SkPaint::kFill_Style);
SkMatrix matrix; SkMatrix matrix;
if (!matrix.setConcat(*fMatrix, prematrix)) { if (!matrix.setConcat(*fMatrix, prematrix)) {
@ -1208,25 +1199,25 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
if (bitmap.getConfig() == SkBitmap::kA8_Config) { if (bitmap.getConfig() == SkBitmap::kA8_Config) {
draw.drawBitmapAsMask(bitmap, paint); draw.drawBitmapAsMask(bitmap, paint);
} else { } else {
SkAutoBitmapShaderInstall install(bitmap, &paint); SkAutoBitmapShaderInstall install(bitmap, paint);
SkRect r; SkRect r;
r.set(0, 0, SkIntToScalar(bitmap.width()), r.set(0, 0, SkIntToScalar(bitmap.width()),
SkIntToScalar(bitmap.height())); SkIntToScalar(bitmap.height()));
// is this ok if paint has a rasterizer? // is this ok if paint has a rasterizer?
draw.drawRect(r, paint); draw.drawRect(r, install.paintWithShader());
} }
} }
void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y, void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
const SkPaint& paint) const { const SkPaint& origPaint) const {
SkDEBUGCODE(this->validate();) SkDEBUGCODE(this->validate();)
// nothing to draw // nothing to draw
if (fClip->isEmpty() || if (fClip->isEmpty() ||
bitmap.width() == 0 || bitmap.height() == 0 || bitmap.width() == 0 || bitmap.height() == 0 ||
bitmap.getConfig() == SkBitmap::kNo_Config || bitmap.getConfig() == SkBitmap::kNo_Config ||
(paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { (origPaint.getAlpha() == 0 && origPaint.getXfermode() == NULL)) {
return; return;
} }
@ -1237,7 +1228,8 @@ void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
return; // nothing to draw return; // nothing to draw
} }
SkAutoPaintStyleRestore restore(paint, SkPaint::kFill_Style); SkPaint paint(origPaint);
paint.setStyle(SkPaint::kFill_Style);
if (NULL == paint.getColorFilter()) { if (NULL == paint.getColorFilter()) {
uint32_t storage[kBlitterStorageLongCount]; uint32_t storage[kBlitterStorageLongCount];
@ -1262,7 +1254,8 @@ void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
} }
} }
SkAutoBitmapShaderInstall install(bitmap, &paint); SkAutoBitmapShaderInstall install(bitmap, paint);
const SkPaint& shaderPaint = install.paintWithShader();
SkMatrix matrix; SkMatrix matrix;
SkRect r; SkRect r;
@ -1272,14 +1265,14 @@ void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
// tell the shader our offset // tell the shader our offset
matrix.setTranslate(r.fLeft, r.fTop); matrix.setTranslate(r.fLeft, r.fTop);
paint.getShader()->setLocalMatrix(matrix); shaderPaint.getShader()->setLocalMatrix(matrix);
SkDraw draw(*this); SkDraw draw(*this);
matrix.reset(); matrix.reset();
draw.fMatrix = &matrix; draw.fMatrix = &matrix;
// call ourself with a rect // call ourself with a rect
// is this OK if paint has a rasterizer? // is this OK if paint has a rasterizer?
draw.drawRect(r, paint); draw.drawRect(r, shaderPaint);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////