From 14d8fa0f58bf7f814901d2ae068af8814d6ed1a4 Mon Sep 17 00:00:00 2001 From: djsollen Date: Fri, 18 Dec 2015 09:34:08 -0800 Subject: Move SkAndroidSDKCanvas to tools and ensure that it is built on all Android builds GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1536013003 Review URL: https://codereview.chromium.org/1536013003 --- tools/android/SkAndroidSDKCanvas.cpp | 365 +++++++++++++++++++++++++++++++++++ tools/android/SkAndroidSDKCanvas.h | 110 +++++++++++ 2 files changed, 475 insertions(+) create mode 100644 tools/android/SkAndroidSDKCanvas.cpp create mode 100644 tools/android/SkAndroidSDKCanvas.h (limited to 'tools/android') diff --git a/tools/android/SkAndroidSDKCanvas.cpp b/tools/android/SkAndroidSDKCanvas.cpp new file mode 100644 index 0000000000..45fcc758f2 --- /dev/null +++ b/tools/android/SkAndroidSDKCanvas.cpp @@ -0,0 +1,365 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkAndroidSDKCanvas.h" + +#include "SkColorFilter.h" +#include "SkPaint.h" +#include "SkPathEffect.h" +#include "SkShader.h" +#include "SkTLazy.h" + +namespace { + +/** Discard SkShaders not exposed by the Android Java API. */ + +void CheckShader(SkPaint* paint) { + SkShader* shader = paint->getShader(); + if (!shader) { + return; + } + + if (shader->isABitmap()) { + return; + } + if (shader->asACompose(nullptr)) { + return; + } + SkShader::GradientType gtype = shader->asAGradient(nullptr); + if (gtype == SkShader::kLinear_GradientType || + gtype == SkShader::kRadial_GradientType || + gtype == SkShader::kSweep_GradientType) { + return; + } + paint->setShader(nullptr); +} + +void Filter(SkPaint* paint) { + + uint32_t flags = paint->getFlags(); + flags &= ~SkPaint::kLCDRenderText_Flag; + paint->setFlags(flags); + + // Android doesn't support Xfermodes above kLighten_Mode + SkXfermode::Mode mode; + SkXfermode::AsMode(paint->getXfermode(), &mode); + if (mode > SkXfermode::kLighten_Mode) { + paint->setXfermode(nullptr); + } + + // Force bilinear scaling or none + if (paint->getFilterQuality() != kNone_SkFilterQuality) { + paint->setFilterQuality(kLow_SkFilterQuality); + } + + 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(nullptr); + } + } + +#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK + SkPathEffect* pe = paint->getPathEffect(); + if (pe && !pe->exposedInAndroidJavaAPI()) { + paint->setPathEffect(nullptr); + } +#endif + + // TODO: Android doesn't support all the flags that can be passed to + // blur filters; we need plumbing to get them out. + + paint->setImageFilter(nullptr); + paint->setLooper(nullptr); +}; + +} // namespace + +#define FILTER(p) \ + SkPaint filteredPaint(p); \ + Filter(&filteredPaint); + +#define FILTER_PTR(p) \ + SkTLazy lazyPaint; \ + SkPaint* filteredPaint = (SkPaint*) p; \ + if (p) { \ + filteredPaint = lazyPaint.set(*p); \ + Filter(filteredPaint); \ + } + + +SkAndroidSDKCanvas::SkAndroidSDKCanvas() : fProxyTarget(nullptr) { } + +void SkAndroidSDKCanvas::reset(SkCanvas* newTarget) { fProxyTarget = newTarget; } + +void SkAndroidSDKCanvas::onDrawPaint(const SkPaint& paint) { + FILTER(paint); + fProxyTarget->drawPaint(filteredPaint); +} +void SkAndroidSDKCanvas::onDrawPoints(PointMode pMode, + size_t count, + const SkPoint pts[], + const SkPaint& paint) { + FILTER(paint); + fProxyTarget->drawPoints(pMode, count, pts, filteredPaint); +} +void SkAndroidSDKCanvas::onDrawOval(const SkRect& r, const SkPaint& paint) { + FILTER(paint); + fProxyTarget->drawOval(r, filteredPaint); +} +void SkAndroidSDKCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) { + FILTER(paint); + fProxyTarget->drawRect(r, filteredPaint); +} +void SkAndroidSDKCanvas::onDrawRRect(const SkRRect& r, const SkPaint& paint) { + FILTER(paint); + fProxyTarget->drawRRect(r, filteredPaint); +} +void SkAndroidSDKCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { + FILTER(paint); + fProxyTarget->drawPath(path, filteredPaint); +} +void SkAndroidSDKCanvas::onDrawBitmap(const SkBitmap& bitmap, + SkScalar left, + SkScalar top, + const SkPaint* paint) { + FILTER_PTR(paint); + fProxyTarget->drawBitmap(bitmap, left, top, filteredPaint); +} +void SkAndroidSDKCanvas::onDrawBitmapRect(const SkBitmap& bitmap, + const SkRect* src, + const SkRect& dst, + const SkPaint* paint, + SkCanvas::SrcRectConstraint constraint) { + FILTER_PTR(paint); + fProxyTarget->legacy_drawBitmapRect(bitmap, src, dst, filteredPaint, constraint); +} +void SkAndroidSDKCanvas::onDrawBitmapNine(const SkBitmap& bitmap, + const SkIRect& center, + const SkRect& dst, + const SkPaint* paint) { + FILTER_PTR(paint); + fProxyTarget->drawBitmapNine(bitmap, center, dst, filteredPaint); +} +void SkAndroidSDKCanvas::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) { + FILTER(paint); + fProxyTarget->drawVertices(vMode, vertexCount, vertices, texs, colors, + xMode, indices, indexCount, filteredPaint); +} + +void SkAndroidSDKCanvas::onDrawDRRect(const SkRRect& outer, + const SkRRect& inner, + const SkPaint& paint) { + FILTER(paint); + fProxyTarget->drawDRRect(outer, inner, filteredPaint); +} + +void SkAndroidSDKCanvas::onDrawText(const void* text, + size_t byteLength, + SkScalar x, + SkScalar y, + const SkPaint& paint) { + FILTER(paint); + fProxyTarget->drawText(text, byteLength, x, y, filteredPaint); +} +void SkAndroidSDKCanvas::onDrawPosText(const void* text, + size_t byteLength, + const SkPoint pos[], + const SkPaint& paint) { + FILTER(paint); + fProxyTarget->drawPosText(text, byteLength, pos, filteredPaint); +} +void SkAndroidSDKCanvas::onDrawPosTextH(const void* text, + size_t byteLength, + const SkScalar xpos[], + SkScalar constY, + const SkPaint& paint) { + FILTER(paint); + fProxyTarget->drawPosTextH(text, byteLength, xpos, constY, filteredPaint); +} +void SkAndroidSDKCanvas::onDrawTextOnPath(const void* text, + size_t byteLength, + const SkPath& path, + const SkMatrix* matrix, + const SkPaint& paint) { + FILTER(paint); + fProxyTarget->drawTextOnPath(text, byteLength, path, matrix, filteredPaint); +} +void SkAndroidSDKCanvas::onDrawTextBlob(const SkTextBlob* blob, + SkScalar x, + SkScalar y, + const SkPaint& paint) { + FILTER(paint); + fProxyTarget->drawTextBlob(blob, x, y, filteredPaint); +} + +void SkAndroidSDKCanvas::onDrawPatch(const SkPoint cubics[12], + const SkColor colors[4], + const SkPoint texCoords[4], + SkXfermode* xmode, + const SkPaint& paint) { + FILTER(paint); + fProxyTarget->drawPatch(cubics, colors, texCoords, xmode, filteredPaint); +} + + +void SkAndroidSDKCanvas::onDrawImage(const SkImage* image, + SkScalar x, + SkScalar y, + const SkPaint* paint) { + FILTER_PTR(paint); + fProxyTarget->drawImage(image, x, y, filteredPaint); +} + +void SkAndroidSDKCanvas::onDrawImageRect(const SkImage* image, + const SkRect* in, + const SkRect& out, + const SkPaint* paint, + SrcRectConstraint constraint) { + FILTER_PTR(paint); + fProxyTarget->legacy_drawImageRect(image, in, out, filteredPaint, constraint); +} + +void SkAndroidSDKCanvas::onDrawPicture(const SkPicture* picture, + const SkMatrix* matrix, + const SkPaint* paint) { + FILTER_PTR(paint); + fProxyTarget->drawPicture(picture, matrix, filteredPaint); +} + +void SkAndroidSDKCanvas::onDrawAtlas(const SkImage* atlas, + const SkRSXform xform[], + const SkRect tex[], + const SkColor colors[], + int count, + SkXfermode::Mode mode, + const SkRect* cullRect, + const SkPaint* paint) { + FILTER_PTR(paint); + fProxyTarget->drawAtlas(atlas, xform, tex, colors, count, mode, cullRect, + filteredPaint); +} + +void SkAndroidSDKCanvas::onDrawImageNine(const SkImage* image, + const SkIRect& center, + const SkRect& dst, + const SkPaint* paint) { + FILTER_PTR(paint); + fProxyTarget->drawImageNine(image, center, dst, filteredPaint); +} + + +void SkAndroidSDKCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) { + fProxyTarget->drawDrawable(drawable, matrix); +} + +SkISize SkAndroidSDKCanvas::getBaseLayerSize() const { + return fProxyTarget->getBaseLayerSize(); +} +bool SkAndroidSDKCanvas::getClipBounds(SkRect* rect) const { + return fProxyTarget->getClipBounds(rect); +} +bool SkAndroidSDKCanvas::getClipDeviceBounds(SkIRect* rect) const { + return fProxyTarget->getClipDeviceBounds(rect); +} + +bool SkAndroidSDKCanvas::isClipEmpty() const { return fProxyTarget->isClipEmpty(); } +bool SkAndroidSDKCanvas::isClipRect() const { return fProxyTarget->isClipRect(); } + +SkSurface* SkAndroidSDKCanvas::onNewSurface(const SkImageInfo& info, + const SkSurfaceProps& props) { + return fProxyTarget->newSurface(info, &props); +} + +bool SkAndroidSDKCanvas::onPeekPixels(SkPixmap* pmap) { + SkASSERT(pmap); + SkImageInfo info; + size_t rowBytes; + const void* addr = fProxyTarget->peekPixels(&info, &rowBytes); + if (addr) { + pmap->reset(info, addr, rowBytes); + return true; + } + return false; +} + +bool SkAndroidSDKCanvas::onAccessTopLayerPixels(SkPixmap* pmap) { + SkASSERT(pmap); + SkImageInfo info; + size_t rowBytes; + const void* addr = fProxyTarget->accessTopLayerPixels(&info, &rowBytes, nullptr); + if (addr) { + pmap->reset(info, addr, rowBytes); + return true; + } + return false; +} + +void SkAndroidSDKCanvas::willSave() { + fProxyTarget->save(); +} + +SkCanvas::SaveLayerStrategy SkAndroidSDKCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) { + fProxyTarget->saveLayer(rec); + return SkCanvas::kNoLayer_SaveLayerStrategy; +} + +void SkAndroidSDKCanvas::willRestore() { + fProxyTarget->restore(); +} + +void SkAndroidSDKCanvas::didRestore() { } + +void SkAndroidSDKCanvas::didConcat(const SkMatrix& m) { + fProxyTarget->concat(m); +} + +void SkAndroidSDKCanvas::didSetMatrix(const SkMatrix& m) { + fProxyTarget->setMatrix(m); +} + +void SkAndroidSDKCanvas::onClipRect(const SkRect& rect, + SkRegion::Op op, + ClipEdgeStyle style) { + fProxyTarget->clipRect(rect, op, style); +} + +void SkAndroidSDKCanvas::onClipRRect(const SkRRect& rrect, + SkRegion::Op op, + ClipEdgeStyle style) { + fProxyTarget->clipRRect(rrect, op, style); +} + +void SkAndroidSDKCanvas::onClipPath(const SkPath& path, + SkRegion::Op op, + ClipEdgeStyle style) { + fProxyTarget->clipPath(path, op, style); +} + +void SkAndroidSDKCanvas::onClipRegion(const SkRegion& region, SkRegion::Op op) { + fProxyTarget->clipRegion(region, op); +} + +void SkAndroidSDKCanvas::onDiscard() { fProxyTarget->discard(); } + + diff --git a/tools/android/SkAndroidSDKCanvas.h b/tools/android/SkAndroidSDKCanvas.h new file mode 100644 index 0000000000..d8ee0ed216 --- /dev/null +++ b/tools/android/SkAndroidSDKCanvas.h @@ -0,0 +1,110 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkAndroidSDKCanvas_DEFINED +#define SkAndroidSDKCanvas_DEFINED + +#include "SkBitmap.h" +#include "SkCanvas.h" +#include "SkPaint.h" +#include "SkPath.h" +#include "SkRect.h" + +/** 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 BREAKS CONSTNESS! + + This still suffers one of the same architectural flaws as SkDrawFilter: + TextBlob paints are incomplete when filter is called. +*/ + +class SkAndroidSDKCanvas : public SkCanvas { +public: + SkAndroidSDKCanvas(); + void reset(SkCanvas* newTarget); + +protected: + + // FILTERING + + void onDrawPaint(const SkPaint& paint) override; + void onDrawPoints(PointMode pMode, size_t count, const SkPoint pts[], + const SkPaint& paint) override; + void onDrawOval(const SkRect& r, const SkPaint& paint) override; + void onDrawRect(const SkRect& r, const SkPaint& paint) override; + void onDrawRRect(const SkRRect& r, const SkPaint& paint) override; + void onDrawPath(const SkPath& path, const SkPaint& paint) override; + void onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, + const SkPaint* paint) override; + void onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, + const SkPaint* paint, SkCanvas::SrcRectConstraint) override; + void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, + const SkRect& dst, const SkPaint* paint) override; + 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) override; + + void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, + const SkPaint& paint) override; + + void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, + const SkPaint& paint) override; + void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], + const SkPaint& paint) override; + void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], + SkScalar constY, const SkPaint& paint) override; + void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, + const SkMatrix* matrix, const SkPaint& paint) override; + void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, + const SkPaint& paint) override; + + void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], + const SkPoint texCoords[4], SkXfermode* xmode, + const SkPaint& paint) override; + + void onDrawImage(const SkImage*, SkScalar, SkScalar, const SkPaint*) override; + void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*, + SrcRectConstraint) override; + void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*); + void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], + const SkColor[], int count, SkXfermode::Mode, + const SkRect* cull, const SkPaint*) override; + void onDrawImageNine(const SkImage*, const SkIRect& center, + const SkRect& dst, const SkPaint*) override; + + // PASS THROUGH + + void onDrawDrawable(SkDrawable*, const SkMatrix*) override; + SkISize getBaseLayerSize() const override; + bool getClipBounds(SkRect*) const override; + bool getClipDeviceBounds(SkIRect*) const override; + bool isClipEmpty() const override; + bool isClipRect() const override; + SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) override; + bool onPeekPixels(SkPixmap*) override; + bool onAccessTopLayerPixels(SkPixmap*) override; + void willSave() override; + SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) override; + void willRestore() override; + void didRestore() override; + void didConcat(const SkMatrix&) override; + void didSetMatrix(const SkMatrix&) override; + void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) override; + void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) override; + void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) override; + void onClipRegion(const SkRegion&, SkRegion::Op) override; + void onDiscard() override; + +protected: + SkCanvas* fProxyTarget; +}; + +#endif // SkAndroidSDKCanvas_DEFINED + -- cgit v1.2.3