blob: cbb55cc0c031a1a933b97fc78a3de0a1d7b77282 [file] [log] [blame]
/*
* 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 "SkColorSpacePriv.h"
#include "SkColorSpaceXformPriv.h"
#include "SkOpts.h"
SkColorSpace_XYZ::SkColorSpace_XYZ(SkGammaNamed gammaNamed,
const SkColorSpaceTransferFn* transferFn,
const SkMatrix44& toXYZD50)
: fGammaNamed(gammaNamed)
, fToXYZD50(toXYZD50)
, fToXYZD50Hash(SkOpts::hash_fn(toXYZD50.values(), 16 * sizeof(SkMScalar), 0))
, fFromXYZD50(SkMatrix44::kUninitialized_Constructor) {
SkASSERT(fGammaNamed != kNonStandard_SkGammaNamed || transferFn);
if (transferFn) {
fTransferFn = *transferFn;
}
}
const SkMatrix44* SkColorSpace_XYZ::onFromXYZD50() 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.
SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor);
srgbToxyzD50.set3x3RowMajorf(gSRGB_toXYZD50);
srgbToxyzD50.invert(&fFromXYZD50);
}
});
return &fFromXYZD50;
}
bool SkColorSpace_XYZ::onGammaCloseToSRGB() const {
return kSRGB_SkGammaNamed == fGammaNamed;
}
bool SkColorSpace_XYZ::onGammaIsLinear() const {
return kLinear_SkGammaNamed == fGammaNamed;
}
bool SkColorSpace_XYZ::onIsNumericalTransferFn(SkColorSpaceTransferFn* coeffs) const {
switch (fGammaNamed) {
case kSRGB_SkGammaNamed:
*coeffs = gSRGB_TransferFn;
break;
case k2Dot2Curve_SkGammaNamed:
*coeffs = g2Dot2_TransferFn;
break;
case kLinear_SkGammaNamed:
*coeffs = gLinear_TransferFn;
break;
case kNonStandard_SkGammaNamed:
*coeffs = fTransferFn;
break;
default:
SkDEBUGFAIL("Unknown named gamma");
return false;
}
return true;
}
sk_sp<SkColorSpace> SkColorSpace_XYZ::makeLinearGamma() const {
if (this->gammaIsLinear()) {
return sk_ref_sp(const_cast<SkColorSpace_XYZ*>(this));
}
return SkColorSpace::MakeRGB(kLinear_SkGammaNamed, fToXYZD50);
}
sk_sp<SkColorSpace> SkColorSpace_XYZ::makeSRGBGamma() const {
if (this->gammaCloseToSRGB()) {
return sk_ref_sp(const_cast<SkColorSpace_XYZ*>(this));
}
return SkColorSpace::MakeRGB(kSRGB_SkGammaNamed, fToXYZD50);
}
sk_sp<SkColorSpace> SkColorSpace_XYZ::makeColorSpin() const {
SkMatrix44 spin(SkMatrix44::kUninitialized_Constructor);
spin.set3x3(0, 1, 0, 0, 0, 1, 1, 0, 0);
spin.postConcat(fToXYZD50);
(void)spin.getType(); // Pre-cache spin matrix type to avoid races in future getType() calls.
return sk_sp<SkColorSpace>(new SkColorSpace_XYZ(fGammaNamed, &fTransferFn, spin));
}