Index: dm/DMSrcSinkAndroid.cpp |
diff --git a/dm/DMSrcSinkAndroid.cpp b/dm/DMSrcSinkAndroid.cpp |
index ed7acb9f9c8832926a1d21fffc5a4ed036f08ba1..43d965b9af050997b9c5a7c727e727e2655c1986 100644 |
--- a/dm/DMSrcSinkAndroid.cpp |
+++ b/dm/DMSrcSinkAndroid.cpp |
@@ -12,8 +12,9 @@ |
#include "DisplayListRenderer.h" |
#include "IContextFactory.h" |
#include "RenderNode.h" |
-#include "SkDrawFilter.h" |
+#include "SkCanvas.h" |
#include "SkiaCanvasProxy.h" |
+#include "SkTLazy.h" |
#include "SkMaskFilter.h" |
#include "SkPictureRecorder.h" |
#include "SkStream.h" |
@@ -54,49 +55,179 @@ void CheckShader(SkPaint* paint) { |
paint->setShader(NULL); |
} |
-/** |
- * An SkDrawFilter implementation which removes all flags and features |
- * not exposed by the Android SDK. |
- */ |
-class ViaAndroidSDKFilter : public SkDrawFilter { |
+/** Simplify a paint. */ |
- bool filter(SkPaint* paint, Type drawType) SK_OVERRIDE { |
+void Filter(SkPaint* paint) { |
- uint32_t flags = paint->getFlags(); |
- flags &= ~SkPaint::kLCDRenderText_Flag; |
- paint->setFlags(flags); |
+ uint32_t flags = paint->getFlags(); |
+ flags &= ~SkPaint::kLCDRenderText_Flag; |
+ paint->setFlags(flags); |
- // Force bilinear scaling or none |
- if (paint->getFilterQuality() != kNone_SkFilterQuality) { |
- paint->setFilterQuality(kLow_SkFilterQuality); |
- } |
+ // Android doesn't support Xfermodes above kLighten_Mode |
+ SkXfermode::Mode mode; |
+ SkXfermode::AsMode(paint->getXfermode(), &mode); |
+ if (mode > SkXfermode::kLighten_Mode) { |
+ paint->setXfermode(NULL); |
+ } |
- CheckShader(paint); |
- |
- // Android SDK only supports mode & matrix color filters |
- SkColorFilter* cf = paint->getColorFilter(); |
- if (cf) { |
- SkColor color; |
- SkXfermode::Mode mode; |
- SkScalar srcColorMatrix[20]; |
- if (!cf->asColorMode(&color, &mode) && !cf->asColorMatrix(srcColorMatrix)) { |
- paint->setColorFilter(NULL); |
- } |
- } |
+ // Force bilinear scaling or none |
+ if (paint->getFilterQuality() != kNone_SkFilterQuality) { |
+ paint->setFilterQuality(kLow_SkFilterQuality); |
+ } |
- SkPathEffect* pe = paint->getPathEffect(); |
- if (pe && !pe->exposedInAndroidJavaAPI()) { |
- paint->setPathEffect(NULL); |
+ CheckShader(paint); |
+ |
+ // Android SDK only supports mode & matrix color filters |
+ // (and, again, no modes above kLighten_Mode). |
+ SkColorFilter* cf = paint->getColorFilter(); |
+ if (cf) { |
+ SkColor color; |
+ SkXfermode::Mode mode; |
+ SkScalar srcColorMatrix[20]; |
+ bool isMode = cf->asColorMode(&color, &mode); |
+ if (isMode && mode > SkXfermode::kLighten_Mode) { |
+ paint->setColorFilter( |
+ SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcOver_Mode)); |
+ } else if (!isMode && !cf->asColorMatrix(srcColorMatrix)) { |
+ paint->setColorFilter(NULL); |
} |
+ } |
+ |
+ SkPathEffect* pe = paint->getPathEffect(); |
+ if (pe && !pe->exposedInAndroidJavaAPI()) { |
+ paint->setPathEffect(NULL); |
+ } |
- // TODO: Android doesn't support all the flags that can be passed to |
- // blur filters; we need plumbing to get them out. |
+ // TODO: Android doesn't support all the flags that can be passed to |
+ // blur filters; we need plumbing to get them out. |
+ |
+ paint->setImageFilter(NULL); |
+ paint->setLooper(NULL); |
+}; |
- paint->setImageFilter(NULL); |
- paint->setLooper(NULL); |
+/** SkDrawFilter is likely to be deprecated; this is a proxy |
+ canvas that does the same thing: alter SkPaint fields. |
+ |
+ onDraw*() functions may have their SkPaint modified, and are then |
+ passed on to the same function on proxyTarget. |
+ |
+ This still suffers one of the same architectural flaws as SkDrawFilter: |
+ TextBlob paints are incomplete when filter is called. |
+*/ |
+ |
+#define FILTER(p) \ |
+ SkPaint filteredPaint(p); \ |
+ Filter(&filteredPaint); |
+ |
+#define FILTER_PTR(p) \ |
+ SkTLazy<SkPaint> lazyPaint; \ |
+ SkPaint* filteredPaint = (SkPaint*) p; \ |
+ if (p) { \ |
+ filteredPaint = lazyPaint.set(*p); \ |
+ Filter(filteredPaint); \ |
+ } |
+ |
+ |
+class FilteringCanvas : public SkCanvas { |
+public: |
+ FilteringCanvas(SkCanvas* proxyTarget) : fProxyTarget(proxyTarget) { } |
+ |
+protected: |
+ void onDrawPaint(const SkPaint& paint) SK_OVERRIDE { |
+ FILTER(paint); |
+ fProxyTarget->drawPaint(filteredPaint); |
+ } |
+ void onDrawPoints(PointMode pMode, size_t count, const SkPoint pts[], |
+ const SkPaint& paint) SK_OVERRIDE { |
+ FILTER(paint); |
+ fProxyTarget->drawPoints(pMode, count, pts, filteredPaint); |
+ } |
+ void onDrawOval(const SkRect& r, const SkPaint& paint) SK_OVERRIDE { |
+ FILTER(paint); |
+ fProxyTarget->drawOval(r, filteredPaint); |
+ } |
+ void onDrawRect(const SkRect& r, const SkPaint& paint) SK_OVERRIDE { |
+ FILTER(paint); |
+ fProxyTarget->drawRect(r, filteredPaint); |
+ } |
+ void onDrawRRect(const SkRRect& r, const SkPaint& paint) SK_OVERRIDE { |
+ FILTER(paint); |
+ fProxyTarget->drawRRect(r, filteredPaint); |
+ } |
+ void onDrawPath(const SkPath& path, const SkPaint& paint) SK_OVERRIDE { |
+ FILTER(paint); |
+ fProxyTarget->drawPath(path, filteredPaint); |
+ } |
+ void onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, |
+ const SkPaint* paint) SK_OVERRIDE { |
+ FILTER_PTR(paint); |
+ fProxyTarget->drawBitmap(bitmap, left, top, filteredPaint); |
+ } |
+ void onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, |
+ const SkPaint* paint, DrawBitmapRectFlags flags) SK_OVERRIDE { |
+ FILTER_PTR(paint); |
+ fProxyTarget->drawBitmapRectToRect(bitmap, src, dst, filteredPaint, flags); |
+ } |
+ void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, |
+ const SkRect& dst, const SkPaint* paint) SK_OVERRIDE { |
+ FILTER_PTR(paint); |
+ fProxyTarget->drawBitmapNine(bitmap, center, dst, filteredPaint); |
+ } |
+ void onDrawSprite(const SkBitmap& bitmap, int left, int top, |
+ const SkPaint* paint) SK_OVERRIDE { |
+ FILTER_PTR(paint); |
+ fProxyTarget->drawSprite(bitmap, left, top, filteredPaint); |
+ } |
+ void onDrawVertices(VertexMode vMode, int vertexCount, const SkPoint vertices[], |
+ const SkPoint texs[], const SkColor colors[], SkXfermode* xMode, |
+ const uint16_t indices[], int indexCount, |
+ const SkPaint& paint) SK_OVERRIDE { |
+ FILTER(paint); |
+ fProxyTarget->drawVertices(vMode, vertexCount, vertices, texs, colors, |
+ xMode, indices, indexCount, filteredPaint); |
+ } |
+ |
+ void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, |
+ const SkPaint& paint) SK_OVERRIDE { |
+ FILTER(paint); |
+ fProxyTarget->drawDRRect(outer, inner, filteredPaint); |
+ } |
+ |
+ void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, |
+ const SkPaint& paint) SK_OVERRIDE { |
+ FILTER(paint); |
+ fProxyTarget->drawText(text, byteLength, x, y, filteredPaint); |
+ } |
+ void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], |
+ const SkPaint& paint) SK_OVERRIDE { |
+ FILTER(paint); |
+ fProxyTarget->drawPosText(text, byteLength, pos, filteredPaint); |
+ } |
+ void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], |
+ SkScalar constY, const SkPaint& paint) SK_OVERRIDE { |
+ FILTER(paint); |
+ fProxyTarget->drawPosTextH(text, byteLength, xpos, constY, filteredPaint); |
+ } |
+ void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, |
+ const SkMatrix* matrix, const SkPaint& paint) SK_OVERRIDE { |
+ FILTER(paint); |
+ fProxyTarget->drawTextOnPath(text, byteLength, path, matrix, filteredPaint); |
+ } |
+ void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, |
+ const SkPaint& paint) SK_OVERRIDE { |
+ FILTER(paint); |
+ fProxyTarget->drawTextBlob(blob, x, y, filteredPaint); |
+ } |
+ |
+ void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], |
+ const SkPoint texCoords[4], SkXfermode* xmode, |
+ const SkPaint& paint) SK_OVERRIDE { |
+ FILTER(paint); |
+ fProxyTarget->drawPatch(cubics, colors, texCoords, xmode, filteredPaint); |
+ } |
- return true; |
- }; |
+protected: |
+ SkCanvas* fProxyTarget; |
}; |
/** |
@@ -249,16 +380,15 @@ Error ViaAndroidSDK::draw(const Src& src, |
: fSrc(src) {} |
Error draw(SkCanvas* canvas) const SK_OVERRIDE { |
- // Route through HWUI's upper layers to get operational transforms |
+ // Pass through HWUI's upper layers to get operational transforms |
SkAutoTDelete<android::Canvas> ac (android::Canvas::create_canvas(canvas)); |
SkAutoTUnref<android::uirenderer::SkiaCanvasProxy> scProxy |
(new android::uirenderer::SkiaCanvasProxy(ac)); |
- ViaAndroidSDKFilter filter; |
- // Route through a draw filter to get paint transforms |
- scProxy->setDrawFilter(&filter); |
+ // Pass through another proxy to get paint transforms |
+ FilteringCanvas fc(scProxy); |
- fSrc.draw(scProxy); |
+ fSrc.draw(&fc); |
return ""; |
} |