Chromium Code Reviews| Index: dm/DMSrcSinkAndroid.cpp |
| diff --git a/dm/DMSrcSinkAndroid.cpp b/dm/DMSrcSinkAndroid.cpp |
| index ed7acb9f9c8832926a1d21fffc5a4ed036f08ba1..cf7661aaf5a57873a1eec641f75638676e35b30c 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" |
| @@ -31,6 +32,8 @@ |
| namespace { |
| +typedef SkTLazy<SkPaint> SkLazyPaint; |
|
djsollen
2015/03/11 19:02:27
don't see the need to typedef this for one instanc
|
| + |
| /** Discard SkShaders not exposed by the Android Java API. */ |
| void CheckShader(SkPaint* paint) { |
| @@ -54,49 +57,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. |
| + |
| + 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) \ |
| + SkLazyPaint lazyPaint; \ |
| + SkPaint* filteredPaint = (SkPaint*) p; \ |
| + if (p) { \ |
| + filteredPaint = lazyPaint.set(*p); \ |
| + Filter(filteredPaint); \ |
| + } |
| + |
| + |
| +class FilteringCanvas : public SkCanvas { |
| +public: |
| + FilteringCanvas(SkCanvas* proxyTarget) : fProxyTarget(proxyTarget) { } |
| - // TODO: Android doesn't support all the flags that can be passed to |
| - // blur filters; we need plumbing to get them out. |
| +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); |
| + } |
| - paint->setImageFilter(NULL); |
| - paint->setLooper(NULL); |
| + 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 +382,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 ""; |
| } |