| Index: src/utils/android/SkAndroidSDKCanvas.cpp
|
| diff --git a/src/utils/android/SkAndroidSDKCanvas.cpp b/src/utils/android/SkAndroidSDKCanvas.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d02fd72620d16d8e4f47e55c48537c89c12a5db5
|
| --- /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(); }
|
| +
|
| +
|
|
|