19876ac5b3016e5353c072378ac1545a0a2270757msarett/*
29876ac5b3016e5353c072378ac1545a0a2270757msarett * Copyright 2016 Google Inc.
39876ac5b3016e5353c072378ac1545a0a2270757msarett *
49876ac5b3016e5353c072378ac1545a0a2270757msarett * Use of this source code is governed by a BSD-style license that can be
59876ac5b3016e5353c072378ac1545a0a2270757msarett * found in the LICENSE file.
69876ac5b3016e5353c072378ac1545a0a2270757msarett */
79876ac5b3016e5353c072378ac1545a0a2270757msarett
8a4083c97d48e8a4f88e2797d7363f141e3d42553Cary Clark#include "SkColorData.h"
9200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett#include "SkColorSpacePriv.h"
1098156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein#include "SkColorSpaceXformPriv.h"
112563601fc2b0505619f905f86bd249ae630197ccraftias#include "SkColorSpaceXform_A2B.h"
1231d097e865f266c8398f45114e4c75c0dfdef058msarett#include "SkColorSpaceXform_Base.h"
1398156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein#include "SkColorSpace_A2B.h"
1498156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein#include "SkColorSpace_XYZ.h"
15200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett#include "SkHalf.h"
1698156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein#include "SkMakeUnique.h"
17200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett#include "SkOpts.h"
185e15961fa77281540a80ac0d036fefe071c11574Mike Klein#include "SkPM4fPriv.h"
19f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett#include "SkRasterPipeline.h"
20ac41bac40f5a80d2bc5ccec584c23478a6900179mtklein#include "SkSRGB.h"
2145c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein#include "../jumper/SkJumper.h"
229876ac5b3016e5353c072378ac1545a0a2270757msarett
236006f678e78af7b6f67a454cd4bc213048983f9dmsarettstatic constexpr float sk_linear_from_2dot2[256] = {
24b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.000000000000000000f, 0.000005077051900662f, 0.000023328004666099f, 0.000056921765712193f,
25b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.000107187362341244f, 0.000175123977503027f, 0.000261543754548491f, 0.000367136269815943f,
26b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.000492503787191433f, 0.000638182842167022f, 0.000804658499513058f, 0.000992374304074325f,
27b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.001201739522438400f, 0.001433134589671860f, 0.001686915316789280f, 0.001963416213396470f,
28b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.002262953160706430f, 0.002585825596234170f, 0.002932318323938360f, 0.003302703032003640f,
29b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.003697239578900130f, 0.004116177093282750f, 0.004559754922526020f, 0.005028203456855540f,
30b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.005521744850239660f, 0.006040593654849810f, 0.006584957382581690f, 0.007155037004573030f,
31b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.007751027397660610f, 0.008373117745148580f, 0.009021491898012130f, 0.009696328701658230f,
32b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.010397802292555300f, 0.011126082368383200f, 0.011881334434813700f, 0.012663720031582100f,
33b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.013473396940142600f, 0.014310519374884100f, 0.015175238159625200f, 0.016067700890886900f,
34b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.016988052089250000f, 0.017936433339950200f, 0.018912983423721500f, 0.019917838438785700f,
35b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.020951131914781100f, 0.022012994919336500f, 0.023103556157921400f, 0.024222942067534200f,
36b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.025371276904734600f, 0.026548682828472900f, 0.027755279978126000f, 0.028991186547107800f,
37b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.030256518852388700f, 0.031551391400226400f, 0.032875916948383800f, 0.034230206565082000f,
38b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.035614369684918800f, 0.037028514161960200f, 0.038472746320194600f, 0.039947171001525600f,
39b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.041451891611462500f, 0.042987010162657100f, 0.044552627316421400f, 0.046148842422351000f,
40b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.047775753556170600f, 0.049433457555908000f, 0.051122050056493400f, 0.052841625522879000f,
41b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.054592277281760300f, 0.056374097551979800f, 0.058187177473685400f, 0.060031607136313200f,
42b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.061907475605455800f, 0.063814870948677200f, 0.065753880260330100f, 0.067724589685424300f,
43b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.069727084442598800f, 0.071761448846239100f, 0.073827766327784600f, 0.075926119456264800f,
44b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.078056589958101900f, 0.080219258736215100f, 0.082414205888459200f, 0.084641510725429500f,
45b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.086901251787660300f, 0.089193506862247800f, 0.091518352998919500f, 0.093875866525577800f,
46b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.096266123063339700f, 0.098689197541094500f, 0.101145164209600000f, 0.103634096655137000f,
47b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.106156067812744000f, 0.108711149979039000f, 0.111299414824660000f, 0.113920933406333000f,
48b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.116575776178572000f, 0.119264013005047000f, 0.121985713169619000f, 0.124740945387051000f,
49b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.127529777813422000f, 0.130352278056244000f, 0.133208513184300000f, 0.136098549737202000f,
50b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.139022453734703000f, 0.141980290685736000f, 0.144972125597231000f, 0.147998022982685000f,
51b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.151058046870511000f, 0.154152260812165000f, 0.157280727890073000f, 0.160443510725344000f,
52b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.163640671485290000f, 0.166872271890766000f, 0.170138373223312000f, 0.173439036332135000f,
53b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.176774321640903000f, 0.180144289154390000f, 0.183548998464951000f, 0.186988508758844000f,
54b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.190462878822409000f, 0.193972167048093000f, 0.197516431440340000f, 0.201095729621346000f,
55b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.204710118836677000f, 0.208359655960767000f, 0.212044397502288000f, 0.215764399609395000f,
56b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.219519718074868000f, 0.223310408341127000f, 0.227136525505149000f, 0.230998124323267000f,
57b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.234895259215880000f, 0.238827984272048000f, 0.242796353254002000f, 0.246800419601550000f,
58b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.250840236436400000f, 0.254915856566385000f, 0.259027332489606000f, 0.263174716398492000f,
59b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.267358060183772000f, 0.271577415438375000f, 0.275832833461245000f, 0.280124365261085000f,
60b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.284452061560024000f, 0.288815972797219000f, 0.293216149132375000f, 0.297652640449211000f,
61b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.302125496358853000f, 0.306634766203158000f, 0.311180499057984000f, 0.315762743736397000f,
62b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.320381548791810000f, 0.325036962521076000f, 0.329729032967515000f, 0.334457807923889000f,
63b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.339223334935327000f, 0.344025661302187000f, 0.348864834082879000f, 0.353740900096629000f,
64b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.358653905926199000f, 0.363603897920553000f, 0.368590922197487000f, 0.373615024646202000f,
65b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.378676250929840000f, 0.383774646487975000f, 0.388910256539059000f, 0.394083126082829000f,
66b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.399293299902674000f, 0.404540822567962000f, 0.409825738436323000f, 0.415148091655907000f,
67b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.420507926167587000f, 0.425905285707146000f, 0.431340213807410000f, 0.436812753800359000f,
68b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.442322948819202000f, 0.447870841800410000f, 0.453456475485731000f, 0.459079892424160000f,
69b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.464741134973889000f, 0.470440245304218000f, 0.476177265397440000f, 0.481952237050698000f,
70b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.487765201877811000f, 0.493616201311074000f, 0.499505276603030000f, 0.505432468828216000f,
71b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.511397818884880000f, 0.517401367496673000f, 0.523443155214325000f, 0.529523222417277000f,
72b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.535641609315311000f, 0.541798355950137000f, 0.547993502196972000f, 0.554227087766085000f,
73b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.560499152204328000f, 0.566809734896638000f, 0.573158875067523000f, 0.579546611782525000f,
74b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.585972983949661000f, 0.592438030320847000f, 0.598941789493296000f, 0.605484299910907000f,
75b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.612065599865624000f, 0.618685727498780000f, 0.625344720802427000f, 0.632042617620641000f,
76b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.638779455650817000f, 0.645555272444935000f, 0.652370105410821000f, 0.659223991813387000f,
77b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.666116968775851000f, 0.673049073280942000f, 0.680020342172095000f, 0.687030812154625000f,
78b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.694080519796882000f, 0.701169501531402000f, 0.708297793656032000f, 0.715465432335048000f,
79b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.722672453600255000f, 0.729918893352071000f, 0.737204787360605000f, 0.744530171266715000f,
80b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.751895080583051000f, 0.759299550695091000f, 0.766743616862161000f, 0.774227314218442000f,
81b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.781750677773962000f, 0.789313742415586000f, 0.796916542907978000f, 0.804559113894567000f,
82b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.812241489898490000f, 0.819963705323528000f, 0.827725794455034000f, 0.835527791460841000f,
83b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.843369730392169000f, 0.851251645184515000f, 0.859173569658532000f, 0.867135537520905000f,
84b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.875137582365205000f, 0.883179737672745000f, 0.891262036813419000f, 0.899384513046529000f,
85b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.907547199521614000f, 0.915750129279253000f, 0.923993335251873000f, 0.932276850264543000f,
86b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.940600707035753000f, 0.948964938178195000f, 0.957369576199527000f, 0.965814653503130000f,
87b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.974300202388861000f, 0.982826255053791000f, 0.991392843592940000f, 1.000000000000000000f,
88b39067696ad08a26bbe49b71a71f0546dc42a075msarett};
89b39067696ad08a26bbe49b71a71f0546dc42a075msarett
906006f678e78af7b6f67a454cd4bc213048983f9dmsarett///////////////////////////////////////////////////////////////////////////////////////////////////
916006f678e78af7b6f67a454cd4bc213048983f9dmsarett
9215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarettstatic void build_table_linear_from_gamma(float* outTable, float exponent) {
9315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) {
9415ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        *outTable++ = powf(x, exponent);
9515ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    }
9615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett}
9715ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett
9815ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett// outTable is always 256 entries, inTable may be larger or smaller.
9915ee3deee8aca2bf6e658449f25ee34a8153e6eemsarettstatic void build_table_linear_from_gamma(float* outTable, const float* inTable,
10015ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett                                          int inTableSize) {
10115ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    if (256 == inTableSize) {
10215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        memcpy(outTable, inTable, sizeof(float) * 256);
10315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        return;
10415ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    }
10515ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett
10615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) {
10715ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        *outTable++ = interp_lut(x, inTable, inTableSize);
10815ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    }
10915ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett}
11015ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett
111aa34f7ea58330cb73ea17f01715cb6c7d439fae9Matt Sarett
11215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarettstatic void build_table_linear_from_gamma(float* outTable, float g, float a, float b, float c,
11315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett                                          float d, float e, float f) {
1142410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett    // Y = (aX + b)^g + e  for X >= d
1152410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett    // Y = cX + f          otherwise
11615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) {
11715ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        if (x >= d) {
1182410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett            *outTable++ = clamp_0_1(powf(a * x + b, g) + e);
11915ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        } else {
1202410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett            *outTable++ = clamp_0_1(c * x + f);
12115ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        }
12215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    }
12315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett}
12415ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett
12515ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett///////////////////////////////////////////////////////////////////////////////////////////////////
12615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett
127f489886915034093278353d06c6f1973b2e8b7d2Matt Sarettstatic const int kDstGammaTableSize = SkColorSpaceXform_Base::kDstGammaTableSize;
1283418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett
1291b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, float exponent) {
130b39067696ad08a26bbe49b71a71f0546dc42a075msarett    float toGammaExp = 1.0f / exponent;
131b39067696ad08a26bbe49b71a71f0546dc42a075msarett
1323418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett    for (int i = 0; i < kDstGammaTableSize; i++) {
1333418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett        float x = ((float) i) * (1.0f / ((float) (kDstGammaTableSize - 1)));
134b39067696ad08a26bbe49b71a71f0546dc42a075msarett        outTable[i] = clamp_normalized_float_to_byte(powf(x, toGammaExp));
135b39067696ad08a26bbe49b71a71f0546dc42a075msarett    }
136dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett}
137dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett
1381b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, const float* inTable,
139b39067696ad08a26bbe49b71a71f0546dc42a075msarett                                        int inTableSize) {
140197e311ac9d15696fae929d8f5fcf9d93ec55e18raftias    invert_table_gamma(nullptr, outTable, kDstGammaTableSize, inTable, inTableSize);
141b39067696ad08a26bbe49b71a71f0546dc42a075msarett}
142dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett
143b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic float inverse_parametric(float x, float g, float a, float b, float c, float d, float e,
144b39067696ad08a26bbe49b71a71f0546dc42a075msarett                                float f) {
145b39067696ad08a26bbe49b71a71f0546dc42a075msarett    // We need to take the inverse of the following piecewise function.
1460cea26aaf27a3e55dabead3f8da1cd7cbcf6ac73Mike Klein    // Y = (aX + b)^g + e  for X >= d
1470cea26aaf27a3e55dabead3f8da1cd7cbcf6ac73Mike Klein    // Y = cX + f          otherwise
148b39067696ad08a26bbe49b71a71f0546dc42a075msarett
149b39067696ad08a26bbe49b71a71f0546dc42a075msarett    // Assume that the gamma function is continuous, or this won't make much sense anyway.
1500cea26aaf27a3e55dabead3f8da1cd7cbcf6ac73Mike Klein    // Plug in |d| to the second equation to calculate the new piecewise interval.
151b39067696ad08a26bbe49b71a71f0546dc42a075msarett    // Then simply use the inverse of the original functions.
1522410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett    float interval = c * d + f;
153b39067696ad08a26bbe49b71a71f0546dc42a075msarett    if (x < interval) {
1542410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett        // X = (Y - F) / C
1552410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett        if (0.0f == c) {
156b39067696ad08a26bbe49b71a71f0546dc42a075msarett            // The gamma curve for this segment is constant, so the inverse is undefined.
157b39067696ad08a26bbe49b71a71f0546dc42a075msarett            // Since this is the lower segment, guess zero.
158b39067696ad08a26bbe49b71a71f0546dc42a075msarett            return 0.0f;
159b39067696ad08a26bbe49b71a71f0546dc42a075msarett        }
160b39067696ad08a26bbe49b71a71f0546dc42a075msarett
1612410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett        return (x - f) / c;
162b39067696ad08a26bbe49b71a71f0546dc42a075msarett    }
163b39067696ad08a26bbe49b71a71f0546dc42a075msarett
1642410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett    // X = ((Y - E)^(1 / G) - B) / A
165b39067696ad08a26bbe49b71a71f0546dc42a075msarett    if (0.0f == a || 0.0f == g) {
166b39067696ad08a26bbe49b71a71f0546dc42a075msarett        // The gamma curve for this segment is constant, so the inverse is undefined.
167b39067696ad08a26bbe49b71a71f0546dc42a075msarett        // Since this is the upper segment, guess one.
168b39067696ad08a26bbe49b71a71f0546dc42a075msarett        return 1.0f;
169b39067696ad08a26bbe49b71a71f0546dc42a075msarett    }
170b39067696ad08a26bbe49b71a71f0546dc42a075msarett
1712410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett    return (powf(x - e, 1.0f / g) - b) / a;
172b39067696ad08a26bbe49b71a71f0546dc42a075msarett}
173b39067696ad08a26bbe49b71a71f0546dc42a075msarett
1741b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, float g, float a,
175b39067696ad08a26bbe49b71a71f0546dc42a075msarett                                        float b, float c, float d, float e, float f) {
1763418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett    for (int i = 0; i < kDstGammaTableSize; i++) {
1773418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett        float x = ((float) i) * (1.0f / ((float) (kDstGammaTableSize - 1)));
178b39067696ad08a26bbe49b71a71f0546dc42a075msarett        float y = inverse_parametric(x, g, a, b, c, d, e, f);
179b39067696ad08a26bbe49b71a71f0546dc42a075msarett        outTable[i] = clamp_normalized_float_to_byte(y);
180b39067696ad08a26bbe49b71a71f0546dc42a075msarett    }
181b39067696ad08a26bbe49b71a71f0546dc42a075msarett}
182b39067696ad08a26bbe49b71a71f0546dc42a075msarett
1836006f678e78af7b6f67a454cd4bc213048983f9dmsarett///////////////////////////////////////////////////////////////////////////////////////////////////
1846006f678e78af7b6f67a454cd4bc213048983f9dmsarett
1851b93bd1e6eba3d14593490e4e24a34546638c8damsaretttemplate <typename T>
1861b93bd1e6eba3d14593490e4e24a34546638c8damsarettstruct GammaFns {
1871b93bd1e6eba3d14593490e4e24a34546638c8damsarett    const T* fSRGBTable;
1881b93bd1e6eba3d14593490e4e24a34546638c8damsarett    const T* f2Dot2Table;
1891b93bd1e6eba3d14593490e4e24a34546638c8damsarett    void (*fBuildFromValue)(T*, float);
1901b93bd1e6eba3d14593490e4e24a34546638c8damsarett    void (*fBuildFromTable)(T*, const float*, int);
1911b93bd1e6eba3d14593490e4e24a34546638c8damsarett    void (*fBuildFromParam)(T*, float, float, float, float, float, float, float);
1921b93bd1e6eba3d14593490e4e24a34546638c8damsarett};
1931b93bd1e6eba3d14593490e4e24a34546638c8damsarett
1941b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic const GammaFns<float> kToLinear {
1951b93bd1e6eba3d14593490e4e24a34546638c8damsarett    sk_linear_from_srgb,
1961b93bd1e6eba3d14593490e4e24a34546638c8damsarett    sk_linear_from_2dot2,
1971b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_from_gamma,
1981b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_from_gamma,
1991b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_from_gamma,
2001b93bd1e6eba3d14593490e4e24a34546638c8damsarett};
2011b93bd1e6eba3d14593490e4e24a34546638c8damsarett
2021b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic const GammaFns<uint8_t> kFromLinear {
20355bcc8e0af3415601b3d62252a0d579fbe87c85amsarett    nullptr,
20455bcc8e0af3415601b3d62252a0d579fbe87c85amsarett    nullptr,
2051b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_to_gamma,
2061b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_to_gamma,
2071b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_to_gamma,
2081b93bd1e6eba3d14593490e4e24a34546638c8damsarett};
2091b93bd1e6eba3d14593490e4e24a34546638c8damsarett
2101b93bd1e6eba3d14593490e4e24a34546638c8damsarett// Build tables to transform src gamma to linear.
2111b93bd1e6eba3d14593490e4e24a34546638c8damsaretttemplate <typename T>
2121b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, int gammaTableSize,
2139488833428e83c93a7e6002f4d056084fb57112fraftias                               const SkColorSpace_XYZ* space, const GammaFns<T>& fns,
214f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                               bool gammasAreMatching)
2154be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarett{
2169488833428e83c93a7e6002f4d056084fb57112fraftias    switch (space->gammaNamed()) {
217600c737b64eae2c7379442ae2c852853cce3a278msarett        case kSRGB_SkGammaNamed:
2181b93bd1e6eba3d14593490e4e24a34546638c8damsarett            outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.fSRGBTable;
2191b93bd1e6eba3d14593490e4e24a34546638c8damsarett            break;
220600c737b64eae2c7379442ae2c852853cce3a278msarett        case k2Dot2Curve_SkGammaNamed:
2211b93bd1e6eba3d14593490e4e24a34546638c8damsarett            outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.f2Dot2Table;
2221b93bd1e6eba3d14593490e4e24a34546638c8damsarett            break;
223600c737b64eae2c7379442ae2c852853cce3a278msarett        case kLinear_SkGammaNamed:
2248bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = nullptr;
2251b93bd1e6eba3d14593490e4e24a34546638c8damsarett            break;
2261b93bd1e6eba3d14593490e4e24a34546638c8damsarett        default: {
2279488833428e83c93a7e6002f4d056084fb57112fraftias            const SkGammas* gammas = space->gammas();
2281b93bd1e6eba3d14593490e4e24a34546638c8damsarett            SkASSERT(gammas);
2291b93bd1e6eba3d14593490e4e24a34546638c8damsarett
2307bbda991af353fbe6b34132132d211d23a3dba8cmsarett            auto build_table = [=](int i) {
2311b93bd1e6eba3d14593490e4e24a34546638c8damsarett                if (gammas->isNamed(i)) {
2321b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    switch (gammas->data(i).fNamed) {
233600c737b64eae2c7379442ae2c852853cce3a278msarett                        case kSRGB_SkGammaNamed:
234a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary                            (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize],
235a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary                                                   gSRGB_TransferFn.fG,
236a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary                                                   gSRGB_TransferFn.fA,
237a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary                                                   gSRGB_TransferFn.fB,
238a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary                                                   gSRGB_TransferFn.fC,
239a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary                                                   gSRGB_TransferFn.fD,
240a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary                                                   gSRGB_TransferFn.fE,
241a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary                                                   gSRGB_TransferFn.fF);
24255bcc8e0af3415601b3d62252a0d579fbe87c85amsarett                            outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2431b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            break;
244600c737b64eae2c7379442ae2c852853cce3a278msarett                        case k2Dot2Curve_SkGammaNamed:
24555bcc8e0af3415601b3d62252a0d579fbe87c85amsarett                            (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 2.2f);
24655bcc8e0af3415601b3d62252a0d579fbe87c85amsarett                            outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2471b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            break;
248600c737b64eae2c7379442ae2c852853cce3a278msarett                        case kLinear_SkGammaNamed:
2491b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 1.0f);
2501b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2511b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            break;
2521b93bd1e6eba3d14593490e4e24a34546638c8damsarett                        default:
2531b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            SkASSERT(false);
2541b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            break;
2551b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    }
2561b93bd1e6eba3d14593490e4e24a34546638c8damsarett                } else if (gammas->isValue(i)) {
2571b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize],
2581b93bd1e6eba3d14593490e4e24a34546638c8damsarett                                           gammas->data(i).fValue);
2591b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2601b93bd1e6eba3d14593490e4e24a34546638c8damsarett                } else if (gammas->isTable(i)) {
2611b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    (*fns.fBuildFromTable)(&gammaTableStorage[i * gammaTableSize], gammas->table(i),
2621b93bd1e6eba3d14593490e4e24a34546638c8damsarett                                           gammas->data(i).fTable.fSize);
2631b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2641b93bd1e6eba3d14593490e4e24a34546638c8damsarett                } else {
2651b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    SkASSERT(gammas->isParametric(i));
266df44fc5f2bb282557df291e20dbd26c070533aa6Matt Sarett                    const SkColorSpaceTransferFn& params = gammas->params(i);
2671b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize], params.fG,
2681b93bd1e6eba3d14593490e4e24a34546638c8damsarett                                           params.fA, params.fB, params.fC, params.fD, params.fE,
2691b93bd1e6eba3d14593490e4e24a34546638c8damsarett                                           params.fF);
2701b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2711b93bd1e6eba3d14593490e4e24a34546638c8damsarett                }
2727bbda991af353fbe6b34132132d211d23a3dba8cmsarett            };
2737bbda991af353fbe6b34132132d211d23a3dba8cmsarett
2747bbda991af353fbe6b34132132d211d23a3dba8cmsarett            if (gammasAreMatching) {
2757bbda991af353fbe6b34132132d211d23a3dba8cmsarett                build_table(0);
2767bbda991af353fbe6b34132132d211d23a3dba8cmsarett                outGammaTables[1] = outGammaTables[0];
2777bbda991af353fbe6b34132132d211d23a3dba8cmsarett                outGammaTables[2] = outGammaTables[0];
2787bbda991af353fbe6b34132132d211d23a3dba8cmsarett            } else {
2797bbda991af353fbe6b34132132d211d23a3dba8cmsarett                build_table(0);
2807bbda991af353fbe6b34132132d211d23a3dba8cmsarett                build_table(1);
2817bbda991af353fbe6b34132132d211d23a3dba8cmsarett                build_table(2);
2821b93bd1e6eba3d14593490e4e24a34546638c8damsarett            }
2837bbda991af353fbe6b34132132d211d23a3dba8cmsarett
2847bbda991af353fbe6b34132132d211d23a3dba8cmsarett            break;
2851b93bd1e6eba3d14593490e4e24a34546638c8damsarett        }
2861b93bd1e6eba3d14593490e4e24a34546638c8damsarett    }
2871b93bd1e6eba3d14593490e4e24a34546638c8damsarett}
2881b93bd1e6eba3d14593490e4e24a34546638c8damsarett
289f489886915034093278353d06c6f1973b2e8b7d2Matt Sarettvoid SkColorSpaceXform_Base::BuildDstGammaTables(const uint8_t* dstGammaTables[3],
2909488833428e83c93a7e6002f4d056084fb57112fraftias                                                 uint8_t* dstStorage,
2919488833428e83c93a7e6002f4d056084fb57112fraftias                                                 const SkColorSpace_XYZ* space,
292f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                                                 bool gammasAreMatching) {
293f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett    build_gamma_tables(dstGammaTables, dstStorage, kDstGammaTableSize, space, kFromLinear,
294f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                       gammasAreMatching);
295f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett}
296f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett
2971b93bd1e6eba3d14593490e4e24a34546638c8damsarett///////////////////////////////////////////////////////////////////////////////////////////////////
2981b93bd1e6eba3d14593490e4e24a34546638c8damsarett
29998156c4592d98b7ee50dfb47bf64efe8660b14adMike Kleinstd::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* src,
30098156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein                                                          SkColorSpace* dst) {
30198156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    return SkColorSpaceXform_Base::New(src, dst, SkTransferFunctionBehavior::kRespect);
302cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett}
303cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett
30498156c4592d98b7ee50dfb47bf64efe8660b14adMike Kleinstd::unique_ptr<SkColorSpaceXform> SkColorSpaceXform_Base::New(
30598156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein        SkColorSpace* src,
30698156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein        SkColorSpace* dst,
30798156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein        SkTransferFunctionBehavior premulBehavior) {
308cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett
30998156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    if (!src || !dst) {
3106006f678e78af7b6f67a454cd4bc213048983f9dmsarett        // Invalid input
3116006f678e78af7b6f67a454cd4bc213048983f9dmsarett        return nullptr;
3126006f678e78af7b6f67a454cd4bc213048983f9dmsarett    }
3136006f678e78af7b6f67a454cd4bc213048983f9dmsarett
314333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein    if (!dst->toXYZD50()) {
315333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein        SkCSXformPrintf("only XYZ destinations supported\n");
3169488833428e83c93a7e6002f4d056084fb57112fraftias        return nullptr;
3179488833428e83c93a7e6002f4d056084fb57112fraftias    }
3189488833428e83c93a7e6002f4d056084fb57112fraftias
319333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein    if (src->toXYZD50()) {
320333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein        return skstd::make_unique<SkColorSpaceXform_XYZ>(static_cast<SkColorSpace_XYZ*>(src),
321333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein                                                         static_cast<SkColorSpace_XYZ*>(dst),
322333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein                                                         premulBehavior);
3236006f678e78af7b6f67a454cd4bc213048983f9dmsarett    }
324333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein    return skstd::make_unique<SkColorSpaceXform_A2B>(static_cast<SkColorSpace_A2B*>(src),
325333848272c4d023199e44ff38f2e6fc6876388e8Mike Klein                                                     static_cast<SkColorSpace_XYZ*>(dst));
3266006f678e78af7b6f67a454cd4bc213048983f9dmsarett}
3276006f678e78af7b6f67a454cd4bc213048983f9dmsarett
3286006f678e78af7b6f67a454cd4bc213048983f9dmsarett///////////////////////////////////////////////////////////////////////////////////////////////////
3296006f678e78af7b6f67a454cd4bc213048983f9dmsarett
330e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Kleinstatic inline int num_tables(SkColorSpace_XYZ* space) {
3319488833428e83c93a7e6002f4d056084fb57112fraftias    switch (space->gammaNamed()) {
3327bbda991af353fbe6b34132132d211d23a3dba8cmsarett        case kSRGB_SkGammaNamed:
3337bbda991af353fbe6b34132132d211d23a3dba8cmsarett        case k2Dot2Curve_SkGammaNamed:
3347bbda991af353fbe6b34132132d211d23a3dba8cmsarett        case kLinear_SkGammaNamed:
3357bbda991af353fbe6b34132132d211d23a3dba8cmsarett            return 0;
3367bbda991af353fbe6b34132132d211d23a3dba8cmsarett        default: {
3379488833428e83c93a7e6002f4d056084fb57112fraftias            const SkGammas* gammas = space->gammas();
3387bbda991af353fbe6b34132132d211d23a3dba8cmsarett            SkASSERT(gammas);
3397bbda991af353fbe6b34132132d211d23a3dba8cmsarett
3407bbda991af353fbe6b34132132d211d23a3dba8cmsarett            // It's likely that each component will have the same gamma.  In this case,
3417bbda991af353fbe6b34132132d211d23a3dba8cmsarett            // we only need to build one table.
34205d7416b371fe1db9faef5a3623e54e109977c2cMike Klein            return gammas->allChannelsSame() ? 1 : 3;
3437bbda991af353fbe6b34132132d211d23a3dba8cmsarett        }
3447bbda991af353fbe6b34132132d211d23a3dba8cmsarett    }
3457bbda991af353fbe6b34132132d211d23a3dba8cmsarett}
3467bbda991af353fbe6b34132132d211d23a3dba8cmsarett
34798156c4592d98b7ee50dfb47bf64efe8660b14adMike KleinSkColorSpaceXform_XYZ::SkColorSpaceXform_XYZ(SkColorSpace_XYZ* src,
34898156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein                                             SkColorSpace_XYZ* dst,
34998156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein                                             SkTransferFunctionBehavior premulBehavior)
350cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett    : fPremulBehavior(premulBehavior)
3513418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett{
35298156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    fColorSpacesAreIdentical = SkColorSpace::Equals(src, dst);
35398156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein
35498156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    SkMatrix44 srcToDst(SkMatrix44::kIdentity_Constructor);
35598156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    if (!fColorSpacesAreIdentical && *src->toXYZD50() != *dst->toXYZD50()) {
35698156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein        srcToDst.setConcat(*dst->fromXYZD50(), *src->toXYZD50());
35798156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    }
35898156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein
35926a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 0] = srcToDst.get(0, 0);
36026a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 1] = srcToDst.get(1, 0);
36126a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 2] = srcToDst.get(2, 0);
36226a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 3] = srcToDst.get(0, 1);
36326a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 4] = srcToDst.get(1, 1);
36426a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 5] = srcToDst.get(2, 1);
36526a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 6] = srcToDst.get(0, 2);
36626a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 7] = srcToDst.get(1, 2);
36726a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 8] = srcToDst.get(2, 2);
36826a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 9] = srcToDst.get(0, 3);
36926a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[10] = srcToDst.get(1, 3);
37026a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[11] = srcToDst.get(2, 3);
37198156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    fSrcToDstIsIdentity = srcToDst.isIdentity();
3727bbda991af353fbe6b34132132d211d23a3dba8cmsarett
37398156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    const int numSrcTables = num_tables(src);
374f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett    const size_t srcEntries = numSrcTables * 256;
3757bbda991af353fbe6b34132132d211d23a3dba8cmsarett    const bool srcGammasAreMatching = (1 >= numSrcTables);
376f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett    fSrcStorage.reset(srcEntries);
37798156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    build_gamma_tables(fSrcGammaTables, fSrcStorage.get(), 256, src, kToLinear,
378f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                       srcGammasAreMatching);
379f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett
38098156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    const int numDstTables = num_tables(dst);
38198156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    dst->toDstGammaTables(fDstGammaTables, &fDstStorage, numDstTables);
382379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett
38398156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    if (src->gammaIsLinear()) {
384379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        fSrcGamma = kLinear_SrcGamma;
38598156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    } else if (kSRGB_SkGammaNamed == src->gammaNamed()) {
386379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        fSrcGamma = kSRGB_SrcGamma;
387379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett    } else {
388379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        fSrcGamma = kTable_SrcGamma;
389379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett    }
390379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett
39198156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    switch (dst->gammaNamed()) {
392379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        case kSRGB_SkGammaNamed:
393379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            fDstGamma = kSRGB_DstGamma;
394379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            break;
395379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        case k2Dot2Curve_SkGammaNamed:
396379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            fDstGamma = k2Dot2_DstGamma;
397379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            break;
398379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        case kLinear_SkGammaNamed:
399379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            fDstGamma = kLinear_DstGamma;
400379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            break;
401379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        default:
402379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            fDstGamma = kTable_DstGamma;
403379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            break;
404379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett    }
4053418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett}
406dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett
4077bbda991af353fbe6b34132132d211d23a3dba8cmsarett
40898156c4592d98b7ee50dfb47bf64efe8660b14adMike Kleinbool SkColorSpaceXform_XYZ::onApply(ColorFormat dstColorFormat, void* dst,
40998156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein                                    ColorFormat srcColorFormat, const void* src,
41098156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein                                    int len, SkAlphaType alphaType) const {
41198156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    if (fColorSpacesAreIdentical && kPremul_SkAlphaType != alphaType) {
412e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein        if ((kRGBA_8888_ColorFormat == dstColorFormat &&
413e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein             kRGBA_8888_ColorFormat == srcColorFormat) ||
414e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein            (kBGRA_8888_ColorFormat == dstColorFormat &&
415e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein             kBGRA_8888_ColorFormat == srcColorFormat))
416e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein        {
417e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein            memcpy(dst, src, len * sizeof(uint32_t));
418e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein            return true;
41958564425e5acb5911cc3719f9c1e39190cc829b8Mike Klein        }
42026a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett
421e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein        if ((kRGBA_8888_ColorFormat == dstColorFormat &&
422e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein             kBGRA_8888_ColorFormat == srcColorFormat) ||
423e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein            (kBGRA_8888_ColorFormat == dstColorFormat &&
424e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein             kRGBA_8888_ColorFormat == srcColorFormat))
425e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein        {
426e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein            SkOpts::RGBA_to_BGRA((uint32_t*)dst, src, len);
427e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein            return true;
428e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein        }
4291f8796dbde0dd2cd146e051e88def2c1c23f5d9cMike Klein    }
4301f8796dbde0dd2cd146e051e88def2c1c23f5d9cMike Klein
431b24704d35f67f5b460be9c92794892e06adceb46Mike Klein    SkRasterPipeline_<256> pipeline;
432f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
43345c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein    SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
43445c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein                       dst_ctx = { (void*)dst, 0 };
43545c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein
43626a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    LoadTablesContext loadTables;
43726a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    switch (srcColorFormat) {
43826a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett        case kRGBA_8888_ColorFormat:
439379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            if (kLinear_SrcGamma == fSrcGamma) {
44045c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein                pipeline.append(SkRasterPipeline::load_8888, &src_ctx);
44126a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett            } else {
442379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                loadTables.fSrc = src;
44326a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett                loadTables.fR = fSrcGammaTables[0];
44426a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett                loadTables.fG = fSrcGammaTables[1];
44526a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett                loadTables.fB = fSrcGammaTables[2];
44626a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett                pipeline.append(SkRasterPipeline::load_tables, &loadTables);
447f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            }
448f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
44926a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett            break;
45026a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett        case kBGRA_8888_ColorFormat:
451379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            if (kLinear_SrcGamma == fSrcGamma) {
45245c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein                pipeline.append(SkRasterPipeline::load_bgra, &src_ctx);
45326a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett            } else {
454379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                loadTables.fSrc = src;
45526a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett                loadTables.fR = fSrcGammaTables[2];
45626a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett                loadTables.fG = fSrcGammaTables[1];
45726a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett                loadTables.fB = fSrcGammaTables[0];
45826a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett                pipeline.append(SkRasterPipeline::load_tables, &loadTables);
459c2d207603edbbd3809d5144fe4a048a2ad774910Mike Klein                pipeline.append(SkRasterPipeline::swap_rb);
460f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            }
461f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
46226a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett            break;
463b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman        case kRGBA_F16_ColorFormat:
464b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman            if (kLinear_SrcGamma != fSrcGamma) {
465b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman                return false;
466b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman            }
46745c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein            pipeline.append(SkRasterPipeline::load_f16, &src_ctx);
468b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman            break;
4694c55027dbf57d0701361b123e36b8fad46c341c3Matt Sarett        case kRGBA_F32_ColorFormat:
4704c55027dbf57d0701361b123e36b8fad46c341c3Matt Sarett            if (kLinear_SrcGamma != fSrcGamma) {
4714c55027dbf57d0701361b123e36b8fad46c341c3Matt Sarett                return false;
4724c55027dbf57d0701361b123e36b8fad46c341c3Matt Sarett            }
47345c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein            pipeline.append(SkRasterPipeline::load_f32, &src_ctx);
4744c55027dbf57d0701361b123e36b8fad46c341c3Matt Sarett            break;
475379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        case kRGBA_U16_BE_ColorFormat:
476379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            switch (fSrcGamma) {
477379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                case kLinear_SrcGamma:
47845c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein                    pipeline.append(SkRasterPipeline::load_u16_be, &src_ctx);
479379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                    break;
480379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                case kSRGB_SrcGamma:
48145c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein                    pipeline.append(SkRasterPipeline::load_u16_be, &src_ctx);
482f1f1162273b382db99f8609e5bbfff24f5594821Mike Klein                    pipeline.append(SkRasterPipeline::from_srgb);
483379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                    break;
484379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                case kTable_SrcGamma:
485379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                    loadTables.fSrc = src;
486379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                    loadTables.fR = fSrcGammaTables[0];
487379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                    loadTables.fG = fSrcGammaTables[1];
488379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                    loadTables.fB = fSrcGammaTables[2];
489379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                    pipeline.append(SkRasterPipeline::load_tables_u16_be, &loadTables);
490379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                    break;
491379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            }
492379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            break;
4935bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett        case kRGB_U16_BE_ColorFormat:
4945bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett            switch (fSrcGamma) {
4955bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                case kLinear_SrcGamma:
49645c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein                    pipeline.append(SkRasterPipeline::load_rgb_u16_be, &src_ctx);
4975bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                    break;
4985bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                case kSRGB_SrcGamma:
49945c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein                    pipeline.append(SkRasterPipeline::load_rgb_u16_be, &src_ctx);
500f1f1162273b382db99f8609e5bbfff24f5594821Mike Klein                    pipeline.append(SkRasterPipeline::from_srgb);
5015bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                    break;
5025bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                case kTable_SrcGamma:
5035bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                    loadTables.fSrc = src;
5045bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                    loadTables.fR = fSrcGammaTables[0];
5055bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                    loadTables.fG = fSrcGammaTables[1];
5065bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                    loadTables.fB = fSrcGammaTables[2];
5075bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                    pipeline.append(SkRasterPipeline::load_tables_rgb_u16_be, &loadTables);
5085bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                    break;
5095bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett            }
5105bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett            break;
5113725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett        default:
5123725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett            return false;
513f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
514f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
51598156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    if (!fSrcToDstIsIdentity) {
516f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        pipeline.append(SkRasterPipeline::matrix_3x4, fSrcToDst);
517f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
518eeb3cb1286c5ca8104da62fb36b07bb0fe04aee5Matt Sarett        if (kRGBA_F16_ColorFormat != dstColorFormat &&
519eeb3cb1286c5ca8104da62fb36b07bb0fe04aee5Matt Sarett            kRGBA_F32_ColorFormat != dstColorFormat)
5208f7a9a9bfb51a00082bde7eb6b04515b935a588fMatt Sarett        {
5215e15961fa77281540a80ac0d036fefe071c11574Mike Klein            bool need_clamp_0, need_clamp_1;
5225e15961fa77281540a80ac0d036fefe071c11574Mike Klein            analyze_3x4_matrix(fSrcToDst, &need_clamp_0, &need_clamp_1);
5235e15961fa77281540a80ac0d036fefe071c11574Mike Klein
5245e15961fa77281540a80ac0d036fefe071c11574Mike Klein            if (need_clamp_0) { pipeline.append(SkRasterPipeline::clamp_0); }
5255e15961fa77281540a80ac0d036fefe071c11574Mike Klein            if (need_clamp_1) { pipeline.append(SkRasterPipeline::clamp_1); }
5265e15961fa77281540a80ac0d036fefe071c11574Mike Klein        }
527f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
528f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
529cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett    if (kPremul_SkAlphaType == alphaType && SkTransferFunctionBehavior::kRespect == fPremulBehavior)
530cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett    {
531f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        pipeline.append(SkRasterPipeline::premul);
532f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
533f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
534e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett    TablesContext tables;
535a07e4302cfefc282d8d235edfbc20a54c75afa88Mike Klein    float to_2dot2 = 1/2.2f;
536379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett    switch (fDstGamma) {
537f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case kSRGB_DstGamma:
538f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            pipeline.append(SkRasterPipeline::to_srgb);
539f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
540f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case k2Dot2_DstGamma:
541a07e4302cfefc282d8d235edfbc20a54c75afa88Mike Klein            pipeline.append(SkRasterPipeline::gamma, &to_2dot2);
542f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
543e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett        case kTable_DstGamma:
544e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett            tables.fR = fDstGammaTables[0];
545e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett            tables.fG = fDstGammaTables[1];
546e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett            tables.fB = fDstGammaTables[2];
547e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett            tables.fCount = SkColorSpaceXform_Base::kDstGammaTableSize;
548e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett            pipeline.append(SkRasterPipeline::byte_tables_rgb, &tables);
549f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        default:
550f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
551f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
552f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
553cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett    if (kPremul_SkAlphaType == alphaType && SkTransferFunctionBehavior::kIgnore == fPremulBehavior)
554cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett    {
555e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett        pipeline.append(SkRasterPipeline::premul);
556e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett    }
557e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett
558f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    switch (dstColorFormat) {
559f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case kRGBA_8888_ColorFormat:
56045c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein             pipeline.append(SkRasterPipeline::store_8888, &dst_ctx);
561f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
562f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case kBGRA_8888_ColorFormat:
56345c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein            pipeline.append(SkRasterPipeline::store_bgra, &dst_ctx);
564f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
565f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case kRGBA_F16_ColorFormat:
566cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett            if (kLinear_DstGamma != fDstGamma) {
567f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                return false;
568f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            }
56945c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein            pipeline.append(SkRasterPipeline::store_f16, &dst_ctx);
570f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
571f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case kRGBA_F32_ColorFormat:
572cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett            if (kLinear_DstGamma != fDstGamma) {
573f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                return false;
574f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            }
57545c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein            pipeline.append(SkRasterPipeline::store_f32, &dst_ctx);
576f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
5773725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett        case kBGR_565_ColorFormat:
5783725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett            if (kOpaque_SkAlphaType != alphaType) {
5793725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett                return false;
5803725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett            }
58145c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein            pipeline.append(SkRasterPipeline::store_565, &dst_ctx);
5823725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett            break;
583379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        default:
584379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            return false;
585f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
58645c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein    pipeline.run(0,0, len,1);
587f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    return true;
588f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett}
589f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
5909488833428e83c93a7e6002f4d056084fb57112fraftiasstd::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace_XYZ* space) {
59198156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    auto xform = skstd::make_unique<SkColorSpaceXform_XYZ>(space, space,
59298156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein                                                           SkTransferFunctionBehavior::kRespect);
59398156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    xform->pretendNotToBeIdentityForTesting();
59498156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    return std::move(xform);
59598156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein}
59698156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein
59798156c4592d98b7ee50dfb47bf64efe8660b14adMike Kleinbool SkColorSpaceXform::apply(ColorFormat dstColorFormat, void* dst,
59898156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein                              ColorFormat srcColorFormat, const void* src,
59998156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein                              int len, SkAlphaType alphaType) const {
60098156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    return ((SkColorSpaceXform_Base*) this)->onApply(dstColorFormat, dst,
60198156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein                                                     srcColorFormat, src,
60298156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein                                                     len, alphaType);
60398156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein}
60498156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein
60598156c4592d98b7ee50dfb47bf64efe8660b14adMike Kleinbool SkColorSpaceXform::Apply(SkColorSpace* dstCS, ColorFormat dstFormat, void* dst,
60698156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein                              SkColorSpace* srcCS, ColorFormat srcFormat, const void* src,
60798156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein                              int len, AlphaOp op) {
60898156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    SkAlphaType at;
60998156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    switch (op) {
61098156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein        case kPreserve_AlphaOp:    at = kUnpremul_SkAlphaType; break;
61198156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein        case kPremul_AlphaOp:      at = kPremul_SkAlphaType;   break;
61298156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein        case kSrcIsOpaque_AlphaOp: at = kOpaque_SkAlphaType;   break;
61398156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    }
61498156c4592d98b7ee50dfb47bf64efe8660b14adMike Klein    return New(srcCS, dstCS)->apply(dstFormat, dst, srcFormat, src, len, at);
6159dc6cf6b8833d36c29a23d2519989b069745fcd5msarett}
616