summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/GLES20Canvas.java15
-rw-r--r--core/java/android/widget/TextView.java5
-rw-r--r--core/jni/android/graphics/Paint.cpp18
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp9
-rw-r--r--graphics/java/android/graphics/Paint.java59
-rw-r--r--graphics/java/android/graphics/drawable/ShapeDrawable.java2
-rw-r--r--libs/hwui/DeferredDisplayList.cpp2
-rw-r--r--libs/hwui/DisplayListOp.h51
-rw-r--r--libs/hwui/DisplayListRenderer.cpp10
-rw-r--r--libs/hwui/DisplayListRenderer.h3
-rw-r--r--libs/hwui/OpenGLRenderer.cpp40
-rw-r--r--libs/hwui/OpenGLRenderer.h36
-rw-r--r--libs/hwui/Renderer.h3
-rw-r--r--libs/hwui/utils/Blur.cpp33
-rw-r--r--libs/hwui/utils/Blur.h6
15 files changed, 118 insertions, 174 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index f234baa..6c451eb 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -43,7 +43,6 @@ import android.text.TextUtils;
class GLES20Canvas extends HardwareCanvas {
// Must match modifiers used in the JNI layer
private static final int MODIFIER_NONE = 0;
- private static final int MODIFIER_SHADOW = 1;
private static final int MODIFIER_SHADER = 2;
private final boolean mOpaque;
@@ -1297,12 +1296,6 @@ class GLES20Canvas extends HardwareCanvas {
private int setupModifiers(Paint paint) {
int modifiers = MODIFIER_NONE;
- if (paint.hasShadow) {
- nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy,
- paint.shadowColor);
- modifiers |= MODIFIER_SHADOW;
- }
-
final Shader shader = paint.getShader();
if (shader != null) {
nSetupShader(mRenderer, shader.native_shader);
@@ -1315,12 +1308,6 @@ class GLES20Canvas extends HardwareCanvas {
private int setupModifiers(Paint paint, int flags) {
int modifiers = MODIFIER_NONE;
- if (paint.hasShadow && (flags & MODIFIER_SHADOW) != 0) {
- nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy,
- paint.shadowColor);
- modifiers |= MODIFIER_SHADOW;
- }
-
final Shader shader = paint.getShader();
if (shader != null && (flags & MODIFIER_SHADER) != 0) {
nSetupShader(mRenderer, shader.native_shader);
@@ -1331,8 +1318,6 @@ class GLES20Canvas extends HardwareCanvas {
}
private static native void nSetupShader(long renderer, long shader);
- private static native void nSetupShadow(long renderer, float radius,
- float dx, float dy, int color);
private static native void nResetModifiers(long renderer, int modifiers);
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b91111d..8f073de 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -289,6 +289,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private Spannable.Factory mSpannableFactory = Spannable.Factory.getInstance();
private float mShadowRadius, mShadowDx, mShadowDy;
+ private int mShadowColor;
+
private boolean mPreDrawRegistered;
@@ -2755,6 +2757,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mShadowRadius = radius;
mShadowDx = dx;
mShadowDy = dy;
+ mShadowColor = color;
// Will change text clip region
if (mEditor != null) mEditor.invalidateTextDisplayList();
@@ -2804,7 +2807,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @attr ref android.R.styleable#TextView_shadowColor
*/
public int getShadowColor() {
- return mTextPaint.shadowColor;
+ return mShadowColor;
}
/**
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 08a88d1..22c17dd 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -33,6 +33,7 @@
#include "SkXfermode.h"
#include "unicode/uloc.h"
#include "unicode/ushape.h"
+#include "utils/Blur.h"
#include "TextLayout.h"
// temporary for debugging
@@ -776,19 +777,23 @@ public:
env->ReleaseStringChars(text, textArray);
}
- static void setShadowLayer(JNIEnv* env, jobject jpaint, jfloat radius,
+ static void setShadowLayer(JNIEnv* env, jobject clazz, jlong paintHandle, jfloat radius,
jfloat dx, jfloat dy, jint color) {
- NPE_CHECK_RETURN_VOID(env, jpaint);
-
- SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
if (radius <= 0) {
paint->setLooper(NULL);
}
else {
- paint->setLooper(new SkBlurDrawLooper(radius, dx, dy, (SkColor)color))->unref();
+ SkScalar sigma = android::uirenderer::Blur::convertRadiusToSigma(radius);
+ paint->setLooper(new SkBlurDrawLooper((SkColor)color, sigma, dx, dy))->unref();
}
}
+ static jboolean hasShadowLayer(JNIEnv* env, jobject clazz, jlong paintHandle) {
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ return paint->getLooper() && paint->getLooper()->asABlurShadow(NULL);
+ }
+
static int breakText(JNIEnv* env, SkPaint& paint, const jchar text[],
int count, float maxWidth, jint bidiFlags, jfloatArray jmeasured,
SkPaint::TextBufferDirection tbd) {
@@ -968,7 +973,8 @@ static JNINativeMethod methods[] = {
(void*) SkPaintGlue::getStringBounds },
{"nativeGetCharArrayBounds", "(J[CIIILandroid/graphics/Rect;)V",
(void*) SkPaintGlue::getCharArrayBounds },
- {"nSetShadowLayer", "(FFFI)V", (void*)SkPaintGlue::setShadowLayer}
+ {"native_setShadowLayer", "(JFFFI)V", (void*)SkPaintGlue::setShadowLayer},
+ {"native_hasShadowLayer", "(J)Z", (void*)SkPaintGlue::hasShadowLayer}
};
static jfieldID req_fieldID(jfieldID id) {
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 7b2f829..fae6698 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -79,7 +79,6 @@ using namespace uirenderer;
#define RENDERER_LOGD(...)
#endif
-#define MODIFIER_SHADOW 1
#define MODIFIER_SHADER 2
// ----------------------------------------------------------------------------
@@ -617,7 +616,6 @@ static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject clazz,
static void android_view_GLES20Canvas_resetModifiers(JNIEnv* env, jobject clazz,
jlong rendererPtr, jint modifiers) {
OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- if (modifiers & MODIFIER_SHADOW) renderer->resetShadow();
if (modifiers & MODIFIER_SHADER) renderer->resetShader();
}
@@ -629,12 +627,6 @@ static void android_view_GLES20Canvas_setupShader(JNIEnv* env, jobject clazz,
}
-static void android_view_GLES20Canvas_setupShadow(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jfloat radius, jfloat dx, jfloat dy, jint color) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- renderer->setupShadow(radius, dx, dy, color);
-}
-
// ----------------------------------------------------------------------------
// Draw filters
// ----------------------------------------------------------------------------
@@ -1032,7 +1024,6 @@ static JNINativeMethod gMethods[] = {
{ "nResetModifiers", "(JI)V", (void*) android_view_GLES20Canvas_resetModifiers },
{ "nSetupShader", "(JJ)V", (void*) android_view_GLES20Canvas_setupShader },
- { "nSetupShadow", "(JFFFI)V", (void*) android_view_GLES20Canvas_setupShadow },
{ "nSetupPaintFilter", "(JII)V", (void*) android_view_GLES20Canvas_setupPaintFilter },
{ "nResetPaintFilter", "(J)V", (void*) android_view_GLES20Canvas_resetPaintFilter },
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 1e1128e..457b3ea 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -55,27 +55,6 @@ public class Paint {
/**
* @hide
*/
- public boolean hasShadow;
- /**
- * @hide
- */
- public float shadowDx;
- /**
- * @hide
- */
- public float shadowDy;
- /**
- * @hide
- */
- public float shadowRadius;
- /**
- * @hide
- */
- public int shadowColor;
-
- /**
- * @hide
- */
public int mBidiFlags = BIDI_DEFAULT_LTR;
static final Style[] sStyleArray = {
@@ -492,12 +471,6 @@ public class Paint {
mCompatScaling = 1;
mInvCompatScaling = 1;
- hasShadow = false;
- shadowDx = 0;
- shadowDy = 0;
- shadowRadius = 0;
- shadowColor = 0;
-
mBidiFlags = BIDI_DEFAULT_LTR;
setTextLocale(Locale.getDefault());
setElegantTextHeight(false);
@@ -538,12 +511,6 @@ public class Paint {
mCompatScaling = paint.mCompatScaling;
mInvCompatScaling = paint.mInvCompatScaling;
- hasShadow = paint.hasShadow;
- shadowDx = paint.shadowDx;
- shadowDy = paint.shadowDy;
- shadowRadius = paint.shadowRadius;
- shadowColor = paint.shadowColor;
-
mBidiFlags = paint.mBidiFlags;
mLocale = paint.mLocale;
}
@@ -1135,22 +1102,24 @@ public class Paint {
* layer is removed.
*/
public void setShadowLayer(float radius, float dx, float dy, int color) {
- hasShadow = radius > 0.0f;
- shadowRadius = radius;
- shadowDx = dx;
- shadowDy = dy;
- shadowColor = color;
- nSetShadowLayer(radius, dx, dy, color);
+ native_setShadowLayer(mNativePaint, radius, dx, dy, color);
}
-
- private native void nSetShadowLayer(float radius, float dx, float dy, int color);
/**
* Clear the shadow layer.
*/
public void clearShadowLayer() {
- hasShadow = false;
- nSetShadowLayer(0, 0, 0, 0);
+ setShadowLayer(0, 0, 0, 0);
+ }
+
+ /**
+ * Checks if the paint has a shadow layer attached
+ *
+ * @return true if the paint has a shadow layer attached and false otherwise
+ * @hide
+ */
+ public boolean hasShadowLayer() {
+ return native_hasShadowLayer(mNativePaint);
}
/**
@@ -2295,4 +2264,8 @@ public class Paint {
private static native void nativeGetCharArrayBounds(long nativePaint,
char[] text, int index, int count, int bidiFlags, Rect bounds);
private static native void finalizer(long nativePaint);
+
+ private static native void native_setShadowLayer(long native_object,
+ float radius, float dx, float dy, int color);
+ private static native boolean native_hasShadowLayer(long native_object);
}
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index 61b1b85..99ab4dd 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -237,7 +237,7 @@ public class ShapeDrawable extends Drawable {
paint.setAlpha(modulateAlpha(prevAlpha, state.mAlpha));
// only draw shape if it may affect output
- if (paint.getAlpha() != 0 || paint.getXfermode() != null || paint.hasShadow) {
+ if (paint.getAlpha() != 0 || paint.getXfermode() != null || paint.hasShadowLayer()) {
final boolean clearColorFilter;
if (mTintFilter != null && paint.getColorFilter() == null) {
paint.setColorFilter(mTintFilter);
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 3d58964..45b6624 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -190,7 +190,7 @@ public:
// Overlapping other operations is only allowed for text without shadow. For other ops,
// multiDraw isn't guaranteed to overdraw correctly
- if (!isTextBatch || state->mDrawModifiers.mHasShadow) {
+ if (!isTextBatch || op->hasTextShadow()) {
if (intersects(state->mBounds)) return false;
}
const DeferredDisplayState* lhs = state;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index ce92beb..f1d70eb 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -183,6 +183,10 @@ public:
return OpenGLRenderer::getAlphaDirect(mPaint);
}
+ virtual bool hasTextShadow() const {
+ return false;
+ }
+
inline float strokeWidthOutset() {
// since anything AA stroke with less than 1.0 pixel width is drawn with an alpha-reduced
// 1.0 stroke, treat 1.0 as minimum.
@@ -244,11 +248,11 @@ public:
bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
localBounds.set(mLocalBounds);
- if (drawModifiers.mHasShadow) {
- // TODO: inspect paint's looper directly
+ OpenGLRenderer::TextShadow textShadow;
+ if (OpenGLRenderer::getTextShadow(mPaint, &textShadow)) {
Rect shadow(mLocalBounds);
- shadow.translate(drawModifiers.mShadowDx, drawModifiers.mShadowDy);
- shadow.outset(drawModifiers.mShadowRadius);
+ shadow.translate(textShadow.dx, textShadow.dx);
+ shadow.outset(textShadow.radius);
localBounds.unionWith(shadow);
}
return true;
@@ -619,41 +623,6 @@ private:
SkiaShader* mShader;
};
-class ResetShadowOp : public StateOp {
-public:
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
- renderer.resetShadow();
- }
-
- virtual void output(int level, uint32_t logFlags) const {
- OP_LOGS("ResetShadow");
- }
-
- virtual const char* name() { return "ResetShadow"; }
-};
-
-class SetupShadowOp : public StateOp {
-public:
- SetupShadowOp(float radius, float dx, float dy, int color)
- : mRadius(radius), mDx(dx), mDy(dy), mColor(color) {}
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
- renderer.setupShadow(mRadius, mDx, mDy, mColor);
- }
-
- virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("SetupShadow, radius %f, %f, %f, color %#x", mRadius, mDx, mDy, mColor);
- }
-
- virtual const char* name() { return "SetupShadow"; }
-
-private:
- float mRadius;
- float mDx;
- float mDy;
- int mColor;
-};
-
class ResetPaintFilterOp : public StateOp {
public:
virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
@@ -1351,6 +1320,10 @@ public:
OP_LOG("Draw some text, %d bytes", mBytesCount);
}
+ virtual bool hasTextShadow() const {
+ return OpenGLRenderer::hasTextShadow(mPaint);
+ }
+
virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
const DeferredDisplayState& state) {
const SkPaint* paint = getPaint(renderer);
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 8afd106..c2ce6ed 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -410,16 +410,6 @@ void DisplayListRenderer::setupShader(SkiaShader* shader) {
addStateOp(new (alloc()) SetupShaderOp(shader));
}
-void DisplayListRenderer::resetShadow() {
- addStateOp(new (alloc()) ResetShadowOp());
- OpenGLRenderer::resetShadow();
-}
-
-void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) {
- addStateOp(new (alloc()) SetupShadowOp(radius, dx, dy, color));
- OpenGLRenderer::setupShadow(radius, dx, dy, color);
-}
-
void DisplayListRenderer::resetPaintFilter() {
addStateOp(new (alloc()) ResetPaintFilterOp());
}
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 25e78c1..185179a 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -102,9 +102,6 @@ public:
virtual void resetShader();
virtual void setupShader(SkiaShader* shader);
- virtual void resetShadow();
- virtual void setupShadow(float radius, float dx, float dy, int color);
-
virtual void resetPaintFilter();
virtual void setupPaintFilter(int clearBits, int setBits);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 6de369c..87b07b3 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2654,28 +2654,32 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text,
FontRenderer& fontRenderer, int alpha, float x, float y) {
mCaches.activeTexture(0);
+ TextShadow textShadow;
+ if (!getTextShadow(paint, &textShadow)) {
+ LOG_ALWAYS_FATAL("failed to query shadow attributes");
+ }
+
// NOTE: The drop shadow will not perform gamma correction
// if shader-based correction is enabled
mCaches.dropShadowCache.setFontRenderer(fontRenderer);
const ShadowTexture* shadow = mCaches.dropShadowCache.get(
- paint, text, bytesCount, count, mDrawModifiers.mShadowRadius, positions);
+ paint, text, bytesCount, count, textShadow.radius, positions);
// If the drop shadow exceeds the max texture size or couldn't be
// allocated, skip drawing
if (!shadow) return;
const AutoTexture autoCleanup(shadow);
- const float sx = x - shadow->left + mDrawModifiers.mShadowDx;
- const float sy = y - shadow->top + mDrawModifiers.mShadowDy;
+ const float sx = x - shadow->left + textShadow.dx;
+ const float sy = y - shadow->top + textShadow.dy;
- const int shadowAlpha = ((mDrawModifiers.mShadowColor >> 24) & 0xFF) * mSnapshot->alpha;
- int shadowColor = mDrawModifiers.mShadowColor;
+ const int shadowAlpha = ((textShadow.color >> 24) & 0xFF) * mSnapshot->alpha;
if (mDrawModifiers.mShader) {
- shadowColor = 0xffffffff;
+ textShadow.color = SK_ColorWHITE;
}
setupDraw();
setupDrawWithTexture(true);
- setupDrawAlpha8Color(shadowColor, shadowAlpha < 255 ? shadowAlpha : alpha);
+ setupDrawAlpha8Color(textShadow.color, shadowAlpha < 255 ? shadowAlpha : alpha);
setupDrawColorFilter(getColorFilter(paint));
setupDrawShader();
setupDrawBlending(paint, true);
@@ -2692,7 +2696,7 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text,
}
bool OpenGLRenderer::canSkipText(const SkPaint* paint) const {
- float alpha = (mDrawModifiers.mHasShadow ? 1.0f : paint->getAlpha()) * mSnapshot->alpha;
+ float alpha = (hasTextShadow(paint) ? 1.0f : paint->getAlpha()) * mSnapshot->alpha;
return alpha == 0.0f && getXfermode(paint->getXfermode()) == SkXfermode::kSrcOver_Mode;
}
@@ -2724,7 +2728,7 @@ status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count
SkXfermode::Mode mode;
getAlphaAndMode(paint, &alpha, &mode);
- if (CC_UNLIKELY(mDrawModifiers.mHasShadow)) {
+ if (CC_UNLIKELY(hasTextShadow(paint))) {
drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer,
alpha, 0.0f, 0.0f);
}
@@ -2801,7 +2805,7 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, f
FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
- if (CC_UNLIKELY(mDrawModifiers.mHasShadow)) {
+ if (CC_UNLIKELY(hasTextShadow(paint))) {
fontRenderer.setFont(paint, mat4::identity());
drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer,
alpha, oldX, oldY);
@@ -3022,22 +3026,6 @@ void OpenGLRenderer::setupShader(SkiaShader* shader) {
}
///////////////////////////////////////////////////////////////////////////////
-// Drop shadow
-///////////////////////////////////////////////////////////////////////////////
-
-void OpenGLRenderer::resetShadow() {
- mDrawModifiers.mHasShadow = false;
-}
-
-void OpenGLRenderer::setupShadow(float radius, float dx, float dy, int color) {
- mDrawModifiers.mHasShadow = true;
- mDrawModifiers.mShadowRadius = radius;
- mDrawModifiers.mShadowDx = dx;
- mDrawModifiers.mShadowDy = dy;
- mDrawModifiers.mShadowColor = color;
-}
-
-///////////////////////////////////////////////////////////////////////////////
// Draw filters
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 4de52ac..1d46945 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -29,6 +29,7 @@
#include <SkShader.h>
#include <SkXfermode.h>
+#include <utils/Blur.h>
#include <utils/Functor.h>
#include <utils/RefBase.h>
#include <utils/SortedVector.h>
@@ -72,13 +73,6 @@ struct DrawModifiers {
SkiaShader* mShader;
float mOverrideLayerAlpha;
- // Drop shadow
- bool mHasShadow;
- float mShadowRadius;
- float mShadowDx;
- float mShadowDy;
- int mShadowColor;
-
// Draw filters
bool mHasDrawFilter;
int mPaintFilterClearBits;
@@ -226,9 +220,6 @@ public:
virtual void resetShader();
virtual void setupShader(SkiaShader* shader);
- virtual void resetShadow();
- virtual void setupShadow(float radius, float dx, float dy, int color);
-
virtual void resetPaintFilter();
virtual void setupPaintFilter(int clearBits, int setBits);
@@ -316,6 +307,31 @@ public:
return paint->getAlpha();
}
+ struct TextShadow {
+ SkScalar radius;
+ float dx;
+ float dy;
+ SkColor color;
+ };
+
+ static inline bool getTextShadow(const SkPaint* paint, TextShadow* textShadow) {
+ SkDrawLooper::BlurShadowRec blur;
+ if (paint && paint->getLooper() && paint->getLooper()->asABlurShadow(&blur)) {
+ if (textShadow) {
+ textShadow->radius = Blur::convertSigmaToRadius(blur.fSigma);
+ textShadow->dx = blur.fOffset.fX;
+ textShadow->dy = blur.fOffset.fY;
+ textShadow->color = blur.fColor;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ static inline bool hasTextShadow(const SkPaint* paint) {
+ return getTextShadow(paint, NULL);
+ }
+
/**
* Return the best transform to use to rasterize text given a full
* transform matrix.
diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h
index 3209a53..57db816 100644
--- a/libs/hwui/Renderer.h
+++ b/libs/hwui/Renderer.h
@@ -178,9 +178,6 @@ public:
virtual void resetShader() = 0;
virtual void setupShader(SkiaShader* shader) = 0;
- virtual void resetShadow() = 0;
- virtual void setupShadow(float radius, float dx, float dy, int color) = 0;
-
virtual void resetPaintFilter() = 0;
virtual void setupPaintFilter(int clearBits, int setBits) = 0;
diff --git a/libs/hwui/utils/Blur.cpp b/libs/hwui/utils/Blur.cpp
index 85d90d0..c020b40 100644
--- a/libs/hwui/utils/Blur.cpp
+++ b/libs/hwui/utils/Blur.cpp
@@ -23,6 +23,31 @@
namespace android {
namespace uirenderer {
+// This constant approximates the scaling done in the software path's
+// "high quality" mode, in SkBlurMask::Blur() (1 / sqrt(3)).
+static const float BLUR_SIGMA_SCALE = 0.57735f;
+
+float Blur::convertRadiusToSigma(float radius) {
+ return radius > 0 ? BLUR_SIGMA_SCALE * radius + 0.5f : 0.0f;
+}
+
+float Blur::convertSigmaToRadius(float sigma) {
+ return sigma > 0.5f ? (sigma - 0.5f) / BLUR_SIGMA_SCALE : 0.0f;
+}
+
+/**
+ * HWUI has used a slightly different equation than Skia to generate the value
+ * for sigma and to preserve compatibility we have kept that logic.
+ *
+ * Based on some experimental radius and sigma values we approximate the
+ * equation sigma = f(radius) as sigma = radius * 0.3 + 0.6. The larger the
+ * radius gets, the more our gaussian blur will resemble a box blur since with
+ * large sigma the gaussian curve begins to lose its shape.
+ */
+static float legacyConvertRadiusToSigma(float radius) {
+ return radius > 0 ? 0.3f * radius + 0.6f : 0.0f;
+}
+
void Blur::generateGaussianWeights(float* weights, int32_t radius) {
// Compute gaussian weights for the blur
// e is the euler's number
@@ -31,13 +56,7 @@ void Blur::generateGaussianWeights(float* weights, int32_t radius) {
// g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 )
// x is of the form [-radius .. 0 .. radius]
// and sigma varies with radius.
- // Based on some experimental radius values and sigma's
- // we approximately fit sigma = f(radius) as
- // sigma = radius * 0.3 + 0.6
- // The larger the radius gets, the more our gaussian blur
- // will resemble a box blur since with large sigma
- // the gaussian curve begins to lose its shape
- float sigma = 0.3f * (float) radius + 0.6f;
+ float sigma = legacyConvertRadiusToSigma((float) radius);
// Now compute the coefficints
// We will store some redundant values to save some math during
diff --git a/libs/hwui/utils/Blur.h b/libs/hwui/utils/Blur.h
index 6c176e9..79aff65 100644
--- a/libs/hwui/utils/Blur.h
+++ b/libs/hwui/utils/Blur.h
@@ -18,12 +18,18 @@
#define ANDROID_HWUI_BLUR_H
#include <stdint.h>
+#include <cutils/compiler.h>
namespace android {
namespace uirenderer {
class Blur {
public:
+ // If radius > 0, return the corresponding sigma, else return 0
+ ANDROID_API static float convertRadiusToSigma(float radius);
+ // If sigma > 0.6, return the corresponding radius, else return 0
+ ANDROID_API static float convertSigmaToRadius(float sigma);
+
static void generateGaussianWeights(float* weights, int32_t radius);
static void horizontal(float* weights, int32_t radius, const uint8_t* source,
uint8_t* dest, int32_t width, int32_t height);