Merge "Replace SkDrawFilter with PaintFilter."
This commit is contained in:
@@ -126,7 +126,6 @@ cc_library_shared {
|
||||
"android/graphics/Camera.cpp",
|
||||
"android/graphics/CanvasProperty.cpp",
|
||||
"android/graphics/ColorFilter.cpp",
|
||||
"android/graphics/DrawFilter.cpp",
|
||||
"android/graphics/FontFamily.cpp",
|
||||
"android/graphics/FontUtils.cpp",
|
||||
"android/graphics/CreateJavaOutputStreamAdaptor.cpp",
|
||||
@@ -143,6 +142,7 @@ cc_library_shared {
|
||||
"android/graphics/NinePatch.cpp",
|
||||
"android/graphics/NinePatchPeeker.cpp",
|
||||
"android/graphics/Paint.cpp",
|
||||
"android/graphics/PaintFilter.cpp",
|
||||
"android/graphics/Path.cpp",
|
||||
"android/graphics/PathMeasure.cpp",
|
||||
"android/graphics/PathEffect.cpp",
|
||||
|
||||
@@ -15,36 +15,43 @@
|
||||
** 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 "GraphicsJNI.h"
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
|
||||
#include "core_jni_helpers.h"
|
||||
|
||||
#include "SkDrawFilter.h"
|
||||
#include "SkPaintFlagsDrawFilter.h"
|
||||
#include "hwui/PaintFilter.h"
|
||||
#include "SkPaint.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
// Custom version of SkPaintFlagsDrawFilter that also calls setFilterQuality.
|
||||
class CompatFlagsDrawFilter : public SkPaintFlagsDrawFilter {
|
||||
class PaintFlagsFilter : public PaintFilter {
|
||||
public:
|
||||
CompatFlagsDrawFilter(uint32_t clearFlags, uint32_t setFlags,
|
||||
SkFilterQuality desiredQuality)
|
||||
: SkPaintFlagsDrawFilter(clearFlags, setFlags)
|
||||
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:
|
||||
CompatPaintFlagsFilter(uint32_t clearFlags, uint32_t setFlags, SkFilterQuality desiredQuality)
|
||||
: PaintFlagsFilter(clearFlags, setFlags)
|
||||
, fDesiredQuality(desiredQuality) {
|
||||
}
|
||||
|
||||
virtual bool filter(SkPaint* paint, Type type) {
|
||||
SkPaintFlagsDrawFilter::filter(paint, type);
|
||||
virtual void filter(SkPaint* paint) {
|
||||
PaintFlagsFilter::filter(paint);
|
||||
paint->setFilterQuality(fDesiredQuality);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -61,16 +68,16 @@ static inline bool hadFiltering(jint& flags) {
|
||||
return result;
|
||||
}
|
||||
|
||||
class SkDrawFilterGlue {
|
||||
class PaintFilterGlue {
|
||||
public:
|
||||
|
||||
static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) {
|
||||
SkDrawFilter* obj = reinterpret_cast<SkDrawFilter*>(objHandle);
|
||||
PaintFilter* obj = reinterpret_cast<PaintFilter*>(objHandle);
|
||||
SkSafeUnref(obj);
|
||||
}
|
||||
|
||||
static jlong CreatePaintFlagsDF(JNIEnv* env, jobject clazz,
|
||||
jint clearFlags, jint setFlags) {
|
||||
static jlong CreatePaintFlagsFilter(JNIEnv* env, jobject clazz,
|
||||
jint clearFlags, jint setFlags) {
|
||||
if (clearFlags | setFlags) {
|
||||
// Mask both groups of flags to remove FILTER_BITMAP_FLAG, which no
|
||||
// longer has a Skia equivalent flag (instead it corresponds to
|
||||
@@ -79,16 +86,16 @@ public:
|
||||
const bool turnFilteringOn = hadFiltering(setFlags);
|
||||
const bool turnFilteringOff = hadFiltering(clearFlags);
|
||||
|
||||
SkDrawFilter* filter;
|
||||
PaintFilter* filter;
|
||||
if (turnFilteringOn) {
|
||||
// Turning filtering on overrides turning it off.
|
||||
filter = new CompatFlagsDrawFilter(clearFlags, setFlags,
|
||||
filter = new CompatPaintFlagsFilter(clearFlags, setFlags,
|
||||
kLow_SkFilterQuality);
|
||||
} else if (turnFilteringOff) {
|
||||
filter = new CompatFlagsDrawFilter(clearFlags, setFlags,
|
||||
filter = new CompatPaintFlagsFilter(clearFlags, setFlags,
|
||||
kNone_SkFilterQuality);
|
||||
} else {
|
||||
filter = new SkPaintFlagsDrawFilter(clearFlags, setFlags);
|
||||
filter = new PaintFlagsFilter(clearFlags, setFlags);
|
||||
}
|
||||
return reinterpret_cast<jlong>(filter);
|
||||
} else {
|
||||
@@ -98,11 +105,11 @@ public:
|
||||
};
|
||||
|
||||
static const JNINativeMethod drawfilter_methods[] = {
|
||||
{"nativeDestructor", "(J)V", (void*) SkDrawFilterGlue::finalizer}
|
||||
{"nativeDestructor", "(J)V", (void*) PaintFilterGlue::finalizer}
|
||||
};
|
||||
|
||||
static const JNINativeMethod paintflags_methods[] = {
|
||||
{"nativeConstructor","(II)J", (void*) SkDrawFilterGlue::CreatePaintFlagsDF}
|
||||
{"nativeConstructor","(II)J", (void*) PaintFilterGlue::CreatePaintFlagsFilter}
|
||||
};
|
||||
|
||||
int register_android_graphics_DrawFilter(JNIEnv* env) {
|
||||
@@ -110,7 +117,7 @@ int register_android_graphics_DrawFilter(JNIEnv* env) {
|
||||
NELEM(drawfilter_methods));
|
||||
result |= RegisterMethodsOrDie(env, "android/graphics/PaintFlagsDrawFilter", paintflags_methods,
|
||||
NELEM(paintflags_methods));
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
#include <androidfw/ResourceTypes.h>
|
||||
#include <hwui/Canvas.h>
|
||||
#include <hwui/Paint.h>
|
||||
#include <hwui/PaintFilter.h>
|
||||
#include <hwui/Typeface.h>
|
||||
#include <minikin/Layout.h>
|
||||
#include <nativehelper/ScopedPrimitiveArray.h>
|
||||
#include <nativehelper/ScopedStringChars.h>
|
||||
|
||||
#include "Bitmap.h"
|
||||
#include "SkDrawFilter.h"
|
||||
#include "SkGraphics.h"
|
||||
#include "SkRegion.h"
|
||||
#include "SkVertices.h"
|
||||
@@ -582,8 +582,9 @@ static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstri
|
||||
env->ReleaseStringChars(text, jchars);
|
||||
}
|
||||
|
||||
static void setDrawFilter(jlong canvasHandle, jlong filterHandle) {
|
||||
get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
|
||||
static void setPaintFilter(jlong canvasHandle, jlong filterHandle) {
|
||||
PaintFilter* paintFilter = reinterpret_cast<PaintFilter*>(filterHandle);
|
||||
get_canvas(canvasHandle)->setPaintFilter(sk_ref_sp(paintFilter));
|
||||
}
|
||||
|
||||
static void freeCaches(JNIEnv* env, jobject) {
|
||||
@@ -633,7 +634,7 @@ static const JNINativeMethod gMethods[] = {
|
||||
{"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
|
||||
{"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
|
||||
{"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
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "VectorDrawable.h"
|
||||
#include "hwui/Bitmap.h"
|
||||
#include "hwui/MinikinUtils.h"
|
||||
#include "hwui/PaintFilter.h"
|
||||
#include "pipeline/skia/AnimatedDrawables.h"
|
||||
|
||||
#include <SkAnimatedImage.h>
|
||||
@@ -28,7 +29,6 @@
|
||||
#include <SkColorFilter.h>
|
||||
#include <SkColorSpaceXformCanvas.h>
|
||||
#include <SkDeque.h>
|
||||
#include <SkDrawFilter.h>
|
||||
#include <SkDrawable.h>
|
||||
#include <SkGraphics.h>
|
||||
#include <SkImage.h>
|
||||
@@ -40,6 +40,8 @@
|
||||
#include <SkTextBlob.h>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
namespace android {
|
||||
|
||||
@@ -211,7 +213,7 @@ public:
|
||||
Clip(const SkRRect& rrect, SkClipOp op, const SkMatrix& m)
|
||||
: mType(Type::RRect), mOp(op), mMatrix(m), mRRect(rrect) {}
|
||||
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 {
|
||||
canvas->setMatrix(mMatrix);
|
||||
@@ -223,7 +225,7 @@ public:
|
||||
canvas->clipRRect(mRRect, mOp);
|
||||
break;
|
||||
case Type::Path:
|
||||
canvas->clipPath(*mPath.get(), mOp);
|
||||
canvas->clipPath(mPath.value(), mOp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -240,7 +242,7 @@ private:
|
||||
SkMatrix mMatrix;
|
||||
|
||||
// These are logically a union (tracked separately due to non-POD path).
|
||||
SkTLazy<SkPath> mPath;
|
||||
std::optional<SkPath> mPath;
|
||||
SkRRect mRRect;
|
||||
};
|
||||
|
||||
@@ -400,12 +402,12 @@ bool SkiaCanvas::clipPath(const SkPath* path, SkClipOp op) {
|
||||
// Canvas state operations: Filters
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
SkDrawFilter* SkiaCanvas::getDrawFilter() {
|
||||
return mCanvas->getDrawFilter();
|
||||
PaintFilter* SkiaCanvas::getPaintFilter() {
|
||||
return mPaintFilter.get();
|
||||
}
|
||||
|
||||
void SkiaCanvas::setDrawFilter(SkDrawFilter* drawFilter) {
|
||||
mCanvas->setDrawFilter(drawFilter);
|
||||
void SkiaCanvas::setPaintFilter(sk_sp<PaintFilter> paintFilter) {
|
||||
mPaintFilter = std::move(paintFilter);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -439,8 +441,15 @@ void SkiaCanvas::drawColor(int color, SkBlendMode 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) {
|
||||
mCanvas->drawPaint(paint);
|
||||
mCanvas->drawPaint(*filterPaint(paint));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -457,53 +466,53 @@ void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint
|
||||
pts[i].set(points[0], points[1]);
|
||||
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) {
|
||||
mCanvas->drawPoint(x, y, paint);
|
||||
mCanvas->drawPoint(x, y, *filterPaint(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,
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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,
|
||||
const SkPaint& paint) {
|
||||
if (CC_UNLIKELY(paint.nothingToDraw())) return;
|
||||
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) {
|
||||
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) {
|
||||
if (CC_UNLIKELY(paint.nothingToDraw())) return;
|
||||
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,
|
||||
@@ -511,9 +520,9 @@ void SkiaCanvas::drawArc(float left, float top, float right, float bottom, float
|
||||
if (CC_UNLIKELY(paint.nothingToDraw())) return;
|
||||
SkRect arc = SkRect::MakeLTRB(left, top, right, bottom);
|
||||
if (fabs(sweepAngle) >= 360.0f) {
|
||||
mCanvas->drawOval(arc, paint);
|
||||
mCanvas->drawOval(arc, *filterPaint(paint));
|
||||
} else {
|
||||
mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, paint);
|
||||
mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, *filterPaint(paint));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -522,19 +531,19 @@ void SkiaCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
|
||||
if (CC_UNLIKELY(path.isEmpty() && (!path.isInverseFillType()))) {
|
||||
return;
|
||||
}
|
||||
mCanvas->drawPath(path, paint);
|
||||
mCanvas->drawPath(path, *filterPaint(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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const SkPaint* SkiaCanvas::addFilter(const SkPaint* origPaint, SkPaint* tmpPaint,
|
||||
sk_sp<SkColorFilter> colorSpaceFilter) {
|
||||
SkiaCanvas::PaintCoW&& SkiaCanvas::filterBitmap(PaintCoW&& paint,
|
||||
sk_sp<SkColorFilter> colorSpaceFilter) const {
|
||||
/* We don't apply the colorSpace filter if this canvas is already wrapped with
|
||||
* a SkColorSpaceXformCanvas since it already takes care of converting the
|
||||
* contents of the bitmap into the appropriate colorspace. The mCanvasWrapper
|
||||
@@ -542,39 +551,31 @@ const SkPaint* SkiaCanvas::addFilter(const SkPaint* origPaint, SkPaint* tmpPaint
|
||||
* to have a non-sRGB colorspace.
|
||||
*/
|
||||
if (!mCanvasWrapper && colorSpaceFilter) {
|
||||
if (origPaint) {
|
||||
*tmpPaint = *origPaint;
|
||||
}
|
||||
|
||||
if (tmpPaint->getColorFilter()) {
|
||||
tmpPaint->setColorFilter(
|
||||
SkColorFilter::MakeComposeFilter(tmpPaint->refColorFilter(), colorSpaceFilter));
|
||||
LOG_ALWAYS_FATAL_IF(!tmpPaint->getColorFilter());
|
||||
SkPaint& tmpPaint = paint.writeable();
|
||||
if (tmpPaint.getColorFilter()) {
|
||||
tmpPaint.setColorFilter(SkColorFilter::MakeComposeFilter(tmpPaint.refColorFilter(),
|
||||
std::move(colorSpaceFilter)));
|
||||
LOG_ALWAYS_FATAL_IF(!tmpPaint.getColorFilter());
|
||||
} 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) {
|
||||
SkPaint tmpPaint;
|
||||
sk_sp<SkColorFilter> 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) {
|
||||
SkAutoCanvasRestore acr(mCanvas, true);
|
||||
mCanvas->concat(matrix);
|
||||
|
||||
SkPaint tmpPaint;
|
||||
sk_sp<SkColorFilter> 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,
|
||||
@@ -583,10 +584,9 @@ void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float s
|
||||
SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
|
||||
SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
|
||||
|
||||
SkPaint tmpPaint;
|
||||
sk_sp<SkColorFilter> 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);
|
||||
}
|
||||
|
||||
@@ -665,21 +665,20 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight,
|
||||
#endif
|
||||
|
||||
// cons-up a shader for the bitmap
|
||||
SkPaint tmpPaint;
|
||||
if (paint) {
|
||||
tmpPaint = *paint;
|
||||
}
|
||||
PaintCoW paintCoW(paint);
|
||||
SkPaint& tmpPaint = paintCoW.writeable();
|
||||
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
|
||||
sk_sp<SkShader> shader =
|
||||
image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
|
||||
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,
|
||||
@@ -706,10 +705,10 @@ void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, floa
|
||||
lattice.fBounds = nullptr;
|
||||
SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
|
||||
|
||||
SkPaint tmpPaint;
|
||||
sk_sp<SkColorFilter> 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) {
|
||||
@@ -732,6 +731,9 @@ void SkiaCanvas::drawGlyphs(ReadGlyphFunc glyphFunc, int count, const SkPaint& p
|
||||
// glyphs centered or right-aligned; the offset above takes
|
||||
// care of all alignment.
|
||||
SkPaint paintCopy(paint);
|
||||
if (mPaintFilter) {
|
||||
mPaintFilter->filter(&paintCopy);
|
||||
}
|
||||
paintCopy.setTextAlign(SkPaint::kLeft_Align);
|
||||
SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
|
||||
// Stroke with a hairline is drawn on HW with a fill style for compatibility with Android O and
|
||||
@@ -760,6 +762,9 @@ void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset,
|
||||
// glyphs centered or right-aligned; the offsets take care of
|
||||
// that portion of the alignment.
|
||||
SkPaint paintCopy(paint);
|
||||
if (mPaintFilter) {
|
||||
mPaintFilter->filter(&paintCopy);
|
||||
}
|
||||
paintCopy.setTextAlign(SkPaint::kLeft_Align);
|
||||
SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
|
||||
|
||||
|
||||
@@ -22,7 +22,9 @@
|
||||
#include "hwui/Canvas.h"
|
||||
|
||||
#include <SkCanvas.h>
|
||||
#include <SkTLazy.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <optional>
|
||||
|
||||
namespace android {
|
||||
|
||||
@@ -87,8 +89,8 @@ public:
|
||||
virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) override;
|
||||
virtual bool clipPath(const SkPath* path, SkClipOp op) override;
|
||||
|
||||
virtual SkDrawFilter* getDrawFilter() override;
|
||||
virtual void setDrawFilter(SkDrawFilter* drawFilter) override;
|
||||
virtual PaintFilter* getPaintFilter() override;
|
||||
virtual void setPaintFilter(sk_sp<PaintFilter> paintFilter) override;
|
||||
|
||||
virtual SkCanvasState* captureCanvasState() const override;
|
||||
|
||||
@@ -158,6 +160,46 @@ protected:
|
||||
const SkPaint& paint, const SkPath& path, size_t start,
|
||||
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:
|
||||
struct SaveRec {
|
||||
int saveCount;
|
||||
@@ -174,8 +216,15 @@ private:
|
||||
|
||||
void drawPoints(const float* points, int count, const SkPaint& paint, SkCanvas::PointMode mode);
|
||||
|
||||
const SkPaint* addFilter(const SkPaint* origPaint, SkPaint* tmpPaint,
|
||||
sk_sp<SkColorFilter> colorSpaceFilter);
|
||||
/** Filters the paint for bitmap drawing.
|
||||
*
|
||||
* 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;
|
||||
|
||||
@@ -185,6 +234,7 @@ private:
|
||||
// unless it is the same as mCanvasOwned.get()
|
||||
std::unique_ptr<SkDeque> mSaveStack; // lazily allocated, tracks partial saves.
|
||||
std::vector<Clip> mClipStack; // tracks persistent clips.
|
||||
sk_sp<PaintFilter> mPaintFilter;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "Typeface.h"
|
||||
#include "pipeline/skia/SkiaRecordingCanvas.h"
|
||||
|
||||
#include <SkDrawFilter.h>
|
||||
#include "hwui/PaintFilter.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
@@ -40,10 +40,10 @@ static inline void drawStroke(SkScalar left, SkScalar right, SkScalar top, SkSca
|
||||
|
||||
void Canvas::drawTextDecorations(float x, float y, float length, const SkPaint& paint) {
|
||||
uint32_t flags;
|
||||
SkDrawFilter* drawFilter = getDrawFilter();
|
||||
if (drawFilter) {
|
||||
PaintFilter* paintFilter = getPaintFilter();
|
||||
if (paintFilter) {
|
||||
SkPaint paintCopy(paint);
|
||||
drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
|
||||
paintFilter->filter(&paintCopy);
|
||||
flags = paintCopy.getFlags();
|
||||
} else {
|
||||
flags = paint.getFlags();
|
||||
|
||||
@@ -39,6 +39,7 @@ enum class Bidi : uint8_t;
|
||||
}
|
||||
|
||||
namespace android {
|
||||
class PaintFilter;
|
||||
|
||||
namespace uirenderer {
|
||||
class CanvasPropertyPaint;
|
||||
@@ -213,8 +214,8 @@ public:
|
||||
virtual bool clipPath(const SkPath* path, SkClipOp op) = 0;
|
||||
|
||||
// filters
|
||||
virtual SkDrawFilter* getDrawFilter() = 0;
|
||||
virtual void setDrawFilter(SkDrawFilter* drawFilter) = 0;
|
||||
virtual PaintFilter* getPaintFilter() = 0;
|
||||
virtual void setPaintFilter(sk_sp<PaintFilter> paintFilter) = 0;
|
||||
|
||||
// WebView only
|
||||
virtual SkCanvasState* captureCanvasState() const { return nullptr; }
|
||||
|
||||
19
libs/hwui/hwui/PaintFilter.h
Normal file
19
libs/hwui/hwui/PaintFilter.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef ANDROID_GRAPHICS_PAINT_FILTER_H_
|
||||
#define ANDROID_GRAPHICS_PAINT_FILTER_H_
|
||||
|
||||
class SkPaint;
|
||||
|
||||
namespace android {
|
||||
|
||||
class PaintFilter : public SkRefCnt {
|
||||
public:
|
||||
/**
|
||||
* Called with the paint that will be used to draw.
|
||||
* The implementation may modify the paint as they wish.
|
||||
*/
|
||||
virtual void filter(SkPaint*) = 0;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif
|
||||
@@ -157,12 +157,45 @@ void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
|
||||
// Recording Canvas draw operations: Bitmaps
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
SkiaCanvas::PaintCoW&& SkiaRecordingCanvas::filterBitmap(PaintCoW&& paint,
|
||||
sk_sp<SkColorFilter> colorSpaceFilter) {
|
||||
bool fixBlending = false;
|
||||
bool fixAA = false;
|
||||
if (paint) {
|
||||
// kClear blend mode is drawn as kDstOut on HW for compatibility with Android O and
|
||||
// older.
|
||||
fixBlending = sApiLevel <= 27 && paint->getBlendMode() == SkBlendMode::kClear;
|
||||
fixAA = paint->isAntiAlias();
|
||||
}
|
||||
|
||||
if (fixBlending || fixAA || colorSpaceFilter) {
|
||||
SkPaint& tmpPaint = paint.writeable();
|
||||
|
||||
if (fixBlending) {
|
||||
tmpPaint.setBlendMode(SkBlendMode::kDstOut);
|
||||
}
|
||||
|
||||
if (colorSpaceFilter) {
|
||||
if (tmpPaint.getColorFilter()) {
|
||||
tmpPaint.setColorFilter(SkColorFilter::MakeComposeFilter(
|
||||
tmpPaint.refColorFilter(), std::move(colorSpaceFilter)));
|
||||
} else {
|
||||
tmpPaint.setColorFilter(std::move(colorSpaceFilter));
|
||||
}
|
||||
LOG_ALWAYS_FATAL_IF(!tmpPaint.getColorFilter());
|
||||
}
|
||||
|
||||
// disabling AA on bitmap draws matches legacy HWUI behavior
|
||||
tmpPaint.setAntiAlias(false);
|
||||
}
|
||||
|
||||
return filterPaint(std::move(paint));
|
||||
}
|
||||
|
||||
void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
|
||||
SkPaint tmpPaint;
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
|
||||
mRecorder.drawImage(image, left, top, bitmapPaint(paint, &tmpPaint, colorFilter));
|
||||
mRecorder.drawImage(image, left, top, filterBitmap(paint, std::move(colorFilter)));
|
||||
// if image->unique() is true, then mRecorder.drawImage failed for some reason. It also means
|
||||
// it is not safe to store a raw SkImage pointer, because the image object will be destroyed
|
||||
// when this function ends.
|
||||
@@ -175,10 +208,9 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, con
|
||||
SkAutoCanvasRestore acr(&mRecorder, true);
|
||||
concat(matrix);
|
||||
|
||||
SkPaint tmpPaint;
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
|
||||
mRecorder.drawImage(image, 0, 0, bitmapPaint(paint, &tmpPaint, colorFilter));
|
||||
mRecorder.drawImage(image, 0, 0, filterBitmap(paint, std::move(colorFilter)));
|
||||
if (!bitmap.isImmutable() && image.get() && !image->unique()) {
|
||||
mDisplayList->mMutableImages.push_back(image.get());
|
||||
}
|
||||
@@ -190,10 +222,9 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop
|
||||
SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
|
||||
SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
|
||||
|
||||
SkPaint tmpPaint;
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
|
||||
mRecorder.drawImageRect(image, srcRect, dstRect, bitmapPaint(paint, &tmpPaint, colorFilter),
|
||||
mRecorder.drawImageRect(image, srcRect, dstRect, filterBitmap(paint, std::move(colorFilter)),
|
||||
SkCanvas::kFast_SrcRectConstraint);
|
||||
if (!bitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty() &&
|
||||
!dstRect.isEmpty()) {
|
||||
@@ -225,23 +256,16 @@ void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& ch
|
||||
lattice.fBounds = nullptr;
|
||||
SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
|
||||
|
||||
SkPaint tmpPaint;
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
|
||||
const SkPaint* filteredPaint = bitmapPaint(paint, &tmpPaint, colorFilter);
|
||||
PaintCoW filteredPaint(paint);
|
||||
// Besides kNone, the other three SkFilterQualities are treated the same. And Android's
|
||||
// Java API only supports kLow and kNone anyway.
|
||||
if (!filteredPaint || filteredPaint->getFilterQuality() == kNone_SkFilterQuality) {
|
||||
if (filteredPaint != &tmpPaint) {
|
||||
if (paint) {
|
||||
tmpPaint = *paint;
|
||||
}
|
||||
filteredPaint = &tmpPaint;
|
||||
}
|
||||
tmpPaint.setFilterQuality(kLow_SkFilterQuality);
|
||||
filteredPaint.writeable().setFilterQuality(kLow_SkFilterQuality);
|
||||
}
|
||||
|
||||
mRecorder.drawImageLattice(image.get(), lattice, dst, filteredPaint);
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
|
||||
mRecorder.drawImageLattice(image.get(), lattice, dst,
|
||||
filterBitmap(std::move(filteredPaint), std::move(colorFilter)));
|
||||
if (!bitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) {
|
||||
mDisplayList->mMutableImages.push_back(image.get());
|
||||
}
|
||||
|
||||
@@ -90,44 +90,7 @@ private:
|
||||
*/
|
||||
void initDisplayList(uirenderer::RenderNode* renderNode, int width, int height);
|
||||
|
||||
inline static const SkPaint* bitmapPaint(const SkPaint* origPaint, SkPaint* tmpPaint,
|
||||
sk_sp<SkColorFilter> colorSpaceFilter) {
|
||||
bool fixBlending = false;
|
||||
bool fixAA = false;
|
||||
if (origPaint) {
|
||||
// kClear blend mode is drawn as kDstOut on HW for compatibility with Android O and
|
||||
// older.
|
||||
fixBlending = sApiLevel <= 27 && origPaint->getBlendMode() == SkBlendMode::kClear;
|
||||
fixAA = origPaint->isAntiAlias();
|
||||
}
|
||||
|
||||
if (fixBlending || fixAA || colorSpaceFilter) {
|
||||
if (origPaint) {
|
||||
*tmpPaint = *origPaint;
|
||||
}
|
||||
|
||||
if (fixBlending) {
|
||||
tmpPaint->setBlendMode(SkBlendMode::kDstOut);
|
||||
}
|
||||
|
||||
if (colorSpaceFilter) {
|
||||
if (tmpPaint->getColorFilter()) {
|
||||
tmpPaint->setColorFilter(SkColorFilter::MakeComposeFilter(
|
||||
tmpPaint->refColorFilter(), colorSpaceFilter));
|
||||
} else {
|
||||
tmpPaint->setColorFilter(colorSpaceFilter);
|
||||
}
|
||||
LOG_ALWAYS_FATAL_IF(!tmpPaint->getColorFilter());
|
||||
}
|
||||
|
||||
// disabling AA on bitmap draws matches legacy HWUI behavior
|
||||
tmpPaint->setAntiAlias(false);
|
||||
return tmpPaint;
|
||||
} else {
|
||||
return origPaint;
|
||||
}
|
||||
}
|
||||
|
||||
PaintCoW&& filterBitmap(PaintCoW&& paint, sk_sp<SkColorFilter> colorSpaceFilter);
|
||||
};
|
||||
|
||||
}; // namespace skiapipeline
|
||||
|
||||
Reference in New Issue
Block a user