extend fastbounds impls to include maskfilters and drawloopers. This allows
us to perform quick-rejects when drawing objects with shadows (esp. text). WebKit draws shadows w/ a looper (fg and shadow) and a maskfilter on the shadow layer. git-svn-id: http://skia.googlecode.com/svn/trunk@3103 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
bf6c1e4aff
commit
9efd9a048a
@ -45,6 +45,20 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual bool next(SkCanvas*, SkPaint* paint) = 0;
|
virtual bool next(SkCanvas*, SkPaint* paint) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fast bounds functions are used to enable the paint to be culled early
|
||||||
|
* in the drawing pipeline. If a subclass can support this feature it must
|
||||||
|
* return true for the canComputeFastBounds() function. If that function
|
||||||
|
* returns false then computeFastBounds behavior is undefined otherwise it
|
||||||
|
* is expected to have the following behavior. Given the parent paint and
|
||||||
|
* the parent's bounding rect the subclass must fill in and return the
|
||||||
|
* storage rect, where the storage rect is with the union of the src rect
|
||||||
|
* and the looper's bounding rect.
|
||||||
|
*/
|
||||||
|
virtual bool canComputeFastBounds(const SkPaint& paint);
|
||||||
|
virtual void computeFastBounds(const SkPaint& paint,
|
||||||
|
const SkRect& src, SkRect* dst);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SkDrawLooper() {}
|
SkDrawLooper() {}
|
||||||
SkDrawLooper(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
|
SkDrawLooper(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
|
||||||
|
@ -79,6 +79,19 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual BlurType asABlur(BlurInfo*) const;
|
virtual BlurType asABlur(BlurInfo*) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fast bounds function is used to enable the paint to be culled early
|
||||||
|
* in the drawing pipeline. This function accepts the current bounds of the
|
||||||
|
* paint as its src param and the filter adjust those bounds using its
|
||||||
|
* current mask and returns the result using the dest param. Callers are
|
||||||
|
* allowed to provide the same struct for both src and dest so each
|
||||||
|
* implementation must accomodate that behavior.
|
||||||
|
*
|
||||||
|
* The default impl calls filterMask with the src mask having no image,
|
||||||
|
* but subclasses may override this if they can compute the rect faster.
|
||||||
|
*/
|
||||||
|
virtual void computeFastBounds(const SkRect& src, SkRect* dest);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// empty for now, but lets get our subclass to remember to init us for the future
|
// empty for now, but lets get our subclass to remember to init us for the future
|
||||||
SkMaskFilter(SkFlattenableReadBuffer&) {}
|
SkMaskFilter(SkFlattenableReadBuffer&) {}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#define SkPaint_DEFINED
|
#define SkPaint_DEFINED
|
||||||
|
|
||||||
#include "SkColor.h"
|
#include "SkColor.h"
|
||||||
|
#include "SkDrawLooper.h"
|
||||||
#include "SkXfermode.h"
|
#include "SkXfermode.h"
|
||||||
|
|
||||||
class SkAutoGlyphCache;
|
class SkAutoGlyphCache;
|
||||||
@ -28,7 +29,6 @@ class SkPath;
|
|||||||
class SkPathEffect;
|
class SkPathEffect;
|
||||||
class SkRasterizer;
|
class SkRasterizer;
|
||||||
class SkShader;
|
class SkShader;
|
||||||
class SkDrawLooper;
|
|
||||||
class SkTypeface;
|
class SkTypeface;
|
||||||
|
|
||||||
typedef const SkGlyph& (*SkDrawCacheProc)(SkGlyphCache*, const char**,
|
typedef const SkGlyph& (*SkDrawCacheProc)(SkGlyphCache*, const char**,
|
||||||
@ -438,10 +438,11 @@ public:
|
|||||||
the bounds computation expensive.
|
the bounds computation expensive.
|
||||||
*/
|
*/
|
||||||
bool canComputeFastBounds() const {
|
bool canComputeFastBounds() const {
|
||||||
|
if (this->getLooper()) {
|
||||||
|
return this->getLooper()->canComputeFastBounds(*this);
|
||||||
|
}
|
||||||
// use bit-or since no need for early exit
|
// use bit-or since no need for early exit
|
||||||
return (reinterpret_cast<uintptr_t>(this->getMaskFilter()) |
|
return (reinterpret_cast<uintptr_t>(this->getRasterizer()) |
|
||||||
reinterpret_cast<uintptr_t>(this->getLooper()) |
|
|
||||||
reinterpret_cast<uintptr_t>(this->getRasterizer()) |
|
|
||||||
reinterpret_cast<uintptr_t>(this->getPathEffect())) == 0;
|
reinterpret_cast<uintptr_t>(this->getPathEffect())) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,8 +468,12 @@ public:
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const {
|
const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const {
|
||||||
return this->getStyle() == kFill_Style ? orig :
|
if (this->getStyle() == kFill_Style &&
|
||||||
this->computeStrokeFastBounds(orig, storage);
|
!this->getLooper() && !this->getMaskFilter()) {
|
||||||
|
return orig;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->doComputeFastBounds(orig, storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the paint's shader object.
|
/** Get the paint's shader object.
|
||||||
@ -892,8 +897,7 @@ private:
|
|||||||
void (*proc)(const SkDescriptor*, void*),
|
void (*proc)(const SkDescriptor*, void*),
|
||||||
void* context, bool ignoreGamma = false) const;
|
void* context, bool ignoreGamma = false) const;
|
||||||
|
|
||||||
const SkRect& computeStrokeFastBounds(const SkRect& orig,
|
const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage) const;
|
||||||
SkRect* storage) const;
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
kCanonicalTextSizeForPaths = 64
|
kCanonicalTextSizeForPaths = 64
|
||||||
|
@ -1397,11 +1397,15 @@ void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
|
|||||||
SkDEBUGCODE(bitmap.validate();)
|
SkDEBUGCODE(bitmap.validate();)
|
||||||
|
|
||||||
if (NULL == paint || paint->canComputeFastBounds()) {
|
if (NULL == paint || paint->canComputeFastBounds()) {
|
||||||
SkRect fastBounds;
|
SkRect bounds = {
|
||||||
fastBounds.set(x, y,
|
x, y,
|
||||||
x + SkIntToScalar(bitmap.width()),
|
x + SkIntToScalar(bitmap.width()),
|
||||||
y + SkIntToScalar(bitmap.height()));
|
y + SkIntToScalar(bitmap.height())
|
||||||
if (this->quickReject(fastBounds, paint2EdgeType(paint))) {
|
};
|
||||||
|
if (paint) {
|
||||||
|
(void)paint->computeFastBounds(bounds, &bounds);
|
||||||
|
}
|
||||||
|
if (this->quickReject(bounds, paint2EdgeType(paint))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1420,7 +1424,12 @@ void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkIRect* src
|
|||||||
|
|
||||||
// do this now, to avoid the cost of calling extract for RLE bitmaps
|
// do this now, to avoid the cost of calling extract for RLE bitmaps
|
||||||
if (NULL == paint || paint->canComputeFastBounds()) {
|
if (NULL == paint || paint->canComputeFastBounds()) {
|
||||||
if (this->quickReject(dst, paint2EdgeType(paint))) {
|
SkRect storage;
|
||||||
|
const SkRect* bounds = &dst;
|
||||||
|
if (paint) {
|
||||||
|
bounds = &paint->computeFastBounds(dst, &storage);
|
||||||
|
}
|
||||||
|
if (this->quickReject(*bounds, paint2EdgeType(paint))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,4 +56,20 @@ SkMaskFilter::BlurType SkMaskFilter::asABlur(BlurInfo*) const {
|
|||||||
return kNone_BlurType;
|
return kNone_BlurType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkMaskFilter::computeFastBounds(const SkRect& src, SkRect* dst) {
|
||||||
|
SkMask srcM, dstM;
|
||||||
|
|
||||||
|
srcM.fImage = NULL;
|
||||||
|
src.roundOut(&srcM.fBounds);
|
||||||
|
srcM.fRowBytes = 0;
|
||||||
|
srcM.fFormat = SkMask::kA8_Format;
|
||||||
|
|
||||||
|
SkIPoint margin; // ignored
|
||||||
|
if (this->filterMask(&dstM, srcM, SkMatrix::I(), &margin)) {
|
||||||
|
dst->set(dstM.fBounds);
|
||||||
|
} else {
|
||||||
|
dst->set(srcM.fBounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
#include "SkPaint.h"
|
#include "SkPaint.h"
|
||||||
#include "SkColorFilter.h"
|
#include "SkColorFilter.h"
|
||||||
#include "SkDrawLooper.h"
|
|
||||||
#include "SkFontHost.h"
|
#include "SkFontHost.h"
|
||||||
#include "SkImageFilter.h"
|
#include "SkImageFilter.h"
|
||||||
#include "SkMaskFilter.h"
|
#include "SkMaskFilter.h"
|
||||||
@ -1847,23 +1846,38 @@ bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const {
|
|||||||
return width != 0; // return true if we're filled, or false if we're hairline (width == 0)
|
return width != 0; // return true if we're filled, or false if we're hairline (width == 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
const SkRect& SkPaint::computeStrokeFastBounds(const SkRect& src,
|
const SkRect& SkPaint::doComputeFastBounds(const SkRect& src,
|
||||||
SkRect* storage) const {
|
SkRect* storage) const {
|
||||||
SkASSERT(storage);
|
SkASSERT(storage);
|
||||||
SkASSERT(this->getStyle() != SkPaint::kFill_Style);
|
|
||||||
|
|
||||||
// since we're stroked, outset the rect by the radius (and join type)
|
if (this->getLooper()) {
|
||||||
SkScalar radius = SkScalarHalf(this->getStrokeWidth());
|
SkASSERT(this->getLooper()->canComputeFastBounds(*this));
|
||||||
if (0 == radius) { // hairline
|
this->getLooper()->computeFastBounds(*this, src, storage);
|
||||||
radius = SK_Scalar1;
|
return *storage;
|
||||||
} else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
|
|
||||||
SkScalar scale = this->getStrokeMiter();
|
|
||||||
if (scale > SK_Scalar1) {
|
|
||||||
radius = SkScalarMul(radius, scale);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
storage->set(src.fLeft - radius, src.fTop - radius,
|
|
||||||
src.fRight + radius, src.fBottom + radius);
|
if (this->getStyle() != SkPaint::kFill_Style) {
|
||||||
|
// since we're stroked, outset the rect by the radius (and join type)
|
||||||
|
SkScalar radius = SkScalarHalf(this->getStrokeWidth());
|
||||||
|
if (0 == radius) { // hairline
|
||||||
|
radius = SK_Scalar1;
|
||||||
|
} else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
|
||||||
|
SkScalar scale = this->getStrokeMiter();
|
||||||
|
if (scale > SK_Scalar1) {
|
||||||
|
radius = SkScalarMul(radius, scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
storage->set(src.fLeft - radius, src.fTop - radius,
|
||||||
|
src.fRight + radius, src.fBottom + radius);
|
||||||
|
} else {
|
||||||
|
*storage = src;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the mask filter
|
||||||
|
if (this->getMaskFilter()) {
|
||||||
|
this->getMaskFilter()->computeFastBounds(*storage, storage);
|
||||||
|
}
|
||||||
|
|
||||||
return *storage;
|
return *storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2021,3 +2035,48 @@ bool SkImageFilter::asABlur(SkSize* sigma) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////
|
||||||
|
|
||||||
|
bool SkDrawLooper::canComputeFastBounds(const SkPaint& paint) {
|
||||||
|
SkCanvas canvas;
|
||||||
|
|
||||||
|
this->init(&canvas);
|
||||||
|
for (;;) {
|
||||||
|
SkPaint p(paint);
|
||||||
|
if (this->next(&canvas, &p)) {
|
||||||
|
p.setLooper(NULL);
|
||||||
|
if (!p.canComputeFastBounds()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkDrawLooper::computeFastBounds(const SkPaint& paint, const SkRect& src,
|
||||||
|
SkRect* dst) {
|
||||||
|
SkCanvas canvas;
|
||||||
|
|
||||||
|
this->init(&canvas);
|
||||||
|
for (bool firstTime = true;; firstTime = false) {
|
||||||
|
SkPaint p(paint);
|
||||||
|
if (this->next(&canvas, &p)) {
|
||||||
|
SkRect r(src);
|
||||||
|
|
||||||
|
p.setLooper(NULL);
|
||||||
|
p.computeFastBounds(r, &r);
|
||||||
|
canvas.getTotalMatrix().mapRect(&r);
|
||||||
|
|
||||||
|
if (firstTime) {
|
||||||
|
*dst = r;
|
||||||
|
} else {
|
||||||
|
dst->join(r);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ enum DrawType {
|
|||||||
DRAW_PICTURE,
|
DRAW_PICTURE,
|
||||||
DRAW_POINTS,
|
DRAW_POINTS,
|
||||||
DRAW_POS_TEXT,
|
DRAW_POS_TEXT,
|
||||||
|
DRAW_POS_TEXT_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT
|
||||||
DRAW_POS_TEXT_H,
|
DRAW_POS_TEXT_H,
|
||||||
DRAW_POS_TEXT_H_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT_H
|
DRAW_POS_TEXT_H_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT_H
|
||||||
DRAW_RECT,
|
DRAW_RECT,
|
||||||
|
@ -606,6 +606,17 @@ void SkPicturePlayback::draw(SkCanvas& canvas) {
|
|||||||
const SkPoint* pos = (const SkPoint*)fReader.skip(points * sizeof(SkPoint));
|
const SkPoint* pos = (const SkPoint*)fReader.skip(points * sizeof(SkPoint));
|
||||||
canvas.drawPosText(text.text(), text.length(), pos, paint);
|
canvas.drawPosText(text.text(), text.length(), pos, paint);
|
||||||
} break;
|
} break;
|
||||||
|
case DRAW_POS_TEXT_TOP_BOTTOM: {
|
||||||
|
const SkPaint& paint = *getPaint();
|
||||||
|
getText(&text);
|
||||||
|
size_t points = getInt();
|
||||||
|
const SkPoint* pos = (const SkPoint*)fReader.skip(points * sizeof(SkPoint));
|
||||||
|
const SkScalar top = fReader.readScalar();
|
||||||
|
const SkScalar bottom = fReader.readScalar();
|
||||||
|
if (!canvas.quickRejectY(top, bottom, SkCanvas::kAA_EdgeType)) {
|
||||||
|
canvas.drawPosText(text.text(), text.length(), pos, paint);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case DRAW_POS_TEXT_H: {
|
case DRAW_POS_TEXT_H: {
|
||||||
const SkPaint& paint = *getPaint();
|
const SkPaint& paint = *getPaint();
|
||||||
getText(&text);
|
getText(&text);
|
||||||
|
@ -287,14 +287,14 @@ void SkPictureRecord::drawSprite(const SkBitmap& bitmap, int left, int top,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint,
|
void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint,
|
||||||
SkScalar baselineY) {
|
SkScalar minY, SkScalar maxY) {
|
||||||
SkPaint::FontMetrics metrics;
|
SkPaint::FontMetrics metrics;
|
||||||
paint.getFontMetrics(&metrics);
|
paint.getFontMetrics(&metrics);
|
||||||
SkRect bounds;
|
SkRect bounds;
|
||||||
// construct a rect so we can see any adjustments from the paint.
|
// construct a rect so we can see any adjustments from the paint.
|
||||||
// we use 0,1 for left,right, just so the rect isn't empty
|
// we use 0,1 for left,right, just so the rect isn't empty
|
||||||
bounds.set(0, metrics.fTop + baselineY,
|
bounds.set(0, metrics.fTop + minY,
|
||||||
SK_Scalar1, metrics.fBottom + baselineY);
|
SK_Scalar1, metrics.fBottom + maxY);
|
||||||
(void)paint.computeFastBounds(bounds, &bounds);
|
(void)paint.computeFastBounds(bounds, &bounds);
|
||||||
// now record the top and bottom
|
// now record the top and bottom
|
||||||
addScalar(bounds.fTop);
|
addScalar(bounds.fTop);
|
||||||
@ -311,7 +311,7 @@ void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x,
|
|||||||
addScalar(x);
|
addScalar(x);
|
||||||
addScalar(y);
|
addScalar(y);
|
||||||
if (fast) {
|
if (fast) {
|
||||||
addFontMetricsTopBottom(paint, y);
|
addFontMetricsTopBottom(paint, y, y);
|
||||||
}
|
}
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
@ -323,23 +323,34 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
bool canUseDrawH = true;
|
bool canUseDrawH = true;
|
||||||
|
SkScalar minY = pos[0].fY;
|
||||||
|
SkScalar maxY = pos[0].fY;
|
||||||
// check if the caller really should have used drawPosTextH()
|
// check if the caller really should have used drawPosTextH()
|
||||||
{
|
{
|
||||||
const SkScalar firstY = pos[0].fY;
|
const SkScalar firstY = pos[0].fY;
|
||||||
for (size_t index = 1; index < points; index++) {
|
for (size_t index = 1; index < points; index++) {
|
||||||
if (pos[index].fY != firstY) {
|
if (pos[index].fY != firstY) {
|
||||||
canUseDrawH = false;
|
canUseDrawH = false;
|
||||||
break;
|
if (pos[index].fY < minY) {
|
||||||
|
minY = pos[index].fY;
|
||||||
|
} else if (pos[index].fY > maxY) {
|
||||||
|
maxY = pos[index].fY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fast = canUseDrawH && paint.canComputeFastBounds();
|
bool fastBounds = paint.canComputeFastBounds();
|
||||||
|
bool fast = canUseDrawH && fastBounds;
|
||||||
|
|
||||||
if (fast) {
|
if (fast) {
|
||||||
addDraw(DRAW_POS_TEXT_H_TOP_BOTTOM);
|
addDraw(DRAW_POS_TEXT_H_TOP_BOTTOM);
|
||||||
|
} else if (canUseDrawH) {
|
||||||
|
addDraw(DRAW_POS_TEXT_H);
|
||||||
|
} else if (fastBounds) {
|
||||||
|
addDraw(DRAW_POS_TEXT_TOP_BOTTOM);
|
||||||
} else {
|
} else {
|
||||||
addDraw(canUseDrawH ? DRAW_POS_TEXT_H : DRAW_POS_TEXT);
|
addDraw(DRAW_POS_TEXT);
|
||||||
}
|
}
|
||||||
addPaint(paint);
|
addPaint(paint);
|
||||||
addText(text, byteLength);
|
addText(text, byteLength);
|
||||||
@ -350,7 +361,7 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
|
|||||||
#endif
|
#endif
|
||||||
if (canUseDrawH) {
|
if (canUseDrawH) {
|
||||||
if (fast) {
|
if (fast) {
|
||||||
addFontMetricsTopBottom(paint, pos[0].fY);
|
addFontMetricsTopBottom(paint, pos[0].fY, pos[0].fY);
|
||||||
}
|
}
|
||||||
addScalar(pos[0].fY);
|
addScalar(pos[0].fY);
|
||||||
SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
|
SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar));
|
||||||
@ -359,6 +370,9 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fWriter.writeMul4(pos, points * sizeof(SkPoint));
|
fWriter.writeMul4(pos, points * sizeof(SkPoint));
|
||||||
|
if (fastBounds) {
|
||||||
|
addFontMetricsTopBottom(paint, minY, maxY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifdef SK_DEBUG_SIZE
|
#ifdef SK_DEBUG_SIZE
|
||||||
fPointBytes += fWriter.size() - start;
|
fPointBytes += fWriter.size() - start;
|
||||||
@ -385,7 +399,7 @@ void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength,
|
|||||||
size_t start = fWriter.size();
|
size_t start = fWriter.size();
|
||||||
#endif
|
#endif
|
||||||
if (fast) {
|
if (fast) {
|
||||||
addFontMetricsTopBottom(paint, constY);
|
addFontMetricsTopBottom(paint, constY, constY);
|
||||||
}
|
}
|
||||||
addScalar(constY);
|
addScalar(constY);
|
||||||
fWriter.writeMul4(xpos, points * sizeof(SkScalar));
|
fWriter.writeMul4(xpos, points * sizeof(SkScalar));
|
||||||
|
@ -66,7 +66,7 @@ public:
|
|||||||
const SkPaint&) SK_OVERRIDE;
|
const SkPaint&) SK_OVERRIDE;
|
||||||
virtual void drawData(const void*, size_t) SK_OVERRIDE;
|
virtual void drawData(const void*, size_t) SK_OVERRIDE;
|
||||||
|
|
||||||
void addFontMetricsTopBottom(const SkPaint& paint, SkScalar baselineY);
|
void addFontMetricsTopBottom(const SkPaint& paint, SkScalar minY, SkScalar maxY);
|
||||||
|
|
||||||
const SkTDArray<const SkFlatBitmap* >& getBitmaps() const {
|
const SkTDArray<const SkFlatBitmap* >& getBitmaps() const {
|
||||||
return fBitmaps;
|
return fBitmaps;
|
||||||
|
@ -22,6 +22,7 @@ public:
|
|||||||
virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
|
virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
|
||||||
SkIPoint* margin) SK_OVERRIDE;
|
SkIPoint* margin) SK_OVERRIDE;
|
||||||
virtual BlurType asABlur(BlurInfo*) const SK_OVERRIDE;
|
virtual BlurType asABlur(BlurInfo*) const SK_OVERRIDE;
|
||||||
|
virtual void computeFastBounds(const SkRect& src, SkRect* dest) SK_OVERRIDE;
|
||||||
|
|
||||||
// overrides from SkFlattenable
|
// overrides from SkFlattenable
|
||||||
virtual Factory getFactory() SK_OVERRIDE;
|
virtual Factory getFactory() SK_OVERRIDE;
|
||||||
@ -98,6 +99,11 @@ bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src,
|
|||||||
blurQuality, margin);
|
blurQuality, margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkBlurMaskFilterImpl::computeFastBounds(const SkRect& src, SkRect* dst) {
|
||||||
|
dst->set(src.fLeft - fRadius, src.fTop - fRadius,
|
||||||
|
src.fRight + fRadius, src.fBottom + fRadius);
|
||||||
|
}
|
||||||
|
|
||||||
SkFlattenable* SkBlurMaskFilterImpl::CreateProc(SkFlattenableReadBuffer& buffer) {
|
SkFlattenable* SkBlurMaskFilterImpl::CreateProc(SkFlattenableReadBuffer& buffer) {
|
||||||
return SkNEW_ARGS(SkBlurMaskFilterImpl, (buffer));
|
return SkNEW_ARGS(SkBlurMaskFilterImpl, (buffer));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user