Index: dm/DMSrcSinkAndroid.cpp |
diff --git a/dm/DMSrcSinkAndroid.cpp b/dm/DMSrcSinkAndroid.cpp |
index 1ad9329669e9a40a2522f2030cc3b06105d74786..ed7acb9f9c8832926a1d21fffc5a4ed036f08ba1 100644 |
--- a/dm/DMSrcSinkAndroid.cpp |
+++ b/dm/DMSrcSinkAndroid.cpp |
@@ -12,6 +12,11 @@ |
#include "DisplayListRenderer.h" |
#include "IContextFactory.h" |
#include "RenderNode.h" |
+#include "SkDrawFilter.h" |
+#include "SkiaCanvasProxy.h" |
+#include "SkMaskFilter.h" |
+#include "SkPictureRecorder.h" |
+#include "SkStream.h" |
#include "android/rect.h" |
#include "android/native_window.h" |
#include "gui/BufferQueue.h" |
@@ -22,10 +27,81 @@ |
#include "renderthread/RenderProxy.h" |
#include "renderthread/TimeLord.h" |
-namespace DM { |
- |
/* These functions are only compiled in the Android Framework. */ |
+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); |
+} |
+ |
+/** |
+ * An SkDrawFilter implementation which removes all flags and features |
+ * not exposed by the Android SDK. |
+ */ |
+class ViaAndroidSDKFilter : public SkDrawFilter { |
+ |
+ bool filter(SkPaint* paint, Type drawType) SK_OVERRIDE { |
+ |
+ 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); |
+ } |
+ |
+ 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); |
+ } |
+ } |
+ |
+ 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); |
+ |
+ return true; |
+ }; |
+}; |
+ |
+/** |
+ * Helper class for setting up android::uirenderer::renderthread::RenderProxy. |
+ */ |
class ContextFactory : public android::uirenderer::IContextFactory { |
public: |
android::uirenderer::AnimationContext* createAnimationContext |
@@ -34,6 +110,10 @@ public: |
} |
}; |
+} // namespace |
+ |
+namespace DM { |
+ |
Error HWUISink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) const { |
// Do all setup in this function because we don't know the size |
// for the RenderNode and RenderProxy during the constructor. |
@@ -155,4 +235,38 @@ Error HWUISink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) const |
return ""; |
} |
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ |
+ |
+ViaAndroidSDK::ViaAndroidSDK(Sink* sink) : fSink(sink) { } |
+ |
+Error ViaAndroidSDK::draw(const Src& src, |
+ SkBitmap* bitmap, |
+ SkWStream* stream, |
+ SkString* log) const { |
+ struct ProxySrc : public Src { |
+ const Src& fSrc; |
+ ProxySrc(const Src& src) |
+ : fSrc(src) {} |
+ |
+ Error draw(SkCanvas* canvas) const SK_OVERRIDE { |
+ // Route 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); |
+ |
+ fSrc.draw(scProxy); |
+ |
+ return ""; |
+ } |
+ SkISize size() const SK_OVERRIDE { return fSrc.size(); } |
+ Name name() const SK_OVERRIDE { sk_throw(); return ""; } |
+ } proxy(src); |
+ |
+ return fSink->draw(proxy, bitmap, stream, log); |
+} |
+ |
} // namespace DM |