summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--graphics/java/android/graphics/Paint.java2
-rw-r--r--libs/hwui/Android.bp7
-rw-r--r--libs/hwui/SkiaCanvas.cpp7
-rw-r--r--libs/hwui/VectorDrawable.cpp7
-rw-r--r--libs/hwui/VectorDrawable.h14
-rw-r--r--libs/hwui/hwui/Canvas.cpp2
-rw-r--r--libs/hwui/hwui/Paint.h9
-rw-r--r--libs/hwui/hwui/PaintImpl.cpp27
-rw-r--r--libs/hwui/jni/Paint.cpp14
-rw-r--r--libs/hwui/jni/Shader.cpp137
-rw-r--r--libs/hwui/jni/android_graphics_drawable_VectorDrawable.cpp4
-rw-r--r--libs/hwui/shader/BitmapShader.cpp31
-rw-r--r--libs/hwui/shader/BitmapShader.h39
-rw-r--r--libs/hwui/shader/ComposeShader.cpp51
-rw-r--r--libs/hwui/shader/ComposeShader.h43
-rw-r--r--libs/hwui/shader/LinearGradientShader.cpp39
-rw-r--r--libs/hwui/shader/LinearGradientShader.h42
-rw-r--r--libs/hwui/shader/RadialGradientShader.cpp38
-rw-r--r--libs/hwui/shader/RadialGradientShader.h42
-rw-r--r--libs/hwui/shader/RuntimeShader.cpp36
-rw-r--r--libs/hwui/shader/RuntimeShader.h40
-rw-r--r--libs/hwui/shader/Shader.cpp87
-rw-r--r--libs/hwui/shader/Shader.h82
-rw-r--r--libs/hwui/shader/SweepGradientShader.cpp38
-rw-r--r--libs/hwui/shader/SweepGradientShader.h41
-rw-r--r--libs/hwui/tests/common/scenes/BitmapShaders.cpp22
-rw-r--r--libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp47
-rw-r--r--libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp24
-rw-r--r--libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp11
-rw-r--r--libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp22
-rw-r--r--libs/hwui/tests/unit/VectorDrawableTests.cpp21
31 files changed, 908 insertions, 118 deletions
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 28d7911c771f..964640b106b9 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -3111,7 +3111,7 @@ public class Paint {
@CriticalNative
private static native boolean nGetFillPath(long paintPtr, long src, long dst);
@CriticalNative
- private static native long nSetShader(long paintPtr, long shader);
+ private static native void nSetShader(long paintPtr, long shader);
@CriticalNative
private static native long nSetColorFilter(long paintPtr, long filter);
@CriticalNative
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 9ae5ad97ed36..0b13754271b9 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -462,6 +462,13 @@ cc_defaults {
"RenderNode.cpp",
"RenderProperties.cpp",
"RootRenderNode.cpp",
+ "shader/Shader.cpp",
+ "shader/BitmapShader.cpp",
+ "shader/ComposeShader.cpp",
+ "shader/LinearGradientShader.cpp",
+ "shader/RadialGradientShader.cpp",
+ "shader/RuntimeShader.cpp",
+ "shader/SweepGradientShader.cpp",
"SkiaCanvas.cpp",
"VectorDrawable.cpp",
],
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 242b8b0d139e..cfba5d4f6aa2 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -42,6 +42,8 @@
#include <SkTextBlob.h>
#include <SkVertices.h>
+#include <shader/BitmapShader.h>
+
#include <memory>
#include <optional>
#include <utility>
@@ -49,6 +51,7 @@
namespace android {
using uirenderer::PaintUtils;
+using uirenderer::BitmapShader;
Canvas* Canvas::create_canvas(const SkBitmap& bitmap) {
return new SkiaCanvas(bitmap);
@@ -681,7 +684,9 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight,
if (paint) {
pnt = *paint;
}
- pnt.setShader(bitmap.makeImage()->makeShader());
+
+ pnt.setShader(sk_ref_sp(new BitmapShader(
+ bitmap.makeImage(), SkTileMode::kClamp, SkTileMode::kClamp, nullptr)));
auto v = builder.detach();
apply_looper(&pnt, [&](const SkPaint& p) {
mCanvas->drawVertices(v, SkBlendMode::kModulate, p);
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index cd908354aea5..0f566e4b494a 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -23,7 +23,6 @@
#include "PathParser.h"
#include "SkColorFilter.h"
#include "SkImageInfo.h"
-#include "SkShader.h"
#include "hwui/Paint.h"
#ifdef __ANDROID__
@@ -159,10 +158,10 @@ void FullPath::draw(SkCanvas* outCanvas, bool useStagingData) {
// Draw path's fill, if fill color or gradient is valid
bool needsFill = false;
- SkPaint paint;
+ Paint paint;
if (properties.getFillGradient() != nullptr) {
paint.setColor(applyAlpha(SK_ColorBLACK, properties.getFillAlpha()));
- paint.setShader(sk_sp<SkShader>(SkSafeRef(properties.getFillGradient())));
+ paint.setShader(sk_sp<Shader>(SkSafeRef(properties.getFillGradient())));
needsFill = true;
} else if (properties.getFillColor() != SK_ColorTRANSPARENT) {
paint.setColor(applyAlpha(properties.getFillColor(), properties.getFillAlpha()));
@@ -179,7 +178,7 @@ void FullPath::draw(SkCanvas* outCanvas, bool useStagingData) {
bool needsStroke = false;
if (properties.getStrokeGradient() != nullptr) {
paint.setColor(applyAlpha(SK_ColorBLACK, properties.getStrokeAlpha()));
- paint.setShader(sk_sp<SkShader>(SkSafeRef(properties.getStrokeGradient())));
+ paint.setShader(sk_sp<Shader>(SkSafeRef(properties.getStrokeGradient())));
needsStroke = true;
} else if (properties.getStrokeColor() != SK_ColorTRANSPARENT) {
paint.setColor(applyAlpha(properties.getStrokeColor(), properties.getStrokeAlpha()));
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index ac7d41e0d600..d4086f1aa622 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -31,8 +31,8 @@
#include <SkPath.h>
#include <SkPathMeasure.h>
#include <SkRect.h>
-#include <SkShader.h>
#include <SkSurface.h>
+#include <shader/Shader.h>
#include <cutils/compiler.h>
#include <stddef.h>
@@ -227,20 +227,20 @@ public:
strokeGradient = prop.strokeGradient;
onPropertyChanged();
}
- void setFillGradient(SkShader* gradient) {
+ void setFillGradient(Shader* gradient) {
if (fillGradient.get() != gradient) {
fillGradient = sk_ref_sp(gradient);
onPropertyChanged();
}
}
- void setStrokeGradient(SkShader* gradient) {
+ void setStrokeGradient(Shader* gradient) {
if (strokeGradient.get() != gradient) {
strokeGradient = sk_ref_sp(gradient);
onPropertyChanged();
}
}
- SkShader* getFillGradient() const { return fillGradient.get(); }
- SkShader* getStrokeGradient() const { return strokeGradient.get(); }
+ Shader* getFillGradient() const { return fillGradient.get(); }
+ Shader* getStrokeGradient() const { return strokeGradient.get(); }
float getStrokeWidth() const { return mPrimitiveFields.strokeWidth; }
void setStrokeWidth(float strokeWidth) {
VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeWidth, strokeWidth);
@@ -320,8 +320,8 @@ public:
count,
};
PrimitiveFields mPrimitiveFields;
- sk_sp<SkShader> fillGradient;
- sk_sp<SkShader> strokeGradient;
+ sk_sp<Shader> fillGradient;
+ sk_sp<Shader> strokeGradient;
};
// Called from UI thread
diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp
index c138a32eacc2..2a377bbb83f2 100644
--- a/libs/hwui/hwui/Canvas.cpp
+++ b/libs/hwui/hwui/Canvas.cpp
@@ -73,7 +73,7 @@ void Canvas::drawTextDecorations(float x, float y, float length, const Paint& pa
static void simplifyPaint(int color, Paint* paint) {
paint->setColor(color);
- paint->setShader(nullptr);
+ paint->setShader((sk_sp<uirenderer::Shader>)nullptr);
paint->setColorFilter(nullptr);
paint->setLooper(nullptr);
paint->setStrokeWidth(4 + 0.04 * paint->getSkFont().getSize());
diff --git a/libs/hwui/hwui/Paint.h b/libs/hwui/hwui/Paint.h
index e75e9e7c6933..0bb689c19079 100644
--- a/libs/hwui/hwui/Paint.h
+++ b/libs/hwui/hwui/Paint.h
@@ -30,6 +30,8 @@
#include <minikin/FamilyVariant.h>
#include <minikin/Hyphenator.h>
+#include <shader/Shader.h>
+
namespace android {
class Paint : public SkPaint {
@@ -149,8 +151,14 @@ public:
// The only respected flags are : [ antialias, dither, filterBitmap ]
static uint32_t GetSkPaintJavaFlags(const SkPaint&);
static void SetSkPaintJavaFlags(SkPaint*, uint32_t flags);
+
+ void setShader(sk_sp<uirenderer::Shader> shader);
private:
+
+ using SkPaint::setShader;
+ using SkPaint::setImageFilter;
+
SkFont mFont;
sk_sp<SkDrawLooper> mLooper;
@@ -169,6 +177,7 @@ private:
bool mStrikeThru = false;
bool mUnderline = false;
bool mDevKern = false;
+ sk_sp<uirenderer::Shader> mShader;
};
} // namespace android
diff --git a/libs/hwui/hwui/PaintImpl.cpp b/libs/hwui/hwui/PaintImpl.cpp
index fa2674fc2f5e..21f60fd7b671 100644
--- a/libs/hwui/hwui/PaintImpl.cpp
+++ b/libs/hwui/hwui/PaintImpl.cpp
@@ -24,7 +24,8 @@ Paint::Paint()
, mWordSpacing(0)
, mFontFeatureSettings()
, mMinikinLocaleListId(0)
- , mFamilyVariant(minikin::FamilyVariant::DEFAULT) {
+ , mFamilyVariant(minikin::FamilyVariant::DEFAULT)
+ , mShader(nullptr) {
// SkPaint::antialiasing defaults to false, but
// SkFont::edging defaults to kAntiAlias. To keep them
// insync, we manually set the font to kAilas.
@@ -45,7 +46,8 @@ Paint::Paint(const Paint& paint)
, mAlign(paint.mAlign)
, mStrikeThru(paint.mStrikeThru)
, mUnderline(paint.mUnderline)
- , mDevKern(paint.mDevKern) {}
+ , mDevKern(paint.mDevKern)
+ , mShader(paint.mShader){}
Paint::~Paint() {}
@@ -65,9 +67,30 @@ Paint& Paint::operator=(const Paint& other) {
mStrikeThru = other.mStrikeThru;
mUnderline = other.mUnderline;
mDevKern = other.mDevKern;
+ mShader = other.mShader;
return *this;
}
+void Paint::setShader(sk_sp<uirenderer::Shader> shader) {
+ if (shader) {
+ // If there is an SkShader compatible shader, apply it
+ sk_sp<SkShader> skShader = shader->asSkShader();
+ if (skShader.get()) {
+ SkPaint::setShader(skShader);
+ SkPaint::setImageFilter(nullptr);
+ } else {
+ // ... otherwise the specified shader can only be represented as an ImageFilter
+ SkPaint::setShader(nullptr);
+ SkPaint::setImageFilter(shader->asSkImageFilter());
+ }
+ } else {
+ // No shader is provided at all, clear out both the SkShader and SkImageFilter slots
+ SkPaint::setShader(nullptr);
+ SkPaint::setImageFilter(nullptr);
+ }
+ mShader = shader;
+}
+
bool operator==(const Paint& a, const Paint& b) {
return static_cast<const SkPaint&>(a) == static_cast<const SkPaint&>(b) &&
a.mFont == b.mFont &&
diff --git a/libs/hwui/jni/Paint.cpp b/libs/hwui/jni/Paint.cpp
index df8635a8fe5a..554674a331cd 100644
--- a/libs/hwui/jni/Paint.cpp
+++ b/libs/hwui/jni/Paint.cpp
@@ -47,6 +47,7 @@
#include <minikin/LocaleList.h>
#include <minikin/Measurement.h>
#include <minikin/MinikinPaint.h>
+#include <shader/Shader.h>
#include <unicode/utf16.h>
#include <cassert>
@@ -54,6 +55,8 @@
#include <memory>
#include <vector>
+using namespace android::uirenderer;
+
namespace android {
struct JMetricsID {
@@ -782,11 +785,10 @@ namespace PaintGlue {
return obj->getFillPath(*src, dst) ? JNI_TRUE : JNI_FALSE;
}
- static jlong setShader(CRITICAL_JNI_PARAMS_COMMA jlong objHandle, jlong shaderHandle) {
- Paint* obj = reinterpret_cast<Paint*>(objHandle);
- SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- obj->setShader(sk_ref_sp(shader));
- return reinterpret_cast<jlong>(obj->getShader());
+ static void setShader(CRITICAL_JNI_PARAMS_COMMA jlong objHandle, jlong shaderHandle) {
+ auto* paint = reinterpret_cast<Paint*>(objHandle);
+ auto* shader = reinterpret_cast<Shader*>(shaderHandle);
+ paint->setShader(sk_ref_sp(shader));
}
static jlong setColorFilter(CRITICAL_JNI_PARAMS_COMMA jlong objHandle, jlong filterHandle) {
@@ -1097,7 +1099,7 @@ static const JNINativeMethod methods[] = {
{"nGetStrokeJoin","(J)I", (void*) PaintGlue::getStrokeJoin},
{"nSetStrokeJoin","(JI)V", (void*) PaintGlue::setStrokeJoin},
{"nGetFillPath","(JJJ)Z", (void*) PaintGlue::getFillPath},
- {"nSetShader","(JJ)J", (void*) PaintGlue::setShader},
+ {"nSetShader","(JJ)V", (void*) PaintGlue::setShader},
{"nSetColorFilter","(JJ)J", (void*) PaintGlue::setColorFilter},
{"nSetXfermode","(JI)V", (void*) PaintGlue::setXfermode},
{"nSetPathEffect","(JJ)J", (void*) PaintGlue::setPathEffect},
diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp
index e76aace601be..9b1972ed664f 100644
--- a/libs/hwui/jni/Shader.cpp
+++ b/libs/hwui/jni/Shader.cpp
@@ -5,6 +5,13 @@
#include "SkShader.h"
#include "SkBlendMode.h"
#include "include/effects/SkRuntimeEffect.h"
+#include "shader/Shader.h"
+#include "shader/BitmapShader.h"
+#include "shader/ComposeShader.h"
+#include "shader/LinearGradientShader.h"
+#include "shader/RadialGradientShader.h"
+#include "shader/RuntimeShader.h"
+#include "shader/SweepGradientShader.h"
#include <vector>
@@ -50,7 +57,7 @@ static jint Color_HSVToColor(JNIEnv* env, jobject, jint alpha, jfloatArray hsvAr
///////////////////////////////////////////////////////////////////////////////////////////////
-static void Shader_safeUnref(SkShader* shader) {
+static void Shader_safeUnref(Shader* shader) {
SkSafeUnref(shader);
}
@@ -74,15 +81,15 @@ static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, j
SkBitmap bitmap;
image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
}
- sk_sp<SkShader> shader = image->makeShader(
- (SkTileMode)tileModeX, (SkTileMode)tileModeY);
- ThrowIAE_IfNull(env, shader.get());
- if (matrix) {
- shader = shader->makeWithLocalMatrix(*matrix);
- }
+ auto* shader = new BitmapShader(
+ image,
+ static_cast<SkTileMode>(tileModeX),
+ static_cast<SkTileMode>(tileModeY),
+ matrix
+ );
- return reinterpret_cast<jlong>(shader.release());
+ return reinterpret_cast<jlong>(shader);
}
///////////////////////////////////////////////////////////////////////////////////////////////
@@ -118,17 +125,18 @@ static jlong LinearGradient_create(JNIEnv* env, jobject, jlong matrixPtr,
#error Need to convert float array to SkScalar array before calling the following function.
#endif
- sk_sp<SkShader> shader(SkGradientShader::MakeLinear(pts, &colors[0],
- GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(),
- static_cast<SkTileMode>(tileMode), sGradientShaderFlags, nullptr));
- ThrowIAE_IfNull(env, shader);
-
- const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
- if (matrix) {
- shader = shader->makeWithLocalMatrix(*matrix);
- }
+ auto* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
+ auto* shader = new LinearGradientShader(
+ pts,
+ colors,
+ GraphicsJNI::getNativeColorSpace(colorSpaceHandle),
+ pos,
+ static_cast<SkTileMode>(tileMode),
+ sGradientShaderFlags,
+ matrix
+ );
- return reinterpret_cast<jlong>(shader.release());
+ return reinterpret_cast<jlong>(shader);
}
///////////////////////////////////////////////////////////////////////////////////////////////
@@ -148,17 +156,20 @@ static jlong RadialGradient_create(JNIEnv* env, jobject, jlong matrixPtr, jfloat
#error Need to convert float array to SkScalar array before calling the following function.
#endif
- sk_sp<SkShader> shader = SkGradientShader::MakeRadial(center, radius, &colors[0],
- GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(),
- static_cast<SkTileMode>(tileMode), sGradientShaderFlags, nullptr);
- ThrowIAE_IfNull(env, shader);
+ auto* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
- const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
- if (matrix) {
- shader = shader->makeWithLocalMatrix(*matrix);
- }
+ auto* shader = new RadialGradientShader(
+ center,
+ radius,
+ colors,
+ GraphicsJNI::getNativeColorSpace(colorSpaceHandle),
+ pos,
+ static_cast<SkTileMode>(tileMode),
+ sGradientShaderFlags,
+ matrix
+ );
- return reinterpret_cast<jlong>(shader.release());
+ return reinterpret_cast<jlong>(shader);
}
///////////////////////////////////////////////////////////////////////////////
@@ -174,54 +185,58 @@ static jlong SweepGradient_create(JNIEnv* env, jobject, jlong matrixPtr, jfloat
#error Need to convert float array to SkScalar array before calling the following function.
#endif
- sk_sp<SkShader> shader = SkGradientShader::MakeSweep(x, y, &colors[0],
- GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(),
- sGradientShaderFlags, nullptr);
- ThrowIAE_IfNull(env, shader);
+ auto* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
- const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
- if (matrix) {
- shader = shader->makeWithLocalMatrix(*matrix);
- }
+ auto* shader = new SweepGradientShader(
+ x,
+ y,
+ colors,
+ GraphicsJNI::getNativeColorSpace(colorSpaceHandle),
+ pos,
+ sGradientShaderFlags,
+ matrix
+ );
- return reinterpret_cast<jlong>(shader.release());
+ return reinterpret_cast<jlong>(shader);
}
///////////////////////////////////////////////////////////////////////////////////////////////
static jlong ComposeShader_create(JNIEnv* env, jobject o, jlong matrixPtr,
jlong shaderAHandle, jlong shaderBHandle, jint xfermodeHandle) {
- const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
- SkShader* shaderA = reinterpret_cast<SkShader *>(shaderAHandle);
- SkShader* shaderB = reinterpret_cast<SkShader *>(shaderBHandle);
- SkBlendMode mode = static_cast<SkBlendMode>(xfermodeHandle);
- sk_sp<SkShader> baseShader(SkShaders::Blend(mode,
- sk_ref_sp(shaderA), sk_ref_sp(shaderB)));
-
- SkShader* shader;
-
- if (matrix) {
- shader = baseShader->makeWithLocalMatrix(*matrix).release();
- } else {
- shader = baseShader.release();
- }
- return reinterpret_cast<jlong>(shader);
+ auto* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
+ auto* shaderA = reinterpret_cast<Shader*>(shaderAHandle);
+ auto* shaderB = reinterpret_cast<Shader*>(shaderBHandle);
+
+ auto mode = static_cast<SkBlendMode>(xfermodeHandle);
+
+ auto* composeShader = new ComposeShader(
+ *shaderA,
+ *shaderB,
+ mode,
+ matrix
+ );
+
+ return reinterpret_cast<jlong>(composeShader);
}
///////////////////////////////////////////////////////////////////////////////////////////////
static jlong RuntimeShader_create(JNIEnv* env, jobject, jlong shaderFactory, jlong matrixPtr,
jbyteArray inputs, jlong colorSpaceHandle, jboolean isOpaque) {
- SkRuntimeEffect* effect = reinterpret_cast<SkRuntimeEffect*>(shaderFactory);
+ auto* effect = reinterpret_cast<SkRuntimeEffect*>(shaderFactory);
AutoJavaByteArray arInputs(env, inputs);
- sk_sp<SkData> fData;
- fData = SkData::MakeWithCopy(arInputs.ptr(), arInputs.length());
- const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
- sk_sp<SkShader> shader = effect->makeShader(fData, nullptr, 0, matrix, isOpaque == JNI_TRUE);
- ThrowIAE_IfNull(env, shader);
+ auto data = SkData::MakeWithCopy(arInputs.ptr(), arInputs.length());
+ auto* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
- return reinterpret_cast<jlong>(shader.release());
+ auto* shader = new RuntimeShader(
+ *effect,
+ std::move(data),
+ isOpaque == JNI_TRUE,
+ matrix
+ );
+ return reinterpret_cast<jlong>(shader);
}
///////////////////////////////////////////////////////////////////////////////////////////////
@@ -239,12 +254,8 @@ static jlong RuntimeShader_createShaderFactory(JNIEnv* env, jobject, jstring sks
///////////////////////////////////////////////////////////////////////////////////////////////
-static void Effect_safeUnref(SkRuntimeEffect* effect) {
- SkSafeUnref(effect);
-}
-
static jlong RuntimeShader_getNativeFinalizer(JNIEnv*, jobject) {
- return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Effect_safeUnref));
+ return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Shader_safeUnref));
}
///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/jni/android_graphics_drawable_VectorDrawable.cpp b/libs/hwui/jni/android_graphics_drawable_VectorDrawable.cpp
index 9cffceb308c8..a1adcb30e80d 100644
--- a/libs/hwui/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/libs/hwui/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -143,13 +143,13 @@ static void updateFullPathPropertiesAndStrokeStyles(JNIEnv*, jobject, jlong full
static void updateFullPathFillGradient(JNIEnv*, jobject, jlong pathPtr, jlong fillGradientPtr) {
VectorDrawable::FullPath* path = reinterpret_cast<VectorDrawable::FullPath*>(pathPtr);
- SkShader* fillShader = reinterpret_cast<SkShader*>(fillGradientPtr);
+ auto* fillShader = reinterpret_cast<Shader*>(fillGradientPtr);
path->mutateStagingProperties()->setFillGradient(fillShader);
}
static void updateFullPathStrokeGradient(JNIEnv*, jobject, jlong pathPtr, jlong strokeGradientPtr) {
VectorDrawable::FullPath* path = reinterpret_cast<VectorDrawable::FullPath*>(pathPtr);
- SkShader* strokeShader = reinterpret_cast<SkShader*>(strokeGradientPtr);
+ auto* strokeShader = reinterpret_cast<Shader*>(strokeGradientPtr);
path->mutateStagingProperties()->setStrokeGradient(strokeShader);
}
diff --git a/libs/hwui/shader/BitmapShader.cpp b/libs/hwui/shader/BitmapShader.cpp
new file mode 100644
index 000000000000..fe653e85a021
--- /dev/null
+++ b/libs/hwui/shader/BitmapShader.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BitmapShader.h"
+
+#include "SkImagePriv.h"
+
+namespace android::uirenderer {
+BitmapShader::BitmapShader(const sk_sp<SkImage>& image, const SkTileMode tileModeX,
+ const SkTileMode tileModeY, const SkMatrix* matrix)
+ : Shader(matrix), skShader(image->makeShader(tileModeX, tileModeY)) {}
+
+sk_sp<SkShader> BitmapShader::makeSkShader() {
+ return skShader;
+}
+
+BitmapShader::~BitmapShader() {}
+} // namespace android::uirenderer \ No newline at end of file
diff --git a/libs/hwui/shader/BitmapShader.h b/libs/hwui/shader/BitmapShader.h
new file mode 100644
index 000000000000..ed6a6e6802d1
--- /dev/null
+++ b/libs/hwui/shader/BitmapShader.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Shader.h"
+#include "SkShader.h"
+
+namespace android::uirenderer {
+
+/**
+ * Shader implementation that renders a Bitmap as either a SkShader or SkImageFilter
+ */
+class BitmapShader : public Shader {
+public:
+ BitmapShader(const sk_sp<SkImage>& image, const SkTileMode tileModeX,
+ const SkTileMode tileModeY, const SkMatrix* matrix);
+ ~BitmapShader() override;
+
+protected:
+ sk_sp<SkShader> makeSkShader() override;
+
+private:
+ sk_sp<SkShader> skShader;
+};
+} // namespace android::uirenderer \ No newline at end of file
diff --git a/libs/hwui/shader/ComposeShader.cpp b/libs/hwui/shader/ComposeShader.cpp
new file mode 100644
index 000000000000..3765489e7431
--- /dev/null
+++ b/libs/hwui/shader/ComposeShader.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ComposeShader.h"
+
+#include "SkImageFilters.h"
+#include "SkShader.h"
+
+namespace android::uirenderer {
+
+ComposeShader::ComposeShader(Shader& shaderA, Shader& shaderB, const SkBlendMode blendMode,
+ const SkMatrix* matrix)
+ : Shader(matrix) {
+ // If both Shaders can be represented as SkShaders then use those, if not
+ // create an SkImageFilter from both Shaders and create the equivalent SkImageFilter
+ sk_sp<SkShader> skShaderA = shaderA.asSkShader();
+ sk_sp<SkShader> skShaderB = shaderB.asSkShader();
+ if (skShaderA.get() && skShaderB.get()) {
+ skShader = SkShaders::Blend(blendMode, skShaderA, skShaderB);
+ skImageFilter = nullptr;
+ } else {
+ sk_sp<SkImageFilter> skImageFilterA = shaderA.asSkImageFilter();
+ sk_sp<SkImageFilter> skImageFilterB = shaderB.asSkImageFilter();
+ skShader = nullptr;
+ skImageFilter = SkImageFilters::Xfermode(blendMode, skImageFilterA, skImageFilterB);
+ }
+}
+
+sk_sp<SkShader> ComposeShader::makeSkShader() {
+ return skShader;
+}
+
+sk_sp<SkImageFilter> ComposeShader::makeSkImageFilter() {
+ return skImageFilter;
+}
+
+ComposeShader::~ComposeShader() {}
+} // namespace android::uirenderer
diff --git a/libs/hwui/shader/ComposeShader.h b/libs/hwui/shader/ComposeShader.h
new file mode 100644
index 000000000000..a246b520d46a
--- /dev/null
+++ b/libs/hwui/shader/ComposeShader.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Shader.h"
+#include "SkShader.h"
+
+namespace android::uirenderer {
+
+/**
+ * Shader implementation that can composite 2 Shaders together with the specified blend mode.
+ * This implementation can appropriately convert the composed result to either an SkShader or
+ * SkImageFilter depending on the inputs
+ */
+class ComposeShader : public Shader {
+public:
+ ComposeShader(Shader& shaderA, Shader& shaderB, const SkBlendMode blendMode,
+ const SkMatrix* matrix);
+ ~ComposeShader() override;
+
+protected:
+ sk_sp<SkShader> makeSkShader() override;
+ sk_sp<SkImageFilter> makeSkImageFilter() override;
+
+private:
+ sk_sp<SkShader> skShader;
+ sk_sp<SkImageFilter> skImageFilter;
+};
+} // namespace android::uirenderer
diff --git a/libs/hwui/shader/LinearGradientShader.cpp b/libs/hwui/shader/LinearGradientShader.cpp
new file mode 100644
index 000000000000..868fa44fb4b7
--- /dev/null
+++ b/libs/hwui/shader/LinearGradientShader.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "LinearGradientShader.h"
+
+#include <vector>
+
+#include "SkGradientShader.h"
+
+namespace android::uirenderer {
+
+LinearGradientShader::LinearGradientShader(const SkPoint pts[2],
+ const std::vector<SkColor4f>& colors,
+ sk_sp<SkColorSpace> colorspace, const SkScalar pos[],
+ const SkTileMode tileMode, const uint32_t shaderFlags,
+ const SkMatrix* matrix)
+ : Shader(matrix)
+ , skShader(SkGradientShader::MakeLinear(pts, colors.data(), colorspace, pos, colors.size(),
+ tileMode, shaderFlags, nullptr)) {}
+
+sk_sp<SkShader> LinearGradientShader::makeSkShader() {
+ return skShader;
+}
+
+LinearGradientShader::~LinearGradientShader() {}
+} // namespace android::uirenderer \ No newline at end of file
diff --git a/libs/hwui/shader/LinearGradientShader.h b/libs/hwui/shader/LinearGradientShader.h
new file mode 100644
index 000000000000..596f4e009448
--- /dev/null
+++ b/libs/hwui/shader/LinearGradientShader.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Shader.h"
+#include "SkShader.h"
+
+namespace android::uirenderer {
+
+/**
+ * Shader implementation that renders a color ramp of colors to either as either SkShader or
+ * SkImageFilter
+ */
+class LinearGradientShader : public Shader {
+public:
+ LinearGradientShader(const SkPoint pts[2], const std::vector<SkColor4f>& colors,
+ sk_sp<SkColorSpace> colorspace, const SkScalar pos[],
+ const SkTileMode tileMode, const uint32_t shaderFlags,
+ const SkMatrix* matrix);
+ ~LinearGradientShader() override;
+
+protected:
+ sk_sp<SkShader> makeSkShader() override;
+
+private:
+ sk_sp<SkShader> skShader;
+};
+} // namespace android::uirenderer
diff --git a/libs/hwui/shader/RadialGradientShader.cpp b/libs/hwui/shader/RadialGradientShader.cpp
new file mode 100644
index 000000000000..21ff56fee2f8
--- /dev/null
+++ b/libs/hwui/shader/RadialGradientShader.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "RadialGradientShader.h"
+
+#include <vector>
+
+#include "SkGradientShader.h"
+
+namespace android::uirenderer {
+
+RadialGradientShader::RadialGradientShader(const SkPoint& center, const float radius,
+ const std::vector<SkColor4f>& colors,
+ sk_sp<SkColorSpace> colorspace, const SkScalar pos[],
+ const SkTileMode tileMode, const uint32_t shaderFlags,
+ const SkMatrix* matrix)
+ : Shader(matrix)
+ , skShader(SkGradientShader::MakeRadial(center, radius, colors.data(), colorspace, pos,
+ colors.size(), tileMode, shaderFlags, nullptr)) {}
+
+sk_sp<SkShader> RadialGradientShader::makeSkShader() {
+ return skShader;
+}
+
+RadialGradientShader::~RadialGradientShader() {}
+} // namespace android::uirenderer \ No newline at end of file
diff --git a/libs/hwui/shader/RadialGradientShader.h b/libs/hwui/shader/RadialGradientShader.h
new file mode 100644
index 000000000000..9a2ff139aedb
--- /dev/null
+++ b/libs/hwui/shader/RadialGradientShader.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Shader.h"
+#include "SkShader.h"
+
+namespace android::uirenderer {
+
+/**
+ * Shader implementation that renders a color ramp from the center outward to either as either
+ * a SkShader or SkImageFilter
+ */
+class RadialGradientShader : public Shader {
+public:
+ RadialGradientShader(const SkPoint& center, const float radius,
+ const std::vector<SkColor4f>& colors, sk_sp<SkColorSpace> colorSpace,
+ const SkScalar pos[], const SkTileMode tileMode, const uint32_t shaderFlags,
+ const SkMatrix* matrix);
+ ~RadialGradientShader() override;
+
+protected:
+ sk_sp<SkShader> makeSkShader() override;
+
+private:
+ sk_sp<SkShader> skShader;
+};
+} // namespace android::uirenderer \ No newline at end of file
diff --git a/libs/hwui/shader/RuntimeShader.cpp b/libs/hwui/shader/RuntimeShader.cpp
new file mode 100644
index 000000000000..dd0b6980841a
--- /dev/null
+++ b/libs/hwui/shader/RuntimeShader.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "RuntimeShader.h"
+
+#include "SkShader.h"
+#include "include/effects/SkRuntimeEffect.h"
+
+namespace android::uirenderer {
+
+RuntimeShader::RuntimeShader(SkRuntimeEffect& effect, sk_sp<SkData> data, bool isOpaque,
+ const SkMatrix* matrix)
+ : Shader(nullptr)
+ , // Explicitly passing null as RuntimeShader is created with the
+ // matrix directly
+ skShader(effect.makeShader(std::move(data), nullptr, 0, matrix, isOpaque)) {}
+
+sk_sp<SkShader> RuntimeShader::makeSkShader() {
+ return skShader;
+}
+
+RuntimeShader::~RuntimeShader() {}
+} // namespace android::uirenderer \ No newline at end of file
diff --git a/libs/hwui/shader/RuntimeShader.h b/libs/hwui/shader/RuntimeShader.h
new file mode 100644
index 000000000000..7fe0b0206467
--- /dev/null
+++ b/libs/hwui/shader/RuntimeShader.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Shader.h"
+#include "SkShader.h"
+#include "include/effects/SkRuntimeEffect.h"
+
+namespace android::uirenderer {
+
+/**
+ * RuntimeShader implementation that can map to either a SkShader or SkImageFilter
+ */
+class RuntimeShader : public Shader {
+public:
+ RuntimeShader(SkRuntimeEffect& effect, sk_sp<SkData> data, bool isOpaque,
+ const SkMatrix* matrix);
+ ~RuntimeShader() override;
+
+protected:
+ sk_sp<SkShader> makeSkShader() override;
+
+private:
+ sk_sp<SkShader> skShader;
+};
+} // namespace android::uirenderer
diff --git a/libs/hwui/shader/Shader.cpp b/libs/hwui/shader/Shader.cpp
new file mode 100644
index 000000000000..45123dd55002
--- /dev/null
+++ b/libs/hwui/shader/Shader.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Shader.h"
+
+#include "SkImageFilters.h"
+#include "SkPaint.h"
+#include "SkRefCnt.h"
+
+namespace android::uirenderer {
+
+Shader::Shader(const SkMatrix* matrix)
+ : localMatrix(matrix ? *matrix : SkMatrix::I())
+ , skShader(nullptr)
+ , skImageFilter(nullptr) {}
+
+Shader::~Shader() {}
+
+sk_sp<SkShader> Shader::asSkShader() {
+ // If we already have created a shader with these parameters just return the existing
+ // shader we have already created
+ if (!this->skShader.get()) {
+ this->skShader = makeSkShader();
+ if (this->skShader.get()) {
+ if (!localMatrix.isIdentity()) {
+ this->skShader = this->skShader->makeWithLocalMatrix(localMatrix);
+ }
+ }
+ }
+ return this->skShader;
+}
+
+/**
+ * By default return null as we cannot convert all visual effects to SkShader instances
+ */
+sk_sp<SkShader> Shader::makeSkShader() {
+ return nullptr;
+}
+
+sk_sp<SkImageFilter> Shader::asSkImageFilter() {
+ // If we already have created an ImageFilter with these parameters just return the existing
+ // ImageFilter we have already created
+ if (!this->skImageFilter.get()) {
+ // Attempt to create an SkImageFilter from the current Shader implementation
+ this->skImageFilter = makeSkImageFilter();
+ if (this->skImageFilter) {
+ if (!localMatrix.isIdentity()) {
+ // If we have created an SkImageFilter and we have a transformation, wrap
+ // the created SkImageFilter to apply the given matrix
+ this->skImageFilter = SkImageFilters::MatrixTransform(
+ localMatrix, kMedium_SkFilterQuality, this->skImageFilter);
+ }
+ } else {
+ // Otherwise if no SkImageFilter implementation is provided, create one from
+ // the result of asSkShader. Note the matrix is already applied to the shader in
+ // this case so just convert it to an SkImageFilter using SkImageFilters::Paint
+ SkPaint paint;
+ paint.setShader(asSkShader());
+ sk_sp<SkImageFilter> paintFilter = SkImageFilters::Paint(paint);
+ this->skImageFilter = SkImageFilters::Xfermode(SkBlendMode::kDstIn,
+ std::move(paintFilter));
+ }
+ }
+ return this->skImageFilter;
+}
+
+/**
+ * By default return null for subclasses to implement. If there is not a direct SkImageFilter
+ * conversion
+ */
+sk_sp<SkImageFilter> Shader::makeSkImageFilter() {
+ return nullptr;
+}
+} // namespace android::uirenderer \ No newline at end of file
diff --git a/libs/hwui/shader/Shader.h b/libs/hwui/shader/Shader.h
new file mode 100644
index 000000000000..3c0cdaae8253
--- /dev/null
+++ b/libs/hwui/shader/Shader.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "SkImageFilter.h"
+#include "SkShader.h"
+#include "SkPaint.h"
+#include "SkRefCnt.h"
+
+class SkMatrix;
+
+namespace android::uirenderer {
+
+/**
+ * Shader class that can optionally wrap an SkShader or SkImageFilter depending
+ * on the implementation
+ */
+class Shader: public SkRefCnt {
+public:
+ /**
+ * Creates a Shader instance with an optional transformation matrix
+ * @param matrix Optional matrix to transform the underlying SkShader or SkImageFilter
+ */
+ Shader(const SkMatrix* matrix);
+ virtual ~Shader();
+
+ /**
+ * Create an SkShader from the current Shader instance or return a previously
+ * created instance. This can be null if no SkShader could be created from this
+ * Shader instance.
+ */
+ sk_sp<SkShader> asSkShader();
+
+ /**
+ * Create an SkImageFilter from the current Shader instance or return a previously
+ * created instance. Unlike asSkShader, this method cannot return null.
+ */
+ sk_sp<SkImageFilter> asSkImageFilter();
+
+protected:
+ /**
+ * Create a new SkShader instance based on this Shader instance
+ */
+ virtual sk_sp<SkShader> makeSkShader();
+
+ /**
+ * Create a new SkImageFilter instance based on this Shader instance. If no SkImageFilter
+ * can be created then return nullptr
+ */
+ virtual sk_sp<SkImageFilter> makeSkImageFilter();
+
+private:
+ /**
+ * Optional matrix transform
+ */
+ const SkMatrix localMatrix;
+
+ /**
+ * Cached SkShader instance to be returned on subsequent queries
+ */
+ sk_sp<SkShader> skShader;
+
+ /**
+ * Cached SkImageFilter instance to be returned on subsequent queries
+ */
+ sk_sp<SkImageFilter> skImageFilter;
+};
+} // namespace android::uirenderer
diff --git a/libs/hwui/shader/SweepGradientShader.cpp b/libs/hwui/shader/SweepGradientShader.cpp
new file mode 100644
index 000000000000..3b1f37f8b051
--- /dev/null
+++ b/libs/hwui/shader/SweepGradientShader.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SweepGradientShader.h"
+
+#include <vector>
+
+#include "SkGradientShader.h"
+#include "SkImageFilters.h"
+
+namespace android::uirenderer {
+
+SweepGradientShader::SweepGradientShader(float x, float y, const std::vector<SkColor4f>& colors,
+ const sk_sp<SkColorSpace>& colorspace, const SkScalar pos[],
+ const uint32_t shaderFlags, const SkMatrix* matrix)
+ : Shader(matrix)
+ , skShader(SkGradientShader::MakeSweep(x, y, colors.data(), colorspace, pos, colors.size(),
+ shaderFlags, nullptr)) {}
+
+sk_sp<SkShader> SweepGradientShader::makeSkShader() {
+ return skShader;
+}
+
+SweepGradientShader::~SweepGradientShader() {}
+} // namespace android::uirenderer \ No newline at end of file
diff --git a/libs/hwui/shader/SweepGradientShader.h b/libs/hwui/shader/SweepGradientShader.h
new file mode 100644
index 000000000000..dad3ef0ffad4
--- /dev/null
+++ b/libs/hwui/shader/SweepGradientShader.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Shader.h"
+#include "SkShader.h"
+
+namespace android::uirenderer {
+
+/**
+ * Shader implementation that renders a color ramp clockwise such that the start and end colors
+ * are visible at 3 o'clock. This handles converting to either an SkShader or SkImageFilter
+ */
+class SweepGradientShader : public Shader {
+public:
+ SweepGradientShader(float x, float y, const std::vector<SkColor4f>& colors,
+ const sk_sp<SkColorSpace>& colorspace, const SkScalar pos[],
+ const uint32_t shaderFlags, const SkMatrix* matrix);
+ virtual ~SweepGradientShader() override;
+
+protected:
+ virtual sk_sp<SkShader> makeSkShader() override;
+
+private:
+ sk_sp<SkShader> skShader;
+};
+} // namespace android::uirenderer
diff --git a/libs/hwui/tests/common/scenes/BitmapShaders.cpp b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
index c4067af388e3..e2c1651d823a 100644
--- a/libs/hwui/tests/common/scenes/BitmapShaders.cpp
+++ b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
@@ -18,6 +18,7 @@
#include "hwui/Paint.h"
#include "TestSceneBase.h"
#include "tests/common/BitmapAllocationTestUtils.h"
+#include <shader/BitmapShader.h>
#include "utils/Color.h"
class BitmapShaders;
@@ -45,15 +46,24 @@ public:
});
Paint paint;
+ sk_sp<BitmapShader> bitmapShader = sk_make_sp<BitmapShader>(
+ hwuiBitmap->makeImage(),
+ SkTileMode::kRepeat,
+ SkTileMode::kRepeat,
+ nullptr
+ );
+
sk_sp<SkImage> image = hwuiBitmap->makeImage();
- sk_sp<SkShader> repeatShader =
- image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat);
- paint.setShader(std::move(repeatShader));
+ paint.setShader(std::move(bitmapShader));
canvas.drawRoundRect(0, 0, 500, 500, 50.0f, 50.0f, paint);
- sk_sp<SkShader> mirrorShader =
- image->makeShader(SkTileMode::kMirror, SkTileMode::kMirror);
- paint.setShader(std::move(mirrorShader));
+ sk_sp<BitmapShader> mirrorBitmapShader = sk_make_sp<BitmapShader>(
+ image,
+ SkTileMode::kMirror,
+ SkTileMode::kMirror,
+ nullptr
+ );
+ paint.setShader(std::move(mirrorBitmapShader));
canvas.drawRoundRect(0, 600, 500, 1100, 50.0f, 50.0f, paint);
}
diff --git a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
index 5886ea39acce..d37bc3c7d37c 100644
--- a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
+++ b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
@@ -20,6 +20,10 @@
#include <SkGradientShader.h>
#include <SkImagePriv.h>
#include <ui/PixelFormat.h>
+#include <shader/BitmapShader.h>
+#include <shader/LinearGradientShader.h>
+#include <shader/RadialGradientShader.h>
+#include <shader/ComposeShader.h>
class HwBitmapInCompositeShader;
@@ -50,20 +54,41 @@ public:
pixels[4000 + 4 * i + 3] = 255;
}
buffer->unlock();
- sk_sp<Bitmap> hardwareBitmap(Bitmap::createFrom(buffer->toAHardwareBuffer(),
- SkColorSpace::MakeSRGB()));
- sk_sp<SkShader> hardwareShader(createBitmapShader(*hardwareBitmap));
+
+ sk_sp<BitmapShader> bitmapShader = sk_make_sp<BitmapShader>(
+ Bitmap::createFrom(
+ buffer->toAHardwareBuffer(),
+ SkColorSpace::MakeSRGB()
+ )->makeImage(),
+ SkTileMode::kClamp,
+ SkTileMode::kClamp,
+ nullptr
+ );
SkPoint center;
center.set(50, 50);
- SkColor colors[2];
- colors[0] = Color::Black;
- colors[1] = Color::White;
- sk_sp<SkShader> gradientShader = SkGradientShader::MakeRadial(
- center, 50, colors, nullptr, 2, SkTileMode::kRepeat);
-
- sk_sp<SkShader> compositeShader(
- SkShaders::Blend(SkBlendMode::kDstATop, hardwareShader, gradientShader));
+
+ std::vector<SkColor4f> vColors(2);
+ vColors[0] = SkColors::kBlack;
+ vColors[1] = SkColors::kWhite;
+
+ sk_sp<RadialGradientShader> radialShader = sk_make_sp<RadialGradientShader>(
+ center,
+ 50,
+ vColors,
+ SkColorSpace::MakeSRGB(),
+ nullptr,
+ SkTileMode::kRepeat,
+ 0,
+ nullptr
+ );
+
+ sk_sp<ComposeShader> compositeShader = sk_make_sp<ComposeShader>(
+ *bitmapShader.get(),
+ *radialShader.get(),
+ SkBlendMode::kDstATop,
+ nullptr
+ );
Paint paint;
paint.setShader(std::move(compositeShader));
diff --git a/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp b/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
index a9449b62a1f8..76e39deedd9a 100644
--- a/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
@@ -17,7 +17,8 @@
#include "TestSceneBase.h"
#include "tests/common/TestListViewSceneBase.h"
#include "hwui/Paint.h"
-#include <SkGradientShader.h>
+#include "SkColor.h"
+#include <shader/LinearGradientShader.h>
class ListOfFadedTextAnimation;
@@ -42,15 +43,26 @@ class ListOfFadedTextAnimation : public TestListViewSceneBase {
pts[0].set(0, 0);
pts[1].set(0, 1);
- SkColor colors[2] = {Color::Black, Color::Transparent};
- sk_sp<SkShader> s(
- SkGradientShader::MakeLinear(pts, colors, NULL, 2, SkTileMode::kClamp));
-
SkMatrix matrix;
matrix.setScale(1, length);
matrix.postRotate(-90);
+
+ std::vector<SkColor4f> vColors(2);
+ vColors[0] = SkColors::kBlack;
+ vColors[1] = SkColors::kTransparent;
+
+ sk_sp<LinearGradientShader> linearGradientShader = sk_make_sp<LinearGradientShader>(
+ pts,
+ vColors,
+ SkColorSpace::MakeSRGB(),
+ nullptr,
+ SkTileMode::kClamp,
+ 0,
+ &matrix
+ );
+
Paint fadingPaint;
- fadingPaint.setShader(s->makeWithLocalMatrix(matrix));
+ fadingPaint.setShader(linearGradientShader);
fadingPaint.setBlendMode(SkBlendMode::kDstOut);
canvas.drawRect(0, 0, length, itemHeight, fadingPaint);
canvas.restore();
diff --git a/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp b/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp
index a0bc5aa245d5..bdc157f85264 100644
--- a/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp
@@ -17,7 +17,7 @@
#include "TestSceneBase.h"
#include <SkColorMatrixFilter.h>
-#include <SkGradientShader.h>
+#include <shader/LinearGradientShader.h>
class SimpleColorMatrixAnimation;
@@ -65,9 +65,12 @@ private:
// enough renderer might apply it directly to the paint color)
float pos[] = {0, 1};
SkPoint pts[] = {SkPoint::Make(0, 0), SkPoint::Make(width, height)};
- SkColor colors[2] = {Color::DeepPurple_500, Color::DeepOrange_500};
- paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2,
- SkTileMode::kClamp));
+ std::vector<SkColor4f> colors(2);
+ colors[0] = SkColor4f::FromColor(Color::DeepPurple_500);
+ colors[1] = SkColor4f::FromColor(Color::DeepOrange_500);
+ paint.setShader(sk_make_sp<LinearGradientShader>(
+ pts, colors, SkColorSpace::MakeSRGB(), pos, SkTileMode::kClamp,
+ 0, nullptr));
// overdraw several times to emphasize shader cost
for (int i = 0; i < 10; i++) {
diff --git a/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp b/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp
index 57a260c8d234..9a15c9d370a4 100644
--- a/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp
@@ -17,6 +17,7 @@
#include "TestSceneBase.h"
#include <SkGradientShader.h>
+#include <shader/LinearGradientShader.h>
class SimpleGradientAnimation;
@@ -55,9 +56,24 @@ private:
// overdraw several times to emphasize shader cost
for (int i = 0; i < 10; i++) {
// use i%2 start position to pick 2 color combo with black in it
- SkColor colors[3] = {Color::Transparent, Color::Black, Color::Cyan_500};
- paint.setShader(SkGradientShader::MakeLinear(pts, colors + (i % 2), pos, 2,
- SkTileMode::kClamp));
+ std::vector<SkColor4f> vColors(2);
+ vColors[0] = ((i % 2) == 0) ?
+ SkColor4f::FromColor(Color::Transparent) :
+ SkColor4f::FromColor(Color::Black);
+ vColors[1] = (((i + 1) % 2) == 0) ?
+ SkColor4f::FromColor(Color::Black) :
+ SkColor4f::FromColor(Color::Cyan_500);
+
+ sk_sp<LinearGradientShader> gradient = sk_make_sp<LinearGradientShader>(
+ pts,
+ vColors,
+ SkColorSpace::MakeSRGB(),
+ pos,
+ SkTileMode::kClamp,
+ 0,
+ nullptr
+ );
+ paint.setShader(gradient);
canvas.drawRect(i, i, width, height, paint);
}
});
diff --git a/libs/hwui/tests/unit/VectorDrawableTests.cpp b/libs/hwui/tests/unit/VectorDrawableTests.cpp
index 6d4c57413f00..5e56b26f46f0 100644
--- a/libs/hwui/tests/unit/VectorDrawableTests.cpp
+++ b/libs/hwui/tests/unit/VectorDrawableTests.cpp
@@ -17,9 +17,14 @@
#include <gtest/gtest.h>
#include "PathParser.h"
+#include "GraphicsJNI.h"
+#include "SkGradientShader.h"
+#include "SkShader.h"
#include "VectorDrawable.h"
#include "utils/MathUtils.h"
#include "utils/VectorDrawableUtils.h"
+#include <shader/Shader.h>
+#include <shader/LinearGradientShader.h>
#include <functional>
@@ -395,7 +400,21 @@ TEST(VectorDrawable, drawPathWithoutIncrementingShaderRefCount) {
bitmap.allocN32Pixels(5, 5, false);
SkCanvas canvas(bitmap);
- sk_sp<SkShader> shader = SkShaders::Color(SK_ColorBLACK);
+ SkPoint pts[2];
+ pts[0].set(0, 0);
+ pts[1].set(0, 0);
+
+ std::vector<SkColor4f> colors(2);
+ colors[0] = SkColors::kBlack;
+ colors[1] = SkColors::kBlack;
+
+ sk_sp<LinearGradientShader> shader = sk_sp(new LinearGradientShader(pts,
+ colors,
+ SkColorSpace::MakeSRGB(),
+ nullptr,
+ SkTileMode::kClamp,
+ SkGradientShader::kInterpolateColorsInPremul_Flag,
+ nullptr));
// Initial ref count is 1
EXPECT_TRUE(shader->unique());