aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkColorSpace_XYZ.cpp
blob: 3570e25b62e931c723cd8057f542cf5e9eb862fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkColorSpace_XYZ.h"
#include "SkChecksum.h"
#include "SkColorSpaceXform_Base.h"

static constexpr float gSRGB_toXYZD50[] {
    0.4358f, 0.3853f, 0.1430f,    // Rx, Gx, Bx
    0.2224f, 0.7170f, 0.0606f,    // Ry, Gy, Gz
    0.0139f, 0.0971f, 0.7139f,    // Rz, Gz, Bz
};

SkColorSpace_XYZ::SkColorSpace_XYZ(SkGammaNamed gammaNamed, const SkMatrix44& toXYZD50)
    : INHERITED(nullptr)
    , fGammaNamed(gammaNamed)
    , fGammas(nullptr)
    , fToXYZD50(toXYZD50)
    , fToXYZD50Hash(SkGoodHash()(toXYZD50))
    , fFromXYZD50(SkMatrix44::kUninitialized_Constructor)
{}

SkColorSpace_XYZ::SkColorSpace_XYZ(SkGammaNamed gammaNamed, sk_sp<SkGammas> gammas,
                                   const SkMatrix44& toXYZD50, sk_sp<SkData> profileData)
    : INHERITED(std::move(profileData))
    , fGammaNamed(gammaNamed)
    , fGammas(std::move(gammas))
    , fToXYZD50(toXYZD50)
    , fToXYZD50Hash(SkGoodHash()(toXYZD50))
    , fFromXYZD50(SkMatrix44::kUninitialized_Constructor)
{}

const SkMatrix44* SkColorSpace_XYZ::fromXYZD50() const {
    fFromXYZOnce([this] {
        if (!fToXYZD50.invert(&fFromXYZD50)) {
            // If a client gives us a dst gamut with a transform that we can't invert, we will
            // simply give them back a transform to sRGB gamut.
            SkDEBUGFAIL("Non-invertible XYZ matrix, defaulting to sRGB");
            SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor);
            srgbToxyzD50.set3x3RowMajorf(gSRGB_toXYZD50);
            srgbToxyzD50.invert(&fFromXYZD50);
        }
    });
    return &fFromXYZD50;
}

bool SkColorSpace_XYZ::onGammaCloseToSRGB() const {
    return kSRGB_SkGammaNamed == fGammaNamed || k2Dot2Curve_SkGammaNamed == fGammaNamed;
}

bool SkColorSpace_XYZ::onGammaIsLinear() const {
    return kLinear_SkGammaNamed == fGammaNamed;
}

sk_sp<SkColorSpace> SkColorSpace_XYZ::makeLinearGamma() {
    if (this->gammaIsLinear()) {
        return sk_ref_sp(this);
    }
    return SkColorSpace_Base::NewRGB(kLinear_SkGammaNamed, fToXYZD50);
}

void SkColorSpace_XYZ::toDstGammaTables(const uint8_t* tables[3], sk_sp<SkData>* storage,
                                         int numTables) const {
    fToDstGammaOnce([this, numTables] {
        const bool gammasAreMatching = numTables <= 1;
        fDstStorage =
                SkData::MakeUninitialized(numTables * SkColorSpaceXform_Base::kDstGammaTableSize);
        SkColorSpaceXform_Base::BuildDstGammaTables(fToDstGammaTables,
                                                    (uint8_t*) fDstStorage->writable_data(), this,
                                                    gammasAreMatching);
    });

    *storage = fDstStorage;
    tables[0] = fToDstGammaTables[0];
    tables[1] = fToDstGammaTables[1];
    tables[2] = fToDstGammaTables[2];
}