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
82
83
84
85
86
|
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkColorSpaceXformSteps.h"
// Our logical flow modulo any optimization is:
// For source colors:
// 1) get colors into linear, unpremul format
// 2) transform to dst gamut
// 3) encode with dst transfer function if dst has non-linear blending
// 4) premul so we can blend
//
// For destination colors:
// a) Linearize if dst has linear blending
// b) (Presumably all destinations are already premul, but logically, premul here)
//
// Now the source and destination pipelines unify:
// I) blend the src and dst colors, which are encoded the same way in the same gamut
// II) if dst has linear blending, encode using dst transfer function
//
// Step 1) is represented by three bits:
// - early_unpremul, converting f(s)*a,a to f(s),a if src has non-linear blending
// - linearize_src, converting f(s),a to s,a _or_ f(s*a),a to s*a,a
// - late_unpremul, converting s*a,a to s,a if src has linear blending
// So we'll either early_unpremul and linearize_src, or linearize_src and late_unpremul.
//
SkColorSpaceXformSteps::SkColorSpaceXformSteps(SkColorSpace* src, SkAlphaType srcAT,
SkColorSpace* dst) {
// Set all bools to false, all floats to 0.0f.
memset(this, 0, sizeof(*this));
// We have some options about what to do with null src or dst here.
#if 1
SkASSERT(src && dst);
#else
// If either the source or destination color space is unspecified,
// treat it as non-linearly-blended sRGB ("legacy").
sk_sp<SkColorSpace> sRGB_NL;
if (!src || !dst) {
sRGB_NL = SkColorSpace::MakeSRGB()->makeNonlinearBlending();
if (!src) { src = sRGB_NL.get(); }
if (!dst) { dst = sRGB_NL.get(); }
}
#endif
bool srcNL = src->nonlinearBlending(),
dstNL = dst->nonlinearBlending();
// Step 1) get source colors into linear, unpremul format
this->early_unpremul = srcNL && srcAT == kPremul_SkAlphaType;
this->linearize_src = true;
this->late_unpremul = !srcNL && srcAT == kPremul_SkAlphaType;
// Step 2) transform source colors into destination gamut
this->gamut_transform = (src->toXYZD50Hash() != dst->toXYZD50Hash());
if (this->gamut_transform && src->toXYZD50() && dst->fromXYZD50()) {
auto xform = SkMatrix44(*src->toXYZD50(), *dst->fromXYZD50());
if (xform.get(3,0) == 0 && xform.get(3,1) == 0 && xform.get(3,2) == 0 &&
xform.get(3,3) == 1 &&
xform.get(0,3) == 0 && xform.get(1,3) == 0 && xform.get(2,3) == 0) {
for (int r = 0; r < 3; r++)
for (int c = 0; c < 3; c++) {
this->src_to_dst_matrix[3*r+c] = xform.get(r,c);
}
}
}
// Step 3) encode with dst transfer function if dst has non-linear blending
this->early_encode = dstNL;
// Step 4) premul so we can blend
this->premul = srcAT != kOpaque_SkAlphaType;
// Step a) linearize if dst has linear blending
this->linearize_dst = !dstNL;
// Step II) if dst has linear blending, encode back using dst transfer function before storing
this->late_encode = !dstNL;
}
|