Loading core/jni/Android.bp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -126,7 +126,6 @@ cc_library_shared { "android/graphics/Camera.cpp", "android/graphics/Camera.cpp", "android/graphics/CanvasProperty.cpp", "android/graphics/CanvasProperty.cpp", "android/graphics/ColorFilter.cpp", "android/graphics/ColorFilter.cpp", "android/graphics/DrawFilter.cpp", "android/graphics/FontFamily.cpp", "android/graphics/FontFamily.cpp", "android/graphics/FontUtils.cpp", "android/graphics/FontUtils.cpp", "android/graphics/CreateJavaOutputStreamAdaptor.cpp", "android/graphics/CreateJavaOutputStreamAdaptor.cpp", Loading @@ -143,6 +142,7 @@ cc_library_shared { "android/graphics/NinePatch.cpp", "android/graphics/NinePatch.cpp", "android/graphics/NinePatchPeeker.cpp", "android/graphics/NinePatchPeeker.cpp", "android/graphics/Paint.cpp", "android/graphics/Paint.cpp", "android/graphics/PaintFilter.cpp", "android/graphics/Path.cpp", "android/graphics/Path.cpp", "android/graphics/PathMeasure.cpp", "android/graphics/PathMeasure.cpp", "android/graphics/PathEffect.cpp", "android/graphics/PathEffect.cpp", Loading core/jni/android/graphics/DrawFilter.cpp→core/jni/android/graphics/PaintFilter.cpp +33 −26 Original line number Original line Diff line number Diff line Loading @@ -15,36 +15,43 @@ ** limitations under the License. ** limitations under the License. */ */ // This file was generated from the C++ include file: SkColorFilter.h // Any changes made to this file will be discarded by the build. // To change this file, either edit the include, or device/tools/gluemaker/main.cpp, // or one of the auxilary file specifications in device/tools/gluemaker. #include "jni.h" #include "jni.h" #include "GraphicsJNI.h" #include "GraphicsJNI.h" #include <android_runtime/AndroidRuntime.h> #include <android_runtime/AndroidRuntime.h> #include "core_jni_helpers.h" #include "core_jni_helpers.h" #include "SkDrawFilter.h" #include "hwui/PaintFilter.h" #include "SkPaintFlagsDrawFilter.h" #include "SkPaint.h" #include "SkPaint.h" namespace android { namespace android { // Custom version of SkPaintFlagsDrawFilter that also calls setFilterQuality. class PaintFlagsFilter : public PaintFilter { class CompatFlagsDrawFilter : public SkPaintFlagsDrawFilter { public: PaintFlagsFilter(uint32_t clearFlags, uint32_t setFlags) { fClearFlags = static_cast<uint16_t>(clearFlags & SkPaint::kAllFlags); fSetFlags = static_cast<uint16_t>(setFlags & SkPaint::kAllFlags); } void filter(SkPaint* paint) override { paint->setFlags((paint->getFlags() & ~fClearFlags) | fSetFlags); } private: uint16_t fClearFlags; uint16_t fSetFlags; }; // Custom version of PaintFlagsDrawFilter that also calls setFilterQuality. class CompatPaintFlagsFilter : public PaintFlagsFilter { public: public: CompatFlagsDrawFilter(uint32_t clearFlags, uint32_t setFlags, CompatPaintFlagsFilter(uint32_t clearFlags, uint32_t setFlags, SkFilterQuality desiredQuality) SkFilterQuality desiredQuality) : PaintFlagsFilter(clearFlags, setFlags) : SkPaintFlagsDrawFilter(clearFlags, setFlags) , fDesiredQuality(desiredQuality) { , fDesiredQuality(desiredQuality) { } } virtual bool filter(SkPaint* paint, Type type) { virtual void filter(SkPaint* paint) { SkPaintFlagsDrawFilter::filter(paint, type); PaintFlagsFilter::filter(paint); paint->setFilterQuality(fDesiredQuality); paint->setFilterQuality(fDesiredQuality); return true; } } private: private: Loading @@ -61,15 +68,15 @@ static inline bool hadFiltering(jint& flags) { return result; return result; } } class SkDrawFilterGlue { class PaintFilterGlue { public: public: static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) { static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) { SkDrawFilter* obj = reinterpret_cast<SkDrawFilter*>(objHandle); PaintFilter* obj = reinterpret_cast<PaintFilter*>(objHandle); SkSafeUnref(obj); SkSafeUnref(obj); } } static jlong CreatePaintFlagsDF(JNIEnv* env, jobject clazz, static jlong CreatePaintFlagsFilter(JNIEnv* env, jobject clazz, jint clearFlags, jint setFlags) { jint clearFlags, jint setFlags) { if (clearFlags | setFlags) { if (clearFlags | setFlags) { // Mask both groups of flags to remove FILTER_BITMAP_FLAG, which no // Mask both groups of flags to remove FILTER_BITMAP_FLAG, which no Loading @@ -79,16 +86,16 @@ public: const bool turnFilteringOn = hadFiltering(setFlags); const bool turnFilteringOn = hadFiltering(setFlags); const bool turnFilteringOff = hadFiltering(clearFlags); const bool turnFilteringOff = hadFiltering(clearFlags); SkDrawFilter* filter; PaintFilter* filter; if (turnFilteringOn) { if (turnFilteringOn) { // Turning filtering on overrides turning it off. // Turning filtering on overrides turning it off. filter = new CompatFlagsDrawFilter(clearFlags, setFlags, filter = new CompatPaintFlagsFilter(clearFlags, setFlags, kLow_SkFilterQuality); kLow_SkFilterQuality); } else if (turnFilteringOff) { } else if (turnFilteringOff) { filter = new CompatFlagsDrawFilter(clearFlags, setFlags, filter = new CompatPaintFlagsFilter(clearFlags, setFlags, kNone_SkFilterQuality); kNone_SkFilterQuality); } else { } else { filter = new SkPaintFlagsDrawFilter(clearFlags, setFlags); filter = new PaintFlagsFilter(clearFlags, setFlags); } } return reinterpret_cast<jlong>(filter); return reinterpret_cast<jlong>(filter); } else { } else { Loading @@ -98,11 +105,11 @@ public: }; }; static const JNINativeMethod drawfilter_methods[] = { static const JNINativeMethod drawfilter_methods[] = { {"nativeDestructor", "(J)V", (void*) SkDrawFilterGlue::finalizer} {"nativeDestructor", "(J)V", (void*) PaintFilterGlue::finalizer} }; }; static const JNINativeMethod paintflags_methods[] = { static const JNINativeMethod paintflags_methods[] = { {"nativeConstructor","(II)J", (void*) SkDrawFilterGlue::CreatePaintFlagsDF} {"nativeConstructor","(II)J", (void*) PaintFilterGlue::CreatePaintFlagsFilter} }; }; int register_android_graphics_DrawFilter(JNIEnv* env) { int register_android_graphics_DrawFilter(JNIEnv* env) { Loading core/jni/android_graphics_Canvas.cpp +5 −4 Original line number Original line Diff line number Diff line Loading @@ -22,13 +22,13 @@ #include <androidfw/ResourceTypes.h> #include <androidfw/ResourceTypes.h> #include <hwui/Canvas.h> #include <hwui/Canvas.h> #include <hwui/Paint.h> #include <hwui/Paint.h> #include <hwui/PaintFilter.h> #include <hwui/Typeface.h> #include <hwui/Typeface.h> #include <minikin/Layout.h> #include <minikin/Layout.h> #include <nativehelper/ScopedPrimitiveArray.h> #include <nativehelper/ScopedPrimitiveArray.h> #include <nativehelper/ScopedStringChars.h> #include <nativehelper/ScopedStringChars.h> #include "Bitmap.h" #include "Bitmap.h" #include "SkDrawFilter.h" #include "SkGraphics.h" #include "SkGraphics.h" #include "SkRegion.h" #include "SkRegion.h" #include "SkVertices.h" #include "SkVertices.h" Loading Loading @@ -582,8 +582,9 @@ static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstri env->ReleaseStringChars(text, jchars); env->ReleaseStringChars(text, jchars); } } static void setDrawFilter(jlong canvasHandle, jlong filterHandle) { static void setPaintFilter(jlong canvasHandle, jlong filterHandle) { get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle)); PaintFilter* paintFilter = reinterpret_cast<PaintFilter*>(filterHandle); get_canvas(canvasHandle)->setPaintFilter(sk_ref_sp(paintFilter)); } } static void freeCaches(JNIEnv* env, jobject) { static void freeCaches(JNIEnv* env, jobject) { Loading Loading @@ -633,7 +634,7 @@ static const JNINativeMethod gMethods[] = { {"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect}, {"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect}, {"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect}, {"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect}, {"nClipPath","(JJI)Z", (void*) CanvasJNI::clipPath}, {"nClipPath","(JJI)Z", (void*) CanvasJNI::clipPath}, {"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter}, {"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setPaintFilter}, }; }; // If called from Canvas these are regular JNI // If called from Canvas these are regular JNI Loading libs/hwui/SkiaCanvas.cpp +58 −53 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include "VectorDrawable.h" #include "VectorDrawable.h" #include "hwui/Bitmap.h" #include "hwui/Bitmap.h" #include "hwui/MinikinUtils.h" #include "hwui/MinikinUtils.h" #include "hwui/PaintFilter.h" #include "pipeline/skia/AnimatedDrawables.h" #include "pipeline/skia/AnimatedDrawables.h" #include <SkAnimatedImage.h> #include <SkAnimatedImage.h> Loading @@ -28,7 +29,6 @@ #include <SkColorFilter.h> #include <SkColorFilter.h> #include <SkColorSpaceXformCanvas.h> #include <SkColorSpaceXformCanvas.h> #include <SkDeque.h> #include <SkDeque.h> #include <SkDrawFilter.h> #include <SkDrawable.h> #include <SkDrawable.h> #include <SkGraphics.h> #include <SkGraphics.h> #include <SkImage.h> #include <SkImage.h> Loading @@ -40,6 +40,8 @@ #include <SkTextBlob.h> #include <SkTextBlob.h> #include <memory> #include <memory> #include <optional> #include <utility> namespace android { namespace android { Loading Loading @@ -211,7 +213,7 @@ public: Clip(const SkRRect& rrect, SkClipOp op, const SkMatrix& m) Clip(const SkRRect& rrect, SkClipOp op, const SkMatrix& m) : mType(Type::RRect), mOp(op), mMatrix(m), mRRect(rrect) {} : mType(Type::RRect), mOp(op), mMatrix(m), mRRect(rrect) {} Clip(const SkPath& path, SkClipOp op, const SkMatrix& m) Clip(const SkPath& path, SkClipOp op, const SkMatrix& m) : mType(Type::Path), mOp(op), mMatrix(m), mPath(&path) {} : mType(Type::Path), mOp(op), mMatrix(m), mPath(std::in_place, path) {} void apply(SkCanvas* canvas) const { void apply(SkCanvas* canvas) const { canvas->setMatrix(mMatrix); canvas->setMatrix(mMatrix); Loading @@ -223,7 +225,7 @@ public: canvas->clipRRect(mRRect, mOp); canvas->clipRRect(mRRect, mOp); break; break; case Type::Path: case Type::Path: canvas->clipPath(*mPath.get(), mOp); canvas->clipPath(mPath.value(), mOp); break; break; } } } } Loading @@ -240,7 +242,7 @@ private: SkMatrix mMatrix; SkMatrix mMatrix; // These are logically a union (tracked separately due to non-POD path). // These are logically a union (tracked separately due to non-POD path). SkTLazy<SkPath> mPath; std::optional<SkPath> mPath; SkRRect mRRect; SkRRect mRRect; }; }; Loading Loading @@ -400,12 +402,12 @@ bool SkiaCanvas::clipPath(const SkPath* path, SkClipOp op) { // Canvas state operations: Filters // Canvas state operations: Filters // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- SkDrawFilter* SkiaCanvas::getDrawFilter() { PaintFilter* SkiaCanvas::getPaintFilter() { return mCanvas->getDrawFilter(); return mPaintFilter.get(); } } void SkiaCanvas::setDrawFilter(SkDrawFilter* drawFilter) { void SkiaCanvas::setPaintFilter(sk_sp<PaintFilter> paintFilter) { mCanvas->setDrawFilter(drawFilter); mPaintFilter = std::move(paintFilter); } } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- Loading Loading @@ -439,8 +441,15 @@ void SkiaCanvas::drawColor(int color, SkBlendMode mode) { mCanvas->drawColor(color, mode); mCanvas->drawColor(color, mode); } } SkiaCanvas::PaintCoW&& SkiaCanvas::filterPaint(PaintCoW&& paint) const { if (mPaintFilter) { mPaintFilter->filter(&paint.writeable()); } return std::move(paint); } void SkiaCanvas::drawPaint(const SkPaint& paint) { void SkiaCanvas::drawPaint(const SkPaint& paint) { mCanvas->drawPaint(paint); mCanvas->drawPaint(*filterPaint(paint)); } } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- Loading @@ -457,53 +466,53 @@ void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint pts[i].set(points[0], points[1]); pts[i].set(points[0], points[1]); points += 2; points += 2; } } mCanvas->drawPoints(mode, count, pts.get(), paint); mCanvas->drawPoints(mode, count, pts.get(), *filterPaint(paint)); } } void SkiaCanvas::drawPoint(float x, float y, const SkPaint& paint) { void SkiaCanvas::drawPoint(float x, float y, const SkPaint& paint) { mCanvas->drawPoint(x, y, paint); mCanvas->drawPoint(x, y, *filterPaint(paint)); } } void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint) { void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint) { this->drawPoints(points, count, paint, SkCanvas::kPoints_PointMode); this->drawPoints(points, count, *filterPaint(paint), SkCanvas::kPoints_PointMode); } } void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY, void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY, const SkPaint& paint) { const SkPaint& paint) { mCanvas->drawLine(startX, startY, stopX, stopY, paint); mCanvas->drawLine(startX, startY, stopX, stopY, *filterPaint(paint)); } } void SkiaCanvas::drawLines(const float* points, int count, const SkPaint& paint) { void SkiaCanvas::drawLines(const float* points, int count, const SkPaint& paint) { if (CC_UNLIKELY(count < 4 || paint.nothingToDraw())) return; if (CC_UNLIKELY(count < 4 || paint.nothingToDraw())) return; this->drawPoints(points, count, paint, SkCanvas::kLines_PointMode); this->drawPoints(points, count, *filterPaint(paint), SkCanvas::kLines_PointMode); } } void SkiaCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) { void SkiaCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; if (CC_UNLIKELY(paint.nothingToDraw())) return; mCanvas->drawRect({left, top, right, bottom}, paint); mCanvas->drawRect({left, top, right, bottom}, *filterPaint(paint)); } } void SkiaCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) { void SkiaCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; if (CC_UNLIKELY(paint.nothingToDraw())) return; mCanvas->drawRegion(region, paint); mCanvas->drawRegion(region, *filterPaint(paint)); } } void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, const SkPaint& paint) { const SkPaint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; if (CC_UNLIKELY(paint.nothingToDraw())) return; SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); mCanvas->drawRoundRect(rect, rx, ry, paint); mCanvas->drawRoundRect(rect, rx, ry, *filterPaint(paint)); } } void SkiaCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) { void SkiaCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) { if (CC_UNLIKELY(radius <= 0 || paint.nothingToDraw())) return; if (CC_UNLIKELY(radius <= 0 || paint.nothingToDraw())) return; mCanvas->drawCircle(x, y, radius, paint); mCanvas->drawCircle(x, y, radius, *filterPaint(paint)); } } void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) { void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; if (CC_UNLIKELY(paint.nothingToDraw())) return; SkRect oval = SkRect::MakeLTRB(left, top, right, bottom); SkRect oval = SkRect::MakeLTRB(left, top, right, bottom); mCanvas->drawOval(oval, paint); mCanvas->drawOval(oval, *filterPaint(paint)); } } void SkiaCanvas::drawArc(float left, float top, float right, float bottom, float startAngle, void SkiaCanvas::drawArc(float left, float top, float right, float bottom, float startAngle, Loading @@ -511,9 +520,9 @@ void SkiaCanvas::drawArc(float left, float top, float right, float bottom, float if (CC_UNLIKELY(paint.nothingToDraw())) return; if (CC_UNLIKELY(paint.nothingToDraw())) return; SkRect arc = SkRect::MakeLTRB(left, top, right, bottom); SkRect arc = SkRect::MakeLTRB(left, top, right, bottom); if (fabs(sweepAngle) >= 360.0f) { if (fabs(sweepAngle) >= 360.0f) { mCanvas->drawOval(arc, paint); mCanvas->drawOval(arc, *filterPaint(paint)); } else { } else { mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, paint); mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, *filterPaint(paint)); } } } } Loading @@ -522,19 +531,19 @@ void SkiaCanvas::drawPath(const SkPath& path, const SkPaint& paint) { if (CC_UNLIKELY(path.isEmpty() && (!path.isInverseFillType()))) { if (CC_UNLIKELY(path.isEmpty() && (!path.isInverseFillType()))) { return; return; } } mCanvas->drawPath(path, paint); mCanvas->drawPath(path, *filterPaint(paint)); } } void SkiaCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) { void SkiaCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) { mCanvas->drawVertices(vertices, mode, paint); mCanvas->drawVertices(vertices, mode, *filterPaint(paint)); } } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // Canvas draw operations: Bitmaps // Canvas draw operations: Bitmaps // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- const SkPaint* SkiaCanvas::addFilter(const SkPaint* origPaint, SkPaint* tmpPaint, SkiaCanvas::PaintCoW&& SkiaCanvas::filterBitmap(PaintCoW&& paint, sk_sp<SkColorFilter> colorSpaceFilter) { sk_sp<SkColorFilter> colorSpaceFilter) const { /* We don't apply the colorSpace filter if this canvas is already wrapped with /* We don't apply the colorSpace filter if this canvas is already wrapped with * a SkColorSpaceXformCanvas since it already takes care of converting the * a SkColorSpaceXformCanvas since it already takes care of converting the * contents of the bitmap into the appropriate colorspace. The mCanvasWrapper * contents of the bitmap into the appropriate colorspace. The mCanvasWrapper Loading @@ -542,39 +551,31 @@ const SkPaint* SkiaCanvas::addFilter(const SkPaint* origPaint, SkPaint* tmpPaint * to have a non-sRGB colorspace. * to have a non-sRGB colorspace. */ */ if (!mCanvasWrapper && colorSpaceFilter) { if (!mCanvasWrapper && colorSpaceFilter) { if (origPaint) { SkPaint& tmpPaint = paint.writeable(); *tmpPaint = *origPaint; if (tmpPaint.getColorFilter()) { } tmpPaint.setColorFilter(SkColorFilter::MakeComposeFilter(tmpPaint.refColorFilter(), std::move(colorSpaceFilter))); if (tmpPaint->getColorFilter()) { LOG_ALWAYS_FATAL_IF(!tmpPaint.getColorFilter()); tmpPaint->setColorFilter( SkColorFilter::MakeComposeFilter(tmpPaint->refColorFilter(), colorSpaceFilter)); LOG_ALWAYS_FATAL_IF(!tmpPaint->getColorFilter()); } else { } else { tmpPaint->setColorFilter(colorSpaceFilter); tmpPaint.setColorFilter(std::move(colorSpaceFilter)); } } return tmpPaint; } else { return origPaint; } } return filterPaint(std::move(paint)); } } void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) { void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) { SkPaint tmpPaint; sk_sp<SkColorFilter> colorFilter; sk_sp<SkColorFilter> colorFilter; sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); mCanvas->drawImage(image, left, top, addFilter(paint, &tmpPaint, colorFilter)); mCanvas->drawImage(image, left, top, filterBitmap(paint, std::move(colorFilter))); } } void SkiaCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) { void SkiaCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) { SkAutoCanvasRestore acr(mCanvas, true); SkAutoCanvasRestore acr(mCanvas, true); mCanvas->concat(matrix); mCanvas->concat(matrix); SkPaint tmpPaint; sk_sp<SkColorFilter> colorFilter; sk_sp<SkColorFilter> colorFilter; sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); mCanvas->drawImage(image, 0, 0, addFilter(paint, &tmpPaint, colorFilter)); mCanvas->drawImage(image, 0, 0, filterBitmap(paint, std::move(colorFilter))); } } void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight, void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight, Loading @@ -583,10 +584,9 @@ void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float s SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom); SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom); SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); SkPaint tmpPaint; sk_sp<SkColorFilter> colorFilter; sk_sp<SkColorFilter> colorFilter; sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); mCanvas->drawImageRect(image, srcRect, dstRect, addFilter(paint, &tmpPaint, colorFilter), mCanvas->drawImageRect(image, srcRect, dstRect, filterBitmap(paint, std::move(colorFilter)), SkCanvas::kFast_SrcRectConstraint); SkCanvas::kFast_SrcRectConstraint); } } Loading Loading @@ -665,21 +665,20 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight, #endif #endif // cons-up a shader for the bitmap // cons-up a shader for the bitmap SkPaint tmpPaint; PaintCoW paintCoW(paint); if (paint) { SkPaint& tmpPaint = paintCoW.writeable(); tmpPaint = *paint; } sk_sp<SkColorFilter> colorFilter; sk_sp<SkColorFilter> colorFilter; sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); sk_sp<SkShader> shader = sk_sp<SkShader> shader = image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); if (colorFilter) { if (colorFilter) { shader = shader->makeWithColorFilter(colorFilter); shader = shader->makeWithColorFilter(std::move(colorFilter)); } } tmpPaint.setShader(shader); tmpPaint.setShader(std::move(shader)); mCanvas->drawVertices(builder.detach(), SkBlendMode::kModulate, tmpPaint); mCanvas->drawVertices(builder.detach(), SkBlendMode::kModulate, *filterPaint(std::move(paintCoW))); } } void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, float dstLeft, void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, float dstLeft, Loading @@ -706,10 +705,10 @@ void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, floa lattice.fBounds = nullptr; lattice.fBounds = nullptr; SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); SkPaint tmpPaint; sk_sp<SkColorFilter> colorFilter; sk_sp<SkColorFilter> colorFilter; sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); mCanvas->drawImageLattice(image.get(), lattice, dst, addFilter(paint, &tmpPaint, colorFilter)); mCanvas->drawImageLattice(image.get(), lattice, dst, filterBitmap(paint, std::move(colorFilter))); } } double SkiaCanvas::drawAnimatedImage(AnimatedImageDrawable* imgDrawable) { double SkiaCanvas::drawAnimatedImage(AnimatedImageDrawable* imgDrawable) { Loading @@ -732,6 +731,9 @@ void SkiaCanvas::drawGlyphs(ReadGlyphFunc glyphFunc, int count, const SkPaint& p // glyphs centered or right-aligned; the offset above takes // glyphs centered or right-aligned; the offset above takes // care of all alignment. // care of all alignment. SkPaint paintCopy(paint); SkPaint paintCopy(paint); if (mPaintFilter) { mPaintFilter->filter(&paintCopy); } paintCopy.setTextAlign(SkPaint::kLeft_Align); paintCopy.setTextAlign(SkPaint::kLeft_Align); SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding); SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding); // Stroke with a hairline is drawn on HW with a fill style for compatibility with Android O and // Stroke with a hairline is drawn on HW with a fill style for compatibility with Android O and Loading Loading @@ -760,6 +762,9 @@ void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, // glyphs centered or right-aligned; the offsets take care of // glyphs centered or right-aligned; the offsets take care of // that portion of the alignment. // that portion of the alignment. SkPaint paintCopy(paint); SkPaint paintCopy(paint); if (mPaintFilter) { mPaintFilter->filter(&paintCopy); } paintCopy.setTextAlign(SkPaint::kLeft_Align); paintCopy.setTextAlign(SkPaint::kLeft_Align); SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding); SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding); Loading libs/hwui/SkiaCanvas.h +55 −5 Original line number Original line Diff line number Diff line Loading @@ -22,7 +22,9 @@ #include "hwui/Canvas.h" #include "hwui/Canvas.h" #include <SkCanvas.h> #include <SkCanvas.h> #include <SkTLazy.h> #include <cassert> #include <optional> namespace android { namespace android { Loading Loading @@ -87,8 +89,8 @@ public: virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) override; virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) override; virtual bool clipPath(const SkPath* path, SkClipOp op) override; virtual bool clipPath(const SkPath* path, SkClipOp op) override; virtual SkDrawFilter* getDrawFilter() override; virtual PaintFilter* getPaintFilter() override; virtual void setDrawFilter(SkDrawFilter* drawFilter) override; virtual void setPaintFilter(sk_sp<PaintFilter> paintFilter) override; virtual SkCanvasState* captureCanvasState() const override; virtual SkCanvasState* captureCanvasState() const override; Loading Loading @@ -158,6 +160,46 @@ protected: const SkPaint& paint, const SkPath& path, size_t start, const SkPaint& paint, const SkPath& path, size_t start, size_t end) override; size_t end) override; /** This class acts as a copy on write SkPaint. * * Initially this will be the SkPaint passed to the contructor. * The first time writable() is called this will become a copy of the * initial SkPaint (or a default SkPaint if nullptr). */ struct PaintCoW { PaintCoW(const SkPaint& that) : mPtr(&that) {} PaintCoW(const SkPaint* ptr) : mPtr(ptr) {} PaintCoW(const PaintCoW&) = delete; PaintCoW(PaintCoW&&) = delete; PaintCoW& operator=(const PaintCoW&) = delete; PaintCoW& operator=(PaintCoW&&) = delete; SkPaint& writeable() { if (!mStorage) { if (!mPtr) { mStorage.emplace(); } else { mStorage.emplace(*mPtr); } mPtr = &*mStorage; } return *mStorage; } operator const SkPaint*() const { return mPtr; } const SkPaint* operator->() const { assert(mPtr); return mPtr; } const SkPaint& operator*() const { assert(mPtr); return *mPtr; } explicit operator bool() { return mPtr != nullptr; } private: const SkPaint* mPtr; std::optional<SkPaint> mStorage; }; /** Filters the paint using the current paint filter. * * @param paint the paint to filter. Will be initialized with the default * SkPaint before filtering if filtering is required. */ PaintCoW&& filterPaint(PaintCoW&& paint) const; private: private: struct SaveRec { struct SaveRec { int saveCount; int saveCount; Loading @@ -174,8 +216,15 @@ private: void drawPoints(const float* points, int count, const SkPaint& paint, SkCanvas::PointMode mode); void drawPoints(const float* points, int count, const SkPaint& paint, SkCanvas::PointMode mode); const SkPaint* addFilter(const SkPaint* origPaint, SkPaint* tmpPaint, /** Filters the paint for bitmap drawing. sk_sp<SkColorFilter> colorSpaceFilter); * * After filtering the paint for bitmap drawing, * also calls filterPaint on the paint. * * @param paint the paint to filter. Will be initialized with the default * SkPaint before filtering if filtering is required. */ PaintCoW&& filterBitmap(PaintCoW&& paint, sk_sp<SkColorFilter> colorSpaceFilter) const; class Clip; class Clip; Loading @@ -185,6 +234,7 @@ private: // unless it is the same as mCanvasOwned.get() // unless it is the same as mCanvasOwned.get() std::unique_ptr<SkDeque> mSaveStack; // lazily allocated, tracks partial saves. std::unique_ptr<SkDeque> mSaveStack; // lazily allocated, tracks partial saves. std::vector<Clip> mClipStack; // tracks persistent clips. std::vector<Clip> mClipStack; // tracks persistent clips. sk_sp<PaintFilter> mPaintFilter; }; }; } // namespace android } // namespace android Loading
core/jni/Android.bp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -126,7 +126,6 @@ cc_library_shared { "android/graphics/Camera.cpp", "android/graphics/Camera.cpp", "android/graphics/CanvasProperty.cpp", "android/graphics/CanvasProperty.cpp", "android/graphics/ColorFilter.cpp", "android/graphics/ColorFilter.cpp", "android/graphics/DrawFilter.cpp", "android/graphics/FontFamily.cpp", "android/graphics/FontFamily.cpp", "android/graphics/FontUtils.cpp", "android/graphics/FontUtils.cpp", "android/graphics/CreateJavaOutputStreamAdaptor.cpp", "android/graphics/CreateJavaOutputStreamAdaptor.cpp", Loading @@ -143,6 +142,7 @@ cc_library_shared { "android/graphics/NinePatch.cpp", "android/graphics/NinePatch.cpp", "android/graphics/NinePatchPeeker.cpp", "android/graphics/NinePatchPeeker.cpp", "android/graphics/Paint.cpp", "android/graphics/Paint.cpp", "android/graphics/PaintFilter.cpp", "android/graphics/Path.cpp", "android/graphics/Path.cpp", "android/graphics/PathMeasure.cpp", "android/graphics/PathMeasure.cpp", "android/graphics/PathEffect.cpp", "android/graphics/PathEffect.cpp", Loading
core/jni/android/graphics/DrawFilter.cpp→core/jni/android/graphics/PaintFilter.cpp +33 −26 Original line number Original line Diff line number Diff line Loading @@ -15,36 +15,43 @@ ** limitations under the License. ** limitations under the License. */ */ // This file was generated from the C++ include file: SkColorFilter.h // Any changes made to this file will be discarded by the build. // To change this file, either edit the include, or device/tools/gluemaker/main.cpp, // or one of the auxilary file specifications in device/tools/gluemaker. #include "jni.h" #include "jni.h" #include "GraphicsJNI.h" #include "GraphicsJNI.h" #include <android_runtime/AndroidRuntime.h> #include <android_runtime/AndroidRuntime.h> #include "core_jni_helpers.h" #include "core_jni_helpers.h" #include "SkDrawFilter.h" #include "hwui/PaintFilter.h" #include "SkPaintFlagsDrawFilter.h" #include "SkPaint.h" #include "SkPaint.h" namespace android { namespace android { // Custom version of SkPaintFlagsDrawFilter that also calls setFilterQuality. class PaintFlagsFilter : public PaintFilter { class CompatFlagsDrawFilter : public SkPaintFlagsDrawFilter { public: PaintFlagsFilter(uint32_t clearFlags, uint32_t setFlags) { fClearFlags = static_cast<uint16_t>(clearFlags & SkPaint::kAllFlags); fSetFlags = static_cast<uint16_t>(setFlags & SkPaint::kAllFlags); } void filter(SkPaint* paint) override { paint->setFlags((paint->getFlags() & ~fClearFlags) | fSetFlags); } private: uint16_t fClearFlags; uint16_t fSetFlags; }; // Custom version of PaintFlagsDrawFilter that also calls setFilterQuality. class CompatPaintFlagsFilter : public PaintFlagsFilter { public: public: CompatFlagsDrawFilter(uint32_t clearFlags, uint32_t setFlags, CompatPaintFlagsFilter(uint32_t clearFlags, uint32_t setFlags, SkFilterQuality desiredQuality) SkFilterQuality desiredQuality) : PaintFlagsFilter(clearFlags, setFlags) : SkPaintFlagsDrawFilter(clearFlags, setFlags) , fDesiredQuality(desiredQuality) { , fDesiredQuality(desiredQuality) { } } virtual bool filter(SkPaint* paint, Type type) { virtual void filter(SkPaint* paint) { SkPaintFlagsDrawFilter::filter(paint, type); PaintFlagsFilter::filter(paint); paint->setFilterQuality(fDesiredQuality); paint->setFilterQuality(fDesiredQuality); return true; } } private: private: Loading @@ -61,15 +68,15 @@ static inline bool hadFiltering(jint& flags) { return result; return result; } } class SkDrawFilterGlue { class PaintFilterGlue { public: public: static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) { static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) { SkDrawFilter* obj = reinterpret_cast<SkDrawFilter*>(objHandle); PaintFilter* obj = reinterpret_cast<PaintFilter*>(objHandle); SkSafeUnref(obj); SkSafeUnref(obj); } } static jlong CreatePaintFlagsDF(JNIEnv* env, jobject clazz, static jlong CreatePaintFlagsFilter(JNIEnv* env, jobject clazz, jint clearFlags, jint setFlags) { jint clearFlags, jint setFlags) { if (clearFlags | setFlags) { if (clearFlags | setFlags) { // Mask both groups of flags to remove FILTER_BITMAP_FLAG, which no // Mask both groups of flags to remove FILTER_BITMAP_FLAG, which no Loading @@ -79,16 +86,16 @@ public: const bool turnFilteringOn = hadFiltering(setFlags); const bool turnFilteringOn = hadFiltering(setFlags); const bool turnFilteringOff = hadFiltering(clearFlags); const bool turnFilteringOff = hadFiltering(clearFlags); SkDrawFilter* filter; PaintFilter* filter; if (turnFilteringOn) { if (turnFilteringOn) { // Turning filtering on overrides turning it off. // Turning filtering on overrides turning it off. filter = new CompatFlagsDrawFilter(clearFlags, setFlags, filter = new CompatPaintFlagsFilter(clearFlags, setFlags, kLow_SkFilterQuality); kLow_SkFilterQuality); } else if (turnFilteringOff) { } else if (turnFilteringOff) { filter = new CompatFlagsDrawFilter(clearFlags, setFlags, filter = new CompatPaintFlagsFilter(clearFlags, setFlags, kNone_SkFilterQuality); kNone_SkFilterQuality); } else { } else { filter = new SkPaintFlagsDrawFilter(clearFlags, setFlags); filter = new PaintFlagsFilter(clearFlags, setFlags); } } return reinterpret_cast<jlong>(filter); return reinterpret_cast<jlong>(filter); } else { } else { Loading @@ -98,11 +105,11 @@ public: }; }; static const JNINativeMethod drawfilter_methods[] = { static const JNINativeMethod drawfilter_methods[] = { {"nativeDestructor", "(J)V", (void*) SkDrawFilterGlue::finalizer} {"nativeDestructor", "(J)V", (void*) PaintFilterGlue::finalizer} }; }; static const JNINativeMethod paintflags_methods[] = { static const JNINativeMethod paintflags_methods[] = { {"nativeConstructor","(II)J", (void*) SkDrawFilterGlue::CreatePaintFlagsDF} {"nativeConstructor","(II)J", (void*) PaintFilterGlue::CreatePaintFlagsFilter} }; }; int register_android_graphics_DrawFilter(JNIEnv* env) { int register_android_graphics_DrawFilter(JNIEnv* env) { Loading
core/jni/android_graphics_Canvas.cpp +5 −4 Original line number Original line Diff line number Diff line Loading @@ -22,13 +22,13 @@ #include <androidfw/ResourceTypes.h> #include <androidfw/ResourceTypes.h> #include <hwui/Canvas.h> #include <hwui/Canvas.h> #include <hwui/Paint.h> #include <hwui/Paint.h> #include <hwui/PaintFilter.h> #include <hwui/Typeface.h> #include <hwui/Typeface.h> #include <minikin/Layout.h> #include <minikin/Layout.h> #include <nativehelper/ScopedPrimitiveArray.h> #include <nativehelper/ScopedPrimitiveArray.h> #include <nativehelper/ScopedStringChars.h> #include <nativehelper/ScopedStringChars.h> #include "Bitmap.h" #include "Bitmap.h" #include "SkDrawFilter.h" #include "SkGraphics.h" #include "SkGraphics.h" #include "SkRegion.h" #include "SkRegion.h" #include "SkVertices.h" #include "SkVertices.h" Loading Loading @@ -582,8 +582,9 @@ static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstri env->ReleaseStringChars(text, jchars); env->ReleaseStringChars(text, jchars); } } static void setDrawFilter(jlong canvasHandle, jlong filterHandle) { static void setPaintFilter(jlong canvasHandle, jlong filterHandle) { get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle)); PaintFilter* paintFilter = reinterpret_cast<PaintFilter*>(filterHandle); get_canvas(canvasHandle)->setPaintFilter(sk_ref_sp(paintFilter)); } } static void freeCaches(JNIEnv* env, jobject) { static void freeCaches(JNIEnv* env, jobject) { Loading Loading @@ -633,7 +634,7 @@ static const JNINativeMethod gMethods[] = { {"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect}, {"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect}, {"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect}, {"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect}, {"nClipPath","(JJI)Z", (void*) CanvasJNI::clipPath}, {"nClipPath","(JJI)Z", (void*) CanvasJNI::clipPath}, {"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter}, {"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setPaintFilter}, }; }; // If called from Canvas these are regular JNI // If called from Canvas these are regular JNI Loading
libs/hwui/SkiaCanvas.cpp +58 −53 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include "VectorDrawable.h" #include "VectorDrawable.h" #include "hwui/Bitmap.h" #include "hwui/Bitmap.h" #include "hwui/MinikinUtils.h" #include "hwui/MinikinUtils.h" #include "hwui/PaintFilter.h" #include "pipeline/skia/AnimatedDrawables.h" #include "pipeline/skia/AnimatedDrawables.h" #include <SkAnimatedImage.h> #include <SkAnimatedImage.h> Loading @@ -28,7 +29,6 @@ #include <SkColorFilter.h> #include <SkColorFilter.h> #include <SkColorSpaceXformCanvas.h> #include <SkColorSpaceXformCanvas.h> #include <SkDeque.h> #include <SkDeque.h> #include <SkDrawFilter.h> #include <SkDrawable.h> #include <SkDrawable.h> #include <SkGraphics.h> #include <SkGraphics.h> #include <SkImage.h> #include <SkImage.h> Loading @@ -40,6 +40,8 @@ #include <SkTextBlob.h> #include <SkTextBlob.h> #include <memory> #include <memory> #include <optional> #include <utility> namespace android { namespace android { Loading Loading @@ -211,7 +213,7 @@ public: Clip(const SkRRect& rrect, SkClipOp op, const SkMatrix& m) Clip(const SkRRect& rrect, SkClipOp op, const SkMatrix& m) : mType(Type::RRect), mOp(op), mMatrix(m), mRRect(rrect) {} : mType(Type::RRect), mOp(op), mMatrix(m), mRRect(rrect) {} Clip(const SkPath& path, SkClipOp op, const SkMatrix& m) Clip(const SkPath& path, SkClipOp op, const SkMatrix& m) : mType(Type::Path), mOp(op), mMatrix(m), mPath(&path) {} : mType(Type::Path), mOp(op), mMatrix(m), mPath(std::in_place, path) {} void apply(SkCanvas* canvas) const { void apply(SkCanvas* canvas) const { canvas->setMatrix(mMatrix); canvas->setMatrix(mMatrix); Loading @@ -223,7 +225,7 @@ public: canvas->clipRRect(mRRect, mOp); canvas->clipRRect(mRRect, mOp); break; break; case Type::Path: case Type::Path: canvas->clipPath(*mPath.get(), mOp); canvas->clipPath(mPath.value(), mOp); break; break; } } } } Loading @@ -240,7 +242,7 @@ private: SkMatrix mMatrix; SkMatrix mMatrix; // These are logically a union (tracked separately due to non-POD path). // These are logically a union (tracked separately due to non-POD path). SkTLazy<SkPath> mPath; std::optional<SkPath> mPath; SkRRect mRRect; SkRRect mRRect; }; }; Loading Loading @@ -400,12 +402,12 @@ bool SkiaCanvas::clipPath(const SkPath* path, SkClipOp op) { // Canvas state operations: Filters // Canvas state operations: Filters // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- SkDrawFilter* SkiaCanvas::getDrawFilter() { PaintFilter* SkiaCanvas::getPaintFilter() { return mCanvas->getDrawFilter(); return mPaintFilter.get(); } } void SkiaCanvas::setDrawFilter(SkDrawFilter* drawFilter) { void SkiaCanvas::setPaintFilter(sk_sp<PaintFilter> paintFilter) { mCanvas->setDrawFilter(drawFilter); mPaintFilter = std::move(paintFilter); } } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- Loading Loading @@ -439,8 +441,15 @@ void SkiaCanvas::drawColor(int color, SkBlendMode mode) { mCanvas->drawColor(color, mode); mCanvas->drawColor(color, mode); } } SkiaCanvas::PaintCoW&& SkiaCanvas::filterPaint(PaintCoW&& paint) const { if (mPaintFilter) { mPaintFilter->filter(&paint.writeable()); } return std::move(paint); } void SkiaCanvas::drawPaint(const SkPaint& paint) { void SkiaCanvas::drawPaint(const SkPaint& paint) { mCanvas->drawPaint(paint); mCanvas->drawPaint(*filterPaint(paint)); } } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- Loading @@ -457,53 +466,53 @@ void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint pts[i].set(points[0], points[1]); pts[i].set(points[0], points[1]); points += 2; points += 2; } } mCanvas->drawPoints(mode, count, pts.get(), paint); mCanvas->drawPoints(mode, count, pts.get(), *filterPaint(paint)); } } void SkiaCanvas::drawPoint(float x, float y, const SkPaint& paint) { void SkiaCanvas::drawPoint(float x, float y, const SkPaint& paint) { mCanvas->drawPoint(x, y, paint); mCanvas->drawPoint(x, y, *filterPaint(paint)); } } void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint) { void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint) { this->drawPoints(points, count, paint, SkCanvas::kPoints_PointMode); this->drawPoints(points, count, *filterPaint(paint), SkCanvas::kPoints_PointMode); } } void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY, void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY, const SkPaint& paint) { const SkPaint& paint) { mCanvas->drawLine(startX, startY, stopX, stopY, paint); mCanvas->drawLine(startX, startY, stopX, stopY, *filterPaint(paint)); } } void SkiaCanvas::drawLines(const float* points, int count, const SkPaint& paint) { void SkiaCanvas::drawLines(const float* points, int count, const SkPaint& paint) { if (CC_UNLIKELY(count < 4 || paint.nothingToDraw())) return; if (CC_UNLIKELY(count < 4 || paint.nothingToDraw())) return; this->drawPoints(points, count, paint, SkCanvas::kLines_PointMode); this->drawPoints(points, count, *filterPaint(paint), SkCanvas::kLines_PointMode); } } void SkiaCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) { void SkiaCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; if (CC_UNLIKELY(paint.nothingToDraw())) return; mCanvas->drawRect({left, top, right, bottom}, paint); mCanvas->drawRect({left, top, right, bottom}, *filterPaint(paint)); } } void SkiaCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) { void SkiaCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; if (CC_UNLIKELY(paint.nothingToDraw())) return; mCanvas->drawRegion(region, paint); mCanvas->drawRegion(region, *filterPaint(paint)); } } void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, const SkPaint& paint) { const SkPaint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; if (CC_UNLIKELY(paint.nothingToDraw())) return; SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); mCanvas->drawRoundRect(rect, rx, ry, paint); mCanvas->drawRoundRect(rect, rx, ry, *filterPaint(paint)); } } void SkiaCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) { void SkiaCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) { if (CC_UNLIKELY(radius <= 0 || paint.nothingToDraw())) return; if (CC_UNLIKELY(radius <= 0 || paint.nothingToDraw())) return; mCanvas->drawCircle(x, y, radius, paint); mCanvas->drawCircle(x, y, radius, *filterPaint(paint)); } } void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) { void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) { if (CC_UNLIKELY(paint.nothingToDraw())) return; if (CC_UNLIKELY(paint.nothingToDraw())) return; SkRect oval = SkRect::MakeLTRB(left, top, right, bottom); SkRect oval = SkRect::MakeLTRB(left, top, right, bottom); mCanvas->drawOval(oval, paint); mCanvas->drawOval(oval, *filterPaint(paint)); } } void SkiaCanvas::drawArc(float left, float top, float right, float bottom, float startAngle, void SkiaCanvas::drawArc(float left, float top, float right, float bottom, float startAngle, Loading @@ -511,9 +520,9 @@ void SkiaCanvas::drawArc(float left, float top, float right, float bottom, float if (CC_UNLIKELY(paint.nothingToDraw())) return; if (CC_UNLIKELY(paint.nothingToDraw())) return; SkRect arc = SkRect::MakeLTRB(left, top, right, bottom); SkRect arc = SkRect::MakeLTRB(left, top, right, bottom); if (fabs(sweepAngle) >= 360.0f) { if (fabs(sweepAngle) >= 360.0f) { mCanvas->drawOval(arc, paint); mCanvas->drawOval(arc, *filterPaint(paint)); } else { } else { mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, paint); mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, *filterPaint(paint)); } } } } Loading @@ -522,19 +531,19 @@ void SkiaCanvas::drawPath(const SkPath& path, const SkPaint& paint) { if (CC_UNLIKELY(path.isEmpty() && (!path.isInverseFillType()))) { if (CC_UNLIKELY(path.isEmpty() && (!path.isInverseFillType()))) { return; return; } } mCanvas->drawPath(path, paint); mCanvas->drawPath(path, *filterPaint(paint)); } } void SkiaCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) { void SkiaCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) { mCanvas->drawVertices(vertices, mode, paint); mCanvas->drawVertices(vertices, mode, *filterPaint(paint)); } } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // Canvas draw operations: Bitmaps // Canvas draw operations: Bitmaps // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- const SkPaint* SkiaCanvas::addFilter(const SkPaint* origPaint, SkPaint* tmpPaint, SkiaCanvas::PaintCoW&& SkiaCanvas::filterBitmap(PaintCoW&& paint, sk_sp<SkColorFilter> colorSpaceFilter) { sk_sp<SkColorFilter> colorSpaceFilter) const { /* We don't apply the colorSpace filter if this canvas is already wrapped with /* We don't apply the colorSpace filter if this canvas is already wrapped with * a SkColorSpaceXformCanvas since it already takes care of converting the * a SkColorSpaceXformCanvas since it already takes care of converting the * contents of the bitmap into the appropriate colorspace. The mCanvasWrapper * contents of the bitmap into the appropriate colorspace. The mCanvasWrapper Loading @@ -542,39 +551,31 @@ const SkPaint* SkiaCanvas::addFilter(const SkPaint* origPaint, SkPaint* tmpPaint * to have a non-sRGB colorspace. * to have a non-sRGB colorspace. */ */ if (!mCanvasWrapper && colorSpaceFilter) { if (!mCanvasWrapper && colorSpaceFilter) { if (origPaint) { SkPaint& tmpPaint = paint.writeable(); *tmpPaint = *origPaint; if (tmpPaint.getColorFilter()) { } tmpPaint.setColorFilter(SkColorFilter::MakeComposeFilter(tmpPaint.refColorFilter(), std::move(colorSpaceFilter))); if (tmpPaint->getColorFilter()) { LOG_ALWAYS_FATAL_IF(!tmpPaint.getColorFilter()); tmpPaint->setColorFilter( SkColorFilter::MakeComposeFilter(tmpPaint->refColorFilter(), colorSpaceFilter)); LOG_ALWAYS_FATAL_IF(!tmpPaint->getColorFilter()); } else { } else { tmpPaint->setColorFilter(colorSpaceFilter); tmpPaint.setColorFilter(std::move(colorSpaceFilter)); } } return tmpPaint; } else { return origPaint; } } return filterPaint(std::move(paint)); } } void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) { void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) { SkPaint tmpPaint; sk_sp<SkColorFilter> colorFilter; sk_sp<SkColorFilter> colorFilter; sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); mCanvas->drawImage(image, left, top, addFilter(paint, &tmpPaint, colorFilter)); mCanvas->drawImage(image, left, top, filterBitmap(paint, std::move(colorFilter))); } } void SkiaCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) { void SkiaCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) { SkAutoCanvasRestore acr(mCanvas, true); SkAutoCanvasRestore acr(mCanvas, true); mCanvas->concat(matrix); mCanvas->concat(matrix); SkPaint tmpPaint; sk_sp<SkColorFilter> colorFilter; sk_sp<SkColorFilter> colorFilter; sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); mCanvas->drawImage(image, 0, 0, addFilter(paint, &tmpPaint, colorFilter)); mCanvas->drawImage(image, 0, 0, filterBitmap(paint, std::move(colorFilter))); } } void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight, void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight, Loading @@ -583,10 +584,9 @@ void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float s SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom); SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom); SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); SkPaint tmpPaint; sk_sp<SkColorFilter> colorFilter; sk_sp<SkColorFilter> colorFilter; sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); mCanvas->drawImageRect(image, srcRect, dstRect, addFilter(paint, &tmpPaint, colorFilter), mCanvas->drawImageRect(image, srcRect, dstRect, filterBitmap(paint, std::move(colorFilter)), SkCanvas::kFast_SrcRectConstraint); SkCanvas::kFast_SrcRectConstraint); } } Loading Loading @@ -665,21 +665,20 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight, #endif #endif // cons-up a shader for the bitmap // cons-up a shader for the bitmap SkPaint tmpPaint; PaintCoW paintCoW(paint); if (paint) { SkPaint& tmpPaint = paintCoW.writeable(); tmpPaint = *paint; } sk_sp<SkColorFilter> colorFilter; sk_sp<SkColorFilter> colorFilter; sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); sk_sp<SkShader> shader = sk_sp<SkShader> shader = image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); if (colorFilter) { if (colorFilter) { shader = shader->makeWithColorFilter(colorFilter); shader = shader->makeWithColorFilter(std::move(colorFilter)); } } tmpPaint.setShader(shader); tmpPaint.setShader(std::move(shader)); mCanvas->drawVertices(builder.detach(), SkBlendMode::kModulate, tmpPaint); mCanvas->drawVertices(builder.detach(), SkBlendMode::kModulate, *filterPaint(std::move(paintCoW))); } } void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, float dstLeft, void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, float dstLeft, Loading @@ -706,10 +705,10 @@ void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, floa lattice.fBounds = nullptr; lattice.fBounds = nullptr; SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); SkPaint tmpPaint; sk_sp<SkColorFilter> colorFilter; sk_sp<SkColorFilter> colorFilter; sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); sk_sp<SkImage> image = bitmap.makeImage(&colorFilter); mCanvas->drawImageLattice(image.get(), lattice, dst, addFilter(paint, &tmpPaint, colorFilter)); mCanvas->drawImageLattice(image.get(), lattice, dst, filterBitmap(paint, std::move(colorFilter))); } } double SkiaCanvas::drawAnimatedImage(AnimatedImageDrawable* imgDrawable) { double SkiaCanvas::drawAnimatedImage(AnimatedImageDrawable* imgDrawable) { Loading @@ -732,6 +731,9 @@ void SkiaCanvas::drawGlyphs(ReadGlyphFunc glyphFunc, int count, const SkPaint& p // glyphs centered or right-aligned; the offset above takes // glyphs centered or right-aligned; the offset above takes // care of all alignment. // care of all alignment. SkPaint paintCopy(paint); SkPaint paintCopy(paint); if (mPaintFilter) { mPaintFilter->filter(&paintCopy); } paintCopy.setTextAlign(SkPaint::kLeft_Align); paintCopy.setTextAlign(SkPaint::kLeft_Align); SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding); SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding); // Stroke with a hairline is drawn on HW with a fill style for compatibility with Android O and // Stroke with a hairline is drawn on HW with a fill style for compatibility with Android O and Loading Loading @@ -760,6 +762,9 @@ void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, // glyphs centered or right-aligned; the offsets take care of // glyphs centered or right-aligned; the offsets take care of // that portion of the alignment. // that portion of the alignment. SkPaint paintCopy(paint); SkPaint paintCopy(paint); if (mPaintFilter) { mPaintFilter->filter(&paintCopy); } paintCopy.setTextAlign(SkPaint::kLeft_Align); paintCopy.setTextAlign(SkPaint::kLeft_Align); SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding); SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding); Loading
libs/hwui/SkiaCanvas.h +55 −5 Original line number Original line Diff line number Diff line Loading @@ -22,7 +22,9 @@ #include "hwui/Canvas.h" #include "hwui/Canvas.h" #include <SkCanvas.h> #include <SkCanvas.h> #include <SkTLazy.h> #include <cassert> #include <optional> namespace android { namespace android { Loading Loading @@ -87,8 +89,8 @@ public: virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) override; virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) override; virtual bool clipPath(const SkPath* path, SkClipOp op) override; virtual bool clipPath(const SkPath* path, SkClipOp op) override; virtual SkDrawFilter* getDrawFilter() override; virtual PaintFilter* getPaintFilter() override; virtual void setDrawFilter(SkDrawFilter* drawFilter) override; virtual void setPaintFilter(sk_sp<PaintFilter> paintFilter) override; virtual SkCanvasState* captureCanvasState() const override; virtual SkCanvasState* captureCanvasState() const override; Loading Loading @@ -158,6 +160,46 @@ protected: const SkPaint& paint, const SkPath& path, size_t start, const SkPaint& paint, const SkPath& path, size_t start, size_t end) override; size_t end) override; /** This class acts as a copy on write SkPaint. * * Initially this will be the SkPaint passed to the contructor. * The first time writable() is called this will become a copy of the * initial SkPaint (or a default SkPaint if nullptr). */ struct PaintCoW { PaintCoW(const SkPaint& that) : mPtr(&that) {} PaintCoW(const SkPaint* ptr) : mPtr(ptr) {} PaintCoW(const PaintCoW&) = delete; PaintCoW(PaintCoW&&) = delete; PaintCoW& operator=(const PaintCoW&) = delete; PaintCoW& operator=(PaintCoW&&) = delete; SkPaint& writeable() { if (!mStorage) { if (!mPtr) { mStorage.emplace(); } else { mStorage.emplace(*mPtr); } mPtr = &*mStorage; } return *mStorage; } operator const SkPaint*() const { return mPtr; } const SkPaint* operator->() const { assert(mPtr); return mPtr; } const SkPaint& operator*() const { assert(mPtr); return *mPtr; } explicit operator bool() { return mPtr != nullptr; } private: const SkPaint* mPtr; std::optional<SkPaint> mStorage; }; /** Filters the paint using the current paint filter. * * @param paint the paint to filter. Will be initialized with the default * SkPaint before filtering if filtering is required. */ PaintCoW&& filterPaint(PaintCoW&& paint) const; private: private: struct SaveRec { struct SaveRec { int saveCount; int saveCount; Loading @@ -174,8 +216,15 @@ private: void drawPoints(const float* points, int count, const SkPaint& paint, SkCanvas::PointMode mode); void drawPoints(const float* points, int count, const SkPaint& paint, SkCanvas::PointMode mode); const SkPaint* addFilter(const SkPaint* origPaint, SkPaint* tmpPaint, /** Filters the paint for bitmap drawing. sk_sp<SkColorFilter> colorSpaceFilter); * * After filtering the paint for bitmap drawing, * also calls filterPaint on the paint. * * @param paint the paint to filter. Will be initialized with the default * SkPaint before filtering if filtering is required. */ PaintCoW&& filterBitmap(PaintCoW&& paint, sk_sp<SkColorFilter> colorSpaceFilter) const; class Clip; class Clip; Loading @@ -185,6 +234,7 @@ private: // unless it is the same as mCanvasOwned.get() // unless it is the same as mCanvasOwned.get() std::unique_ptr<SkDeque> mSaveStack; // lazily allocated, tracks partial saves. std::unique_ptr<SkDeque> mSaveStack; // lazily allocated, tracks partial saves. std::vector<Clip> mClipStack; // tracks persistent clips. std::vector<Clip> mClipStack; // tracks persistent clips. sk_sp<PaintFilter> mPaintFilter; }; }; } // namespace android } // namespace android