Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2017 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkColorSpace_New.h"
      9 #include "SkOpts.h"
     10 #include "SkRasterPipeline.h"
     11 
     12 // ~~~~~~~~~~~~~~~~~~~~~~~ SkColorSpace_New::TransferFn ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
     13 
     14 namespace {
     15 
     16     struct LinearTransferFn : public SkColorSpace_New::TransferFn {
     17         SkColorSpaceTransferFn parameterize() const override {
     18             return { 1,1, 0,0,0,0,0 };
     19         }
     20 
     21         void linearizeDst(SkRasterPipeline*) const override {}
     22         void linearizeSrc(SkRasterPipeline*) const override {}
     23         void    encodeSrc(SkRasterPipeline*) const override {}
     24     };
     25 
     26     struct SRGBTransferFn : public SkColorSpace_New::TransferFn {
     27         SkColorSpaceTransferFn parameterize() const override {
     28             return { 2.4f, 1/1.055f, 0.055f/1.055f, 1/12.92f, 0.04045f, 0, 0 };
     29         }
     30 
     31         void linearizeDst(SkRasterPipeline* p) const override {
     32             p->append(SkRasterPipeline::from_srgb_dst);
     33         }
     34         void linearizeSrc(SkRasterPipeline* p) const override {
     35             p->append(SkRasterPipeline::from_srgb);
     36         }
     37         void encodeSrc(SkRasterPipeline* p) const override {
     38             p->append(SkRasterPipeline::to_srgb);
     39         }
     40     };
     41 
     42     struct GammaTransferFn : public SkColorSpace_New::TransferFn {
     43         float fGamma;
     44         float fInv;
     45 
     46         explicit GammaTransferFn(float gamma) : fGamma(gamma), fInv(1.0f/gamma) {}
     47 
     48         SkColorSpaceTransferFn parameterize() const override {
     49             return { fGamma, 1, 0,0,0,0,0 };
     50         }
     51 
     52         void linearizeDst(SkRasterPipeline* p) const override {
     53             p->append(SkRasterPipeline::gamma_dst, &fGamma);
     54         }
     55         void linearizeSrc(SkRasterPipeline* p) const override {
     56             p->append(SkRasterPipeline::gamma, &fGamma);
     57         }
     58         void encodeSrc(SkRasterPipeline* p) const override {
     59             p->append(SkRasterPipeline::gamma, &fInv);
     60         }
     61     };
     62 
     63 }
     64 
     65 sk_sp<SkColorSpace_New::TransferFn> SkColorSpace_New::TransferFn::MakeLinear() {
     66     return sk_make_sp<LinearTransferFn>();
     67 }
     68 sk_sp<SkColorSpace_New::TransferFn> SkColorSpace_New::TransferFn::MakeSRGB() {
     69     return sk_make_sp<SRGBTransferFn>();
     70 }
     71 sk_sp<SkColorSpace_New::TransferFn> SkColorSpace_New::TransferFn::MakeGamma(float gamma) {
     72     if (gamma == 1) {
     73         return MakeLinear();
     74     }
     75     return sk_make_sp<GammaTransferFn>(gamma);
     76 }
     77 
     78 bool SkColorSpace_New::TransferFn::equals(const SkColorSpace_New::TransferFn& other) const {
     79     SkColorSpaceTransferFn a = this->parameterize(),
     80                            b = other.parameterize();
     81     return 0 == memcmp(&a,&b, sizeof(SkColorSpaceTransferFn));
     82 }
     83 
     84 void SkColorSpace_New::TransferFn::updateICCProfile(ICCProfile*) const {
     85     // TODO
     86 }
     87 
     88 // ~~~~~~~~~~~~~~~~~~~~~~~ SkColorSpace_New ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
     89 
     90 SkColorSpace_New::SkColorSpace_New(sk_sp<TransferFn> transferFn,
     91                                    SkMatrix44 toXYZD50,
     92                                    Blending blending)
     93     : fTransferFn(std::move(transferFn))
     94     , fFromXYZD50(SkMatrix44::kUninitialized_Constructor)
     95     , fToXYZD50(toXYZD50)
     96     , fToXYZD50Hash(SkOpts::hash_fn(&toXYZD50, 16*sizeof(SkMScalar), 0))
     97     , fBlending(blending)
     98 {
     99     // It's pretty subtle what do to if the to-XYZ matrix is not invertible.
    100     // That means the same point in XYZ is mapped to from more than one point in RGB,
    101     // or put another way, we threw information away when mapping RGB -> XYZ.
    102     //
    103     // We'd probably like to set fToXYZD50 as one of the family of matrices that
    104     // will correctly roundtrip XYZ -> RGB -> XYZ.  Choosing which is an open problem.
    105     SkAssertResult(fToXYZD50.invert(&fFromXYZD50));
    106 }
    107 
    108 sk_sp<SkColorSpace> SkColorSpace_New::makeLinearGamma() const {
    109     return sk_make_sp<SkColorSpace_New>(TransferFn::MakeLinear(), fToXYZD50, fBlending);
    110 }
    111 sk_sp<SkColorSpace> SkColorSpace_New::makeSRGBGamma() const {
    112     return sk_make_sp<SkColorSpace_New>(TransferFn::MakeSRGB(), fToXYZD50, fBlending);
    113 }
    114 
    115 SkGammaNamed SkColorSpace_New::onGammaNamed() const {
    116     return kNonStandard_SkGammaNamed;  // TODO
    117 }
    118 
    119 bool SkColorSpace_New::onGammaCloseToSRGB() const {
    120     return fTransferFn->equals(*TransferFn::MakeSRGB());  // TODO: more efficient?
    121 }
    122 
    123 bool SkColorSpace_New::onGammaIsLinear() const {
    124     return fTransferFn->equals(*TransferFn::MakeLinear());  // TODO: more efficient?
    125 }
    126 
    127 bool SkColorSpace_New::onIsNumericalTransferFn(SkColorSpaceTransferFn* fn) const {
    128     *fn = fTransferFn->parameterize();
    129     return true;
    130 }
    131