aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/effects.gyp2
-rw-r--r--gyp/gpu.gyp2
-rw-r--r--gyp/utils.gyp18
-rw-r--r--src/utils/android/SkAndroidSDKCanvas.cpp316
-rw-r--r--src/utils/android/SkAndroidSDKCanvas.h106
5 files changed, 442 insertions, 2 deletions
diff --git a/gyp/effects.gyp b/gyp/effects.gyp
index 63b8636500..6cc790c377 100644
--- a/gyp/effects.gyp
+++ b/gyp/effects.gyp
@@ -9,7 +9,7 @@
'dependencies': [
'core.gyp:*',
'images.gyp:*',
- 'utils.gyp:*',
+ 'utils.gyp:utils',
],
'includes': [
'effects.gypi',
diff --git a/gyp/gpu.gyp b/gyp/gpu.gyp
index c69a4867d6..8569b5a924 100644
--- a/gyp/gpu.gyp
+++ b/gyp/gpu.gyp
@@ -85,7 +85,7 @@
'standalone_static_library': 1,
'dependencies': [
'core.gyp:*',
- 'utils.gyp:*',
+ 'utils.gyp:utils',
'etc1.gyp:libetc1',
'ktx.gyp:libSkKTX',
],
diff --git a/gyp/utils.gyp b/gyp/utils.gyp
index 19816f88e4..d3d14d86e1 100644
--- a/gyp/utils.gyp
+++ b/gyp/utils.gyp
@@ -124,5 +124,23 @@
],
},
},
+ {
+ 'target_name': 'android_utils',
+ 'product_name': 'skia_android_utils',
+ 'type': 'static_library',
+ 'standalone_static_library': 1,
+ 'dependencies': [
+ 'core.gyp:*',
+ ],
+ 'sources': [
+ '../src/utils/android/SkAndroidSDKCanvas.h',
+ '../src/utils/android/SkAndroidSDKCanvas.cpp',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '../src/utils/android',
+ ],
+ },
+ },
],
}
diff --git a/src/utils/android/SkAndroidSDKCanvas.cpp b/src/utils/android/SkAndroidSDKCanvas.cpp
new file mode 100644
index 0000000000..d02fd72620
--- /dev/null
+++ b/src/utils/android/SkAndroidSDKCanvas.cpp
@@ -0,0 +1,316 @@
+/*
+ * 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 "SkPathEffect.h"
+#include "SkShader.h"
+
+namespace {
+
+/** Discard SkShaders not exposed by the Android Java API. */
+
+void CheckShader(SkPaint* paint) {
+ SkShader* shader = paint->getShader();
+ if (!shader) {
+ return;
+ }
+
+ if (shader->asABitmap(NULL, NULL, NULL) == SkShader::kDefault_BitmapType) {
+ return;
+ }
+ if (shader->asACompose(NULL)) {
+ return;
+ }
+ SkShader::GradientType gtype = shader->asAGradient(NULL);
+ if (gtype == SkShader::kLinear_GradientType ||
+ gtype == SkShader::kRadial_GradientType ||
+ gtype == SkShader::kSweep_GradientType) {
+ return;
+ }
+ paint->setShader(NULL);
+}
+
+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(NULL);
+ }
+
+ // 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(NULL);
+ }
+ }
+
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+ SkPathEffect* pe = paint->getPathEffect();
+ if (pe && !pe->exposedInAndroidJavaAPI()) {
+ paint->setPathEffect(NULL);
+ }
+#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(NULL);
+ paint->setLooper(NULL);
+};
+
+} // namespace
+
+#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); \
+ }
+
+
+SkAndroidSDKCanvas::SkAndroidSDKCanvas() : fProxyTarget(NULL) { }
+
+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,
+ DrawBitmapRectFlags flags) {
+ FILTER_PTR(paint);
+ fProxyTarget->drawBitmapRectToRect(bitmap, src, dst, filteredPaint, flags);
+}
+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::onDrawSprite(const SkBitmap& bitmap,
+ int left,
+ int top,
+ const SkPaint* paint) {
+ FILTER_PTR(paint);
+ fProxyTarget->drawSprite(bitmap, left, top, 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) {
+ FILTER_PTR(paint);
+ fProxyTarget->drawImageRect(image, in, out, filteredPaint);
+}
+
+void SkAndroidSDKCanvas::onDrawPicture(const SkPicture* picture,
+ const SkMatrix* matrix,
+ const SkPaint* paint) {
+ FILTER_PTR(paint);
+ fProxyTarget->drawPicture(picture, matrix, filteredPaint);
+}
+
+void SkAndroidSDKCanvas::onDrawDrawable(SkDrawable* drawable) {
+ fProxyTarget->drawDrawable(drawable);
+}
+
+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);
+}
+
+const void* SkAndroidSDKCanvas::onPeekPixels(SkImageInfo* info, size_t* data) {
+ return fProxyTarget->peekPixels(info, data);
+}
+
+void* SkAndroidSDKCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* data) {
+ return fProxyTarget->accessTopLayerPixels(info, data);
+}
+
+void SkAndroidSDKCanvas::willSave() { fProxyTarget->save(); }
+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/src/utils/android/SkAndroidSDKCanvas.h b/src/utils/android/SkAndroidSDKCanvas.h
new file mode 100644
index 0000000000..fc046189f7
--- /dev/null
+++ b/src/utils/android/SkAndroidSDKCanvas.h
@@ -0,0 +1,106 @@
+/*
+ * 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) SK_OVERRIDE;
+ void onDrawPoints(PointMode pMode, size_t count, const SkPoint pts[],
+ const SkPaint& paint) SK_OVERRIDE;
+ void onDrawOval(const SkRect& r, const SkPaint& paint) SK_OVERRIDE;
+ void onDrawRect(const SkRect& r, const SkPaint& paint) SK_OVERRIDE;
+ void onDrawRRect(const SkRRect& r, const SkPaint& paint) SK_OVERRIDE;
+ void onDrawPath(const SkPath& path, const SkPaint& paint) SK_OVERRIDE;
+ void onDrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
+ const SkPaint* paint) SK_OVERRIDE;
+ void onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
+ const SkPaint* paint, DrawBitmapRectFlags flags) SK_OVERRIDE;
+ void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
+ const SkRect& dst, const SkPaint* paint) SK_OVERRIDE;
+ void onDrawSprite(const SkBitmap& bitmap, int left, int top,
+ const SkPaint* paint) SK_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) SK_OVERRIDE;
+
+ void onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
+ const SkPaint& paint) SK_OVERRIDE;
+
+ void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint& paint) SK_OVERRIDE;
+ void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint& paint) SK_OVERRIDE;
+ void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+ SkScalar constY, const SkPaint& paint) SK_OVERRIDE;
+ void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint& paint) SK_OVERRIDE;
+ void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
+ const SkPaint& paint) SK_OVERRIDE;
+
+ void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkXfermode* xmode,
+ const SkPaint& paint) SK_OVERRIDE;
+
+ void onDrawImage(const SkImage*, SkScalar, SkScalar, const SkPaint*) SK_OVERRIDE;
+ void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*)
+ SK_OVERRIDE;
+ void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*);
+
+ // PASS THROUGH
+
+ void onDrawDrawable(SkDrawable*) SK_OVERRIDE;
+ SkISize getBaseLayerSize() const SK_OVERRIDE;
+ bool getClipBounds(SkRect*) const SK_OVERRIDE;
+ bool getClipDeviceBounds(SkIRect*) const SK_OVERRIDE;
+ bool isClipEmpty() const SK_OVERRIDE;
+ bool isClipRect() const SK_OVERRIDE;
+ SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) SK_OVERRIDE;
+ const void* onPeekPixels(SkImageInfo*, size_t*) SK_OVERRIDE;
+ void* onAccessTopLayerPixels(SkImageInfo*, size_t*) SK_OVERRIDE;
+ void willSave() SK_OVERRIDE;
+ void willRestore() SK_OVERRIDE;
+ void didRestore() SK_OVERRIDE;
+ void didConcat(const SkMatrix&) SK_OVERRIDE;
+ void didSetMatrix(const SkMatrix&) SK_OVERRIDE;
+ void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
+ void onClipRegion(const SkRegion&, SkRegion::Op) SK_OVERRIDE;
+ void onDiscard() SK_OVERRIDE;
+
+protected:
+ SkCanvas* fProxyTarget;
+};
+
+#endif // SkAndroidSDKCanvas_DEFINED
+