aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-03-15 20:56:58 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-03-15 20:56:58 +0000
commitf67e4cf4c18cd228738a11372859ee0280bce1d7 (patch)
treea456d4c82362669303d993c57e326a1fd0466e59
parent759c16e20dc42577226c8805bfea92d8bacb14d8 (diff)
add filterTextFlags() to SkDevice (virtual) to allow device subclasses to
filter what text features we try to use. The filtering allows for implementation limitations to dictate when we turn off certain text features. git-svn-id: http://skia.googlecode.com/svn/trunk@943 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--include/core/SkDevice.h15
-rw-r--r--include/gpu/SkGpuDevice.h1
-rw-r--r--src/core/SkCanvas.cpp38
-rw-r--r--src/core/SkDevice.cpp26
-rw-r--r--src/core/SkPaint.cpp23
-rw-r--r--src/gpu/SkGpuDevice.cpp25
6 files changed, 103 insertions, 25 deletions
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index 55d823b747..7332ba7b4e 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -214,6 +214,21 @@ public:
SkRefDict& getRefDict() { return fRefDict; }
+ struct TextFlags {
+ uint32_t fFlags; // SkPaint::getFlags()
+ SkPaint::Hinting fHinting;
+ };
+
+ /**
+ * Device may filter the text flags for drawing text here. If it wants to
+ * make a change to the specified values, it should write them into the
+ * textflags parameter (output) and return true. If the paint is fine as
+ * is, then ignore the textflags parameter and return false.
+ *
+ * The baseclass SkDevice filters based on its depth and blitters.
+ */
+ virtual bool filterTextFlags(const SkPaint& paint, TextFlags*);
+
protected:
/** Update as needed the pixel value in the bitmap, so that the caller can access
the pixels directly. Note: only the pixels field should be altered. The config/width/height/rowbytes
diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h
index 3fed99ab69..8852803a06 100644
--- a/include/gpu/SkGpuDevice.h
+++ b/include/gpu/SkGpuDevice.h
@@ -109,6 +109,7 @@ public:
const SkPaint& paint);
virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
const SkPaint&);
+ virtual bool filterTextFlags(const SkPaint& paint, TextFlags*);
virtual void flush() { fContext->flush(false); }
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 2b7d588911..a31623e7f4 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1352,12 +1352,42 @@ void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
ITER_END
}
+class SkDeviceFilteredPaint {
+public:
+ SkDeviceFilteredPaint(SkDevice* device, const SkPaint& paint) {
+ SkDevice::TextFlags flags;
+ if (device->filterTextFlags(paint, &flags)) {
+ SkPaint* newPaint = new (fStorage) SkPaint(paint);
+ newPaint->setFlags(flags.fFlags);
+ newPaint->setHinting(flags.fHinting);
+ fPaint = newPaint;
+ } else {
+ fPaint = &paint;
+ }
+ }
+
+ ~SkDeviceFilteredPaint() {
+ if (reinterpret_cast<SkPaint*>(fStorage) == fPaint) {
+ fPaint->~SkPaint();
+ }
+ }
+
+ const SkPaint& paint() const { return *fPaint; }
+
+private:
+ // points to either fStorage or the caller's paint
+ const SkPaint* fPaint;
+ // we rely on the fPaint above to ensure proper alignment of fStorage
+ char fStorage[sizeof(SkPaint)];
+};
+
void SkCanvas::drawText(const void* text, size_t byteLength,
SkScalar x, SkScalar y, const SkPaint& paint) {
ITER_BEGIN(paint, SkDrawFilter::kText_Type)
while (iter.next()) {
- iter.fDevice->drawText(iter, text, byteLength, x, y, paint);
+ SkDeviceFilteredPaint dfp(iter.fDevice, paint);
+ iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
}
ITER_END
@@ -1368,8 +1398,9 @@ void SkCanvas::drawPosText(const void* text, size_t byteLength,
ITER_BEGIN(paint, SkDrawFilter::kText_Type)
while (iter.next()) {
+ SkDeviceFilteredPaint dfp(iter.fDevice, paint);
iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
- paint);
+ dfp.paint());
}
ITER_END
@@ -1381,8 +1412,9 @@ void SkCanvas::drawPosTextH(const void* text, size_t byteLength,
ITER_BEGIN(paint, SkDrawFilter::kText_Type)
while (iter.next()) {
+ SkDeviceFilteredPaint dfp(iter.fDevice, paint);
iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
- paint);
+ dfp.paint());
}
ITER_END
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 619a37182d..82318487cc 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -178,6 +178,32 @@ void SkDevice::drawDevice(const SkDraw& draw, SkDevice* device,
///////////////////////////////////////////////////////////////////////////////
+bool SkDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
+ if (!paint.isLCDRenderText()) {
+ // we're cool with the paint as is
+ return false;
+ }
+
+ if (SkBitmap::kARGB_8888_Config != fBitmap.config() ||
+ paint.getShader() ||
+ paint.getXfermode() || // unless its srcover
+ paint.getMaskFilter() ||
+ paint.getRasterizer() ||
+ paint.getColorFilter() ||
+ paint.getPathEffect() ||
+ paint.isFakeBoldText() ||
+ paint.getStyle() != SkPaint::kFill_Style) {
+ // turn off lcd
+ flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
+ flags->fHinting = paint.getHinting();
+ return true;
+ }
+ // we're cool with the paint as is
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
SkDevice* SkRasterDeviceFactory::newDevice(SkCanvas* canvas,
SkBitmap::Config config, int width,
int height, bool isOpaque,
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index e3d8dd19af..1e406415b5 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1104,25 +1104,6 @@ static void add_flattenable(SkDescriptor* desc, uint32_t tag,
buffer->flatten(desc->addEntry(tag, buffer->size(), NULL));
}
-/*
- * Returns false if any condition holds where we cannot support rendering
- * LCD16 text. Over time we may loosen these restrictions (e.g. as we write
- * more blits that can handle it).
- *
- * The goal is to never return false if the user has requested it, but for now
- * we have some restrictions.
- */
-static bool canSupportLCD16(const SkPaint& paint) {
- return !paint.getShader() &&
- !paint.getXfermode() && // unless its srcover
- !paint.getMaskFilter() &&
- !paint.getRasterizer() &&
- !paint.getColorFilter() &&
- !paint.getPathEffect() &&
- !paint.isFakeBoldText() &&
- paint.getStyle() == SkPaint::kFill_Style;
-}
-
static SkMask::Format computeMaskFormat(const SkPaint& paint) {
uint32_t flags = paint.getFlags();
@@ -1138,9 +1119,7 @@ static SkMask::Format computeMaskFormat(const SkPaint& paint) {
}
#else
if (flags & SkPaint::kLCDRenderText_Flag) {
- if (canSupportLCD16(paint)) {
- return SkMask::kLCD16_Format;
- }
+ return SkMask::kLCD16_Format;
}
#endif
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 91a6319a17..3707b67119 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1181,6 +1181,31 @@ void SkGpuDevice::drawTextOnPath(const SkDraw& draw, const void* text,
///////////////////////////////////////////////////////////////////////////////
+bool SkGpuDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
+ if (!paint.isLCDRenderText()) {
+ // we're cool with the paint as is
+ return false;
+ }
+
+ if (paint.getShader() ||
+ paint.getXfermode() || // unless its srcover
+ paint.getMaskFilter() ||
+ paint.getRasterizer() ||
+ paint.getColorFilter() ||
+ paint.getPathEffect() ||
+ paint.isFakeBoldText() ||
+ paint.getStyle() != SkPaint::kFill_Style) {
+ // turn off lcd
+ flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
+ flags->fHinting = paint.getHinting();
+ return true;
+ }
+ // we're cool with the paint as is
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
SkGpuDevice::TexCache* SkGpuDevice::lockCachedTexture(const SkBitmap& bitmap,
const GrSamplerState& sampler,
GrTexture** texture,