<commit_before>/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkColorSpaceXform.h"
#include "SkColorSpaceXformCanvas.h"
#include "SkMakeUnique.h"
#include "SkNoDrawCanvas.h"
#include "SkSurface.h"
#include "SkTLazy.h"

class SkColorSpaceXformCanvas : public SkNoDrawCanvas {
public:
    SkColorSpaceXformCanvas(SkCanvas* target,
                            sk_sp<SkColorSpace> targetCS)
        : SkNoDrawCanvas(SkIRect::MakeSize(target->getBaseLayerSize()))
        , fTarget(target)
        , fTargetCS(std::move(targetCS)) {

        fFromSRGB = SkColorSpaceXform::New(SkColorSpace::MakeSRGB().get(), fTargetCS.get());
    }

    SkColor xform(SkColor srgb) const {
        SkColor xformed;
        SkAssertResult(fFromSRGB->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &xformed,
                                        SkColorSpaceXform::kBGRA_8888_ColorFormat, &srgb,
                                        1, kUnpremul_SkAlphaType));
        return xformed;
    }

    const SkPaint& xform(const SkPaint& paint, SkTLazy<SkPaint>* lazy) const {
        const SkPaint* result = &paint;
        auto get_lazy = [&] {
            if (!lazy->isValid()) {
                lazy->init(paint);
                result = lazy->get();
            }
            return lazy->get();
        };

        // All SkColorSpaces have the same black point.
        if (paint.getColor() & 0xffffff) {
            get_lazy()->setColor(this->xform(paint.getColor()));
        }

        // TODO:
        //    - shaders
        //    - color filters
        //    - image filters?

        return *result;
    }

    sk_sp<const SkImage> xform(const SkImage* img) const {
        // TODO: for real
        return sk_ref_sp(img);
    }

    const SkPaint* xform(const SkPaint* paint, SkTLazy<SkPaint>* lazy) const {
        return paint ? &this->xform(*paint, lazy) : nullptr;
    }

    void onDrawPaint(const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawPaint(this->xform(paint, &lazy));
    }

    void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawRect(rect, this->xform(paint, &lazy));
    }
    void onDrawOval(const SkRect& oval, const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawOval(oval, this->xform(paint, &lazy));
    }
    void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawRRect(rrect, this->xform(paint, &lazy));
    }
    void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawDRRect(outer, inner, this->xform(paint, &lazy));
    }
    void onDrawPath(const SkPath& path, const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawPath(path, this->xform(paint, &lazy));
    }
    void onDrawArc(const SkRect& oval, SkScalar start, SkScalar sweep, bool useCenter,
                   const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawArc(oval, start, sweep, useCenter, this->xform(paint, &lazy));
    }
    void onDrawRegion(const SkRegion& region, const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawRegion(region, this->xform(paint, &lazy));
    }
    void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texs[4],
                     SkBlendMode mode, const SkPaint& paint) override {
        // TODO: colors
        SkTLazy<SkPaint> lazy;
        fTarget->drawPatch(cubics, colors, texs, mode, this->xform(paint, &lazy));
    }
    void onDrawPoints(PointMode mode, size_t count, const SkPoint* pts,
                      const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawPoints(mode, count, pts, this->xform(paint, &lazy));
    }
    void onDrawVertices(VertexMode vmode, int count,
                        const SkPoint* verts, const SkPoint* texs, const SkColor* colors,
                        SkBlendMode mode,
                        const uint16_t* indices, int indexCount, const SkPaint& paint) override {
        // TODO: colors
        SkTLazy<SkPaint> lazy;
        fTarget->drawVertices(vmode, count, verts, texs, colors, mode, indices, indexCount,
                              this->xform(paint, &lazy));
    }

    void onDrawText(const void* ptr, size_t len,
                    SkScalar x, SkScalar y,
                    const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawText(ptr, len, x, y, this->xform(paint, &lazy));
    }
    void onDrawPosText(const void* ptr, size_t len,
                       const SkPoint* xys,
                       const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawPosText(ptr, len, xys, this->xform(paint, &lazy));
    }
    void onDrawPosTextH(const void* ptr, size_t len,
                        const SkScalar* xs, SkScalar y,
                        const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawPosTextH(ptr, len, xs, y, this->xform(paint, &lazy));
    }
    void onDrawTextOnPath(const void* ptr, size_t len,
                          const SkPath& path, const SkMatrix* matrix,
                          const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawTextOnPath(ptr, len, path, matrix, this->xform(paint, &lazy));
    }
    void onDrawTextRSXform(const void* ptr, size_t len,
                           const SkRSXform* xforms, const SkRect* cull,
                           const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawTextRSXform(ptr, len, xforms, cull, this->xform(paint, &lazy));
    }
    void onDrawTextBlob(const SkTextBlob* blob,
                        SkScalar x, SkScalar y,
                        const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawTextBlob(blob, x, y, this->xform(paint, &lazy));
    }

    void onDrawImage(const SkImage* img,
                     SkScalar l, SkScalar t,
                     const SkPaint* paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawImage(this->xform(img).get(),
                           l, t,
                           this->xform(paint, &lazy));
    }
    void onDrawImageRect(const SkImage* img,
                         const SkRect* src, const SkRect& dst,
                         const SkPaint* paint, SrcRectConstraint constraint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawImageRect(this->xform(img).get(),
                               src ? *src : dst, dst,
                               this->xform(paint, &lazy), constraint);
    }
    void onDrawImageNine(const SkImage* img,
                         const SkIRect& center, const SkRect& dst,
                         const SkPaint* paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawImageNine(this->xform(img).get(),
                               center, dst,
                               this->xform(paint, &lazy));
    }
    void onDrawImageLattice(const SkImage* img,
                            const Lattice& lattice, const SkRect& dst,
                            const SkPaint* paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawImageLattice(this->xform(img).get(),
                                  lattice, dst,
                                  this->xform(paint, &lazy));
    }
    void onDrawAtlas(const SkImage* atlas, const SkRSXform* xforms, const SkRect* tex,
                     const SkColor* colors, int count, SkBlendMode mode,
                     const SkRect* cull, const SkPaint* paint) override {
        // TODO: colors
        SkTLazy<SkPaint> lazy;
        fTarget->drawAtlas(this->xform(atlas).get(), xforms, tex, colors, count, mode, cull,
                           this->xform(paint, &lazy));
    }

    void onDrawBitmap(const SkBitmap& bitmap,
                      SkScalar l, SkScalar t,
                      const SkPaint* paint) override {
        if (auto image = SkImage::MakeFromBitmap(bitmap)) {
            this->onDrawImage(image.get(), l, t, paint);
        }
    }
    void onDrawBitmapRect(const SkBitmap& bitmap,
                          const SkRect* src, const SkRect& dst,
                          const SkPaint* paint, SrcRectConstraint constraint) override {
        if (auto image = SkImage::MakeFromBitmap(bitmap)) {
            this->onDrawImageRect(image.get(), src, dst, paint, constraint);
        }
    }
    void onDrawBitmapNine(const SkBitmap& bitmap,
                          const SkIRect& center, const SkRect& dst,
                          const SkPaint* paint) override {
        if (auto image = SkImage::MakeFromBitmap(bitmap)) {<commit_msg>More SkCSXformCanvas work.<commit_after>/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkColorFilter.h"
#include "SkColorSpaceXform.h"
#include "SkColorSpaceXformCanvas.h"
#include "SkMakeUnique.h"
#include "SkNoDrawCanvas.h"
#include "SkSurface.h"
#include "SkTLazy.h"

class SkColorSpaceXformCanvas : public SkNoDrawCanvas {
public:
    SkColorSpaceXformCanvas(SkCanvas* target,
                            sk_sp<SkColorSpace> targetCS)
        : SkNoDrawCanvas(SkIRect::MakeSize(target->getBaseLayerSize()))
        , fTarget(target)
        , fTargetCS(std::move(targetCS)) {

        fFromSRGB = SkColorSpaceXform::New(SkColorSpace::MakeSRGB().get(), fTargetCS.get());
    }

    void xform(SkColor* xformed, const SkColor* srgb, int n) const {
        SkAssertResult(fFromSRGB->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, xformed,
                                        SkColorSpaceXform::kBGRA_8888_ColorFormat, srgb,
                                        n, kUnpremul_SkAlphaType));
    }

    SkColor xform(SkColor srgb) const {
        SkColor xformed;
        this->xform(&xformed, &srgb, 1);
        return xformed;
    }

    const SkPaint& xform(const SkPaint& paint, SkTLazy<SkPaint>* lazy) const {
        const SkPaint* result = &paint;
        auto get_lazy = [&] {
            if (!lazy->isValid()) {
                lazy->init(paint);
                result = lazy->get();
            }
            return lazy->get();
        };

        // All SkColorSpaces have the same black point.
        if (paint.getColor() & 0xffffff) {
            get_lazy()->setColor(this->xform(paint.getColor()));
        }

        // As far as I know, SkModeColorFilter is the only color filter that holds a color.
        if (auto cf = paint.getColorFilter()) {
            SkColor color;
            SkBlendMode mode;
            if (cf->asColorMode(&color, &mode)) {
                get_lazy()->setColorFilter(SkColorFilter::MakeModeFilter(this->xform(color), mode));
            }
        }

        // TODO:
        //    - shaders
        //    - image filters?

        return *result;
    }

    const SkPaint* xform(const SkPaint* paint, SkTLazy<SkPaint>* lazy) const {
        return paint ? &this->xform(*paint, lazy) : nullptr;
    }

    sk_sp<const SkImage> xform(const SkImage* img) const {
        // TODO: for real
        return sk_ref_sp(img);
    }

    void onDrawPaint(const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawPaint(this->xform(paint, &lazy));
    }

    void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawRect(rect, this->xform(paint, &lazy));
    }
    void onDrawOval(const SkRect& oval, const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawOval(oval, this->xform(paint, &lazy));
    }
    void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawRRect(rrect, this->xform(paint, &lazy));
    }
    void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawDRRect(outer, inner, this->xform(paint, &lazy));
    }
    void onDrawPath(const SkPath& path, const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawPath(path, this->xform(paint, &lazy));
    }
    void onDrawArc(const SkRect& oval, SkScalar start, SkScalar sweep, bool useCenter,
                   const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawArc(oval, start, sweep, useCenter, this->xform(paint, &lazy));
    }
    void onDrawRegion(const SkRegion& region, const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawRegion(region, this->xform(paint, &lazy));
    }
    void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texs[4],
                     SkBlendMode mode, const SkPaint& paint) override {
        SkColor xformed[4];
        if (colors) {
            this->xform(xformed, colors, 4);
            colors = xformed;
        }

        SkTLazy<SkPaint> lazy;
        fTarget->drawPatch(cubics, colors, texs, mode, this->xform(paint, &lazy));
    }
    void onDrawPoints(PointMode mode, size_t count, const SkPoint* pts,
                      const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawPoints(mode, count, pts, this->xform(paint, &lazy));
    }
    void onDrawVertices(VertexMode vmode, int count,
                        const SkPoint* verts, const SkPoint* texs, const SkColor* colors,
                        SkBlendMode mode,
                        const uint16_t* indices, int indexCount, const SkPaint& paint) override {
        SkTArray<SkColor> xformed;
        if (colors) {
            xformed.reset(count);
            this->xform(xformed.begin(), colors, count);
            colors = xformed.begin();
        }

        SkTLazy<SkPaint> lazy;
        fTarget->drawVertices(vmode, count, verts, texs, colors, mode, indices, indexCount,
                              this->xform(paint, &lazy));
    }

    void onDrawText(const void* ptr, size_t len,
                    SkScalar x, SkScalar y,
                    const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawText(ptr, len, x, y, this->xform(paint, &lazy));
    }
    void onDrawPosText(const void* ptr, size_t len,
                       const SkPoint* xys,
                       const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawPosText(ptr, len, xys, this->xform(paint, &lazy));
    }
    void onDrawPosTextH(const void* ptr, size_t len,
                        const SkScalar* xs, SkScalar y,
                        const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawPosTextH(ptr, len, xs, y, this->xform(paint, &lazy));
    }
    void onDrawTextOnPath(const void* ptr, size_t len,
                          const SkPath& path, const SkMatrix* matrix,
                          const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawTextOnPath(ptr, len, path, matrix, this->xform(paint, &lazy));
    }
    void onDrawTextRSXform(const void* ptr, size_t len,
                           const SkRSXform* xforms, const SkRect* cull,
                           const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawTextRSXform(ptr, len, xforms, cull, this->xform(paint, &lazy));
    }
    void onDrawTextBlob(const SkTextBlob* blob,
                        SkScalar x, SkScalar y,
                        const SkPaint& paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawTextBlob(blob, x, y, this->xform(paint, &lazy));
    }

    void onDrawImage(const SkImage* img,
                     SkScalar l, SkScalar t,
                     const SkPaint* paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawImage(this->xform(img).get(),
                           l, t,
                           this->xform(paint, &lazy));
    }
    void onDrawImageRect(const SkImage* img,
                         const SkRect* src, const SkRect& dst,
                         const SkPaint* paint, SrcRectConstraint constraint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawImageRect(this->xform(img).get(),
                               src ? *src : dst, dst,
                               this->xform(paint, &lazy), constraint);
    }
    void onDrawImageNine(const SkImage* img,
                         const SkIRect& center, const SkRect& dst,
                         const SkPaint* paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawImageNine(this->xform(img).get(),
                               center, dst,
                               this->xform(paint, &lazy));
    }
    void onDrawImageLattice(const SkImage* img,
                            const Lattice& lattice, const SkRect& dst,
                            const SkPaint* paint) override {
        SkTLazy<SkPaint> lazy;
        fTarget->drawImageLattice(this->xform(img).get(),
                                  lattice, dst,
                                  this->xform(paint, &lazy));
    }
    void onDrawAtlas(const SkImage* atlas, const SkRSXform* xforms, const SkRect* tex,
                     const SkColor* colors, int count, SkBlendMode mode,
                     const SkRect* cull, const SkPaint* paint) override {
        SkTArray<SkColor> xformed;
        if (colors) {
            xformed.reset(count);
            this->xform(xformed.begin(), colors, count);
            colors = xformed.begin();
        }

        SkTLazy<SkPaint> lazy;
        fTarget->drawAtlas(this->xform(atlas).get(), xforms, tex, colors, count, mode, cull,
                           this->xform(paint, &lazy));
    }

    void onDrawBitmap(const SkBitmap& bitmap,
                      SkScalar l, SkScalar t,
                      const SkPaint* paint) override {
        if (auto image = SkImage::MakeFromBitmap(bitmap)) {
            this->onDrawImage(image.get(), l, t, paint);
        }
    }
    void onDrawBitmapRect(const SkBitmap& bitmap,
                          const SkRect* src, const SkRect& dst,
                          const SkPaint* paint, SrcRectConstraint constraint) override {
        if (auto image = SkImage::MakeFromBitmap(bitmap)) {
            this->onDrawImageRect(image.get(), src, dst, paint, constraint);
        }
    }
    void onDrawBitmapNine(const SkBitmap& bitmap,
                          const SkIRect& center, const SkRect& dst,
                          const SkPaint* paint) override {
        if (auto image = SkImage::MakeFromBitmap(bitmap)) {
{'fraction_non_alphanumeric': 0.1074262139003491, 'fraction_numerical': 0.002221516978736909, 'mean_word_length': 1.9616228070175439, 'pattern_counts': {'":': 0, '<': 57, '<?xml version=': 0, '>': 184, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5984546', 'n_tokens_mistral': 5687, 'n_tokens_neox': 5575, 'n_words': 1355}