Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fa3e3404 authored by Derek Sollenberger's avatar Derek Sollenberger
Browse files

Use colorFilters when rendering to an sRGB bitmap.

Bug: 62347704
Test: CtsUiRenderingTestCases, CtsGraphicsTestCases, hwui_unit_tests
Change-Id: I3e237b64cd92217b02d4995bdd695a28d3f393ee
parent 0041c043
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ Canvas* Picture::beginRecording(int width, int height) {
    mWidth = width;
    mHeight = height;
    SkCanvas* canvas = mRecorder->beginRecording(SkIntToScalar(width), SkIntToScalar(height));
    return Canvas::create_canvas(canvas, Canvas::XformToSRGB::kDefer);
    return Canvas::create_canvas(canvas);
}

void Picture::endRecording() {
+2 −6
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@

#include "CreateJavaOutputStreamAdaptor.h"

#include "SkColorSpaceXformCanvas.h"
#include "SkDocument.h"
#include "SkPicture.h"
#include "SkPictureRecorder.h"
@@ -95,10 +94,7 @@ public:

            SkCanvas* canvas = document->beginPage(page->mWidth, page->mHeight,
                    &(page->mContentRect));
            std::unique_ptr<SkCanvas> toSRGBCanvas =
                    SkCreateColorSpaceXformCanvas(canvas, SkColorSpace::MakeSRGB());

            toSRGBCanvas->drawPicture(page->mPicture);
            canvas->drawPicture(page->mPicture);

            document->endPage();
        }
@@ -131,7 +127,7 @@ static jlong nativeStartPage(JNIEnv* env, jobject thiz, jlong documentPtr,
    PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
    SkCanvas* canvas = document->startPage(pageWidth, pageHeight,
            contentLeft, contentTop, contentRight, contentBottom);
    return reinterpret_cast<jlong>(Canvas::create_canvas(canvas, Canvas::XformToSRGB::kDefer));
    return reinterpret_cast<jlong>(Canvas::create_canvas(canvas));
}

static void nativeFinishPage(JNIEnv* env, jobject thiz, jlong documentPtr) {
+45 −18
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@

#include <SkCanvasStateUtils.h>
#include <SkColorFilter.h>
// TODO remove me!
#include <SkColorSpaceXformCanvas.h>
#include <SkDrawable.h>
#include <SkDeque.h>
@@ -48,25 +47,33 @@ Canvas* Canvas::create_canvas(const SkBitmap& bitmap) {
    return new SkiaCanvas(bitmap);
}

Canvas* Canvas::create_canvas(SkCanvas* skiaCanvas, XformToSRGB xformToSRGB) {
    return new SkiaCanvas(skiaCanvas, xformToSRGB);
Canvas* Canvas::create_canvas(SkCanvas* skiaCanvas) {
    return new SkiaCanvas(skiaCanvas);
}

SkiaCanvas::SkiaCanvas() {}

SkiaCanvas::SkiaCanvas(SkCanvas* canvas, XformToSRGB xformToSRGB)
    : mCanvas(canvas)
{
    LOG_ALWAYS_FATAL_IF(XformToSRGB::kImmediate == xformToSRGB);
}
SkiaCanvas::SkiaCanvas(SkCanvas* canvas) : mCanvas(canvas) {}

SkiaCanvas::SkiaCanvas(const SkBitmap& bitmap) {
    sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
    mCanvasOwned =
            std::unique_ptr<SkCanvas>(new SkCanvas(bitmap, SkCanvas::ColorBehavior::kLegacy));
    mCanvasWrapper = SkCreateColorSpaceXformCanvas(mCanvasOwned.get(),
            cs == nullptr ? SkColorSpace::MakeSRGB() : std::move(cs));
    if (cs.get() == nullptr || cs->isSRGB()) {
        if(!uirenderer::Properties::isSkiaEnabled()) {
            mCanvasWrapper = SkCreateColorSpaceXformCanvas(mCanvasOwned.get(), SkColorSpace::MakeSRGB());
            mCanvas = mCanvasWrapper.get();
        } else {
            mCanvas = mCanvasOwned.get();
        }
    } else {
        /** The wrapper is needed if we are drawing into a non-sRGB destination, since
         *  we need to transform all colors (not just bitmaps via filters) into the
         *  destination's colorspace.
         */
        mCanvasWrapper = SkCreateColorSpaceXformCanvas(mCanvasOwned.get(), std::move(cs));
        mCanvas = mCanvasWrapper.get();
    }
}

SkiaCanvas::~SkiaCanvas() {}
@@ -75,6 +82,7 @@ void SkiaCanvas::reset(SkCanvas* skiaCanvas) {
    if (mCanvas != skiaCanvas) {
        mCanvas = skiaCanvas;
        mCanvasOwned.reset();
        mCanvasWrapper.reset();
    }
    mSaveStack.reset(nullptr);
    mHighContrastText = false;
@@ -88,13 +96,18 @@ void SkiaCanvas::setBitmap(const SkBitmap& bitmap) {
    sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
    std::unique_ptr<SkCanvas> newCanvas =
            std::unique_ptr<SkCanvas>(new SkCanvas(bitmap, SkCanvas::ColorBehavior::kLegacy));
    std::unique_ptr<SkCanvas> newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(),
            cs == nullptr ? SkColorSpace::MakeSRGB() : std::move(cs));
    std::unique_ptr<SkCanvas> newCanvasWrapper;
    if (cs.get() != nullptr && !cs->isSRGB()) {
        newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(), std::move(cs));
    }
    else if(!uirenderer::Properties::isSkiaEnabled()) {
        newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(), SkColorSpace::MakeSRGB());
    }

    // deletes the previously owned canvas (if any)
    mCanvasOwned = std::move(newCanvas);
    mCanvasWrapper = std::move(newCanvasWrapper);
    mCanvas = mCanvasWrapper.get();
    mCanvas = mCanvasWrapper ? mCanvasWrapper.get() : mCanvasOwned.get();

    // clean up the old save stack
    mSaveStack.reset(nullptr);
@@ -531,13 +544,27 @@ void SkiaCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, cons
// Canvas draw operations: Bitmaps
// ----------------------------------------------------------------------------

inline static const SkPaint* addFilter(const SkPaint* origPaint, SkPaint* tmpPaint,
        sk_sp<SkColorFilter> colorFilter) {
    if (colorFilter) {
const SkPaint* SkiaCanvas::addFilter(const SkPaint* origPaint, SkPaint* tmpPaint,
        sk_sp<SkColorFilter> colorSpaceFilter) {
    /* 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
     * should only be used if this canvas is backed by a surface/bitmap that is known
     * to have a non-sRGB colorspace.
     */
    if (!mCanvasWrapper && colorSpaceFilter) {
        if (origPaint) {
            *tmpPaint = *origPaint;
        }
        tmpPaint->setColorFilter(colorFilter);

        if (tmpPaint->getColorFilter()) {
            tmpPaint->setColorFilter(SkColorFilter::MakeComposeFilter(
                    tmpPaint->refColorFilter(), colorSpaceFilter));
            LOG_ALWAYS_FATAL_IF(!tmpPaint->getColorFilter());
        } else {
            tmpPaint->setColorFilter(colorSpaceFilter);
        }

        return tmpPaint;
    } else {
        return origPaint;
+4 −5
Original line number Diff line number Diff line
@@ -37,12 +37,8 @@ public:
     *  @param canvas SkCanvas to handle calls made to this SkiaCanvas. Must
     *      not be NULL. This constructor does not take ownership, so the caller
     *      must guarantee that it remains valid while the SkiaCanvas is valid.
     *  @param xformToSRGB Indicates if bitmaps should be xformed to the sRGB
     *      color space before drawing.  This makes sense for software rendering.
     *      For the picture case, it may make more sense to leave bitmaps as is,
     *      and handle the xform when replaying the picture.
     */
    explicit SkiaCanvas(SkCanvas* canvas, XformToSRGB xformToSRGB);
    explicit SkiaCanvas(SkCanvas* canvas);

    virtual ~SkiaCanvas();

@@ -182,6 +178,9 @@ 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);

    class Clip;

    std::unique_ptr<SkCanvas> mCanvasWrapper; // might own a wrapper on the canvas
+1 −12
Original line number Diff line number Diff line
@@ -98,15 +98,6 @@ public:
    static WARN_UNUSED_RESULT Canvas* create_recording_canvas(int width, int height,
            uirenderer::RenderNode* renderNode = nullptr);

    enum class XformToSRGB {
        // Transform any Bitmaps to the sRGB color space before drawing.
        kImmediate,

        // Draw the Bitmap as is.  This likely means that we are recording and that the
        // transform can be handled at playback time.
        kDefer,
    };

    /**
     *  Create a new Canvas object which delegates to an SkCanvas.
     *
@@ -114,12 +105,10 @@ public:
     *      delegated to this object. This function will call ref() on the
     *      SkCanvas, and the returned Canvas will unref() it upon
     *      destruction.
     *  @param xformToSRGB Indicates if bitmaps should be xformed to the sRGB
     *      color space before drawing.
     *  @return new non-null Canvas Object.  The type of DisplayList produced by this canvas is
     *      determined based on  Properties::getRenderPipelineType().
     */
    static Canvas* create_canvas(SkCanvas* skiaCanvas, XformToSRGB xformToSRGB);
    static Canvas* create_canvas(SkCanvas* skiaCanvas);

    /**
     *  Provides a Skia SkCanvas interface that acts as a proxy to this Canvas.
Loading