SkColorSpaceXform.cpp revision c0444615ed76360f680619ad4d1f92cda6181a50
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 89876ac5b3016e5353c072378ac1545a0a2270757msarett#include "SkColorPriv.h" 99876ac5b3016e5353c072378ac1545a0a2270757msarett#include "SkColorSpace_Base.h" 10200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett#include "SkColorSpacePriv.h" 119876ac5b3016e5353c072378ac1545a0a2270757msarett#include "SkColorSpaceXform.h" 12200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett#include "SkHalf.h" 13200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett#include "SkOpts.h" 14ac41bac40f5a80d2bc5ccec584c23478a6900179mtklein#include "SkSRGB.h" 159876ac5b3016e5353c072378ac1545a0a2270757msarett 166006f678e78af7b6f67a454cd4bc213048983f9dmsarettstatic constexpr float sk_linear_from_2dot2[256] = { 17b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.000000000000000000f, 0.000005077051900662f, 0.000023328004666099f, 0.000056921765712193f, 18b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.000107187362341244f, 0.000175123977503027f, 0.000261543754548491f, 0.000367136269815943f, 19b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.000492503787191433f, 0.000638182842167022f, 0.000804658499513058f, 0.000992374304074325f, 20b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.001201739522438400f, 0.001433134589671860f, 0.001686915316789280f, 0.001963416213396470f, 21b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.002262953160706430f, 0.002585825596234170f, 0.002932318323938360f, 0.003302703032003640f, 22b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.003697239578900130f, 0.004116177093282750f, 0.004559754922526020f, 0.005028203456855540f, 23b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.005521744850239660f, 0.006040593654849810f, 0.006584957382581690f, 0.007155037004573030f, 24b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.007751027397660610f, 0.008373117745148580f, 0.009021491898012130f, 0.009696328701658230f, 25b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.010397802292555300f, 0.011126082368383200f, 0.011881334434813700f, 0.012663720031582100f, 26b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.013473396940142600f, 0.014310519374884100f, 0.015175238159625200f, 0.016067700890886900f, 27b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.016988052089250000f, 0.017936433339950200f, 0.018912983423721500f, 0.019917838438785700f, 28b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.020951131914781100f, 0.022012994919336500f, 0.023103556157921400f, 0.024222942067534200f, 29b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.025371276904734600f, 0.026548682828472900f, 0.027755279978126000f, 0.028991186547107800f, 30b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.030256518852388700f, 0.031551391400226400f, 0.032875916948383800f, 0.034230206565082000f, 31b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.035614369684918800f, 0.037028514161960200f, 0.038472746320194600f, 0.039947171001525600f, 32b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.041451891611462500f, 0.042987010162657100f, 0.044552627316421400f, 0.046148842422351000f, 33b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.047775753556170600f, 0.049433457555908000f, 0.051122050056493400f, 0.052841625522879000f, 34b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.054592277281760300f, 0.056374097551979800f, 0.058187177473685400f, 0.060031607136313200f, 35b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.061907475605455800f, 0.063814870948677200f, 0.065753880260330100f, 0.067724589685424300f, 36b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.069727084442598800f, 0.071761448846239100f, 0.073827766327784600f, 0.075926119456264800f, 37b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.078056589958101900f, 0.080219258736215100f, 0.082414205888459200f, 0.084641510725429500f, 38b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.086901251787660300f, 0.089193506862247800f, 0.091518352998919500f, 0.093875866525577800f, 39b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.096266123063339700f, 0.098689197541094500f, 0.101145164209600000f, 0.103634096655137000f, 40b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.106156067812744000f, 0.108711149979039000f, 0.111299414824660000f, 0.113920933406333000f, 41b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.116575776178572000f, 0.119264013005047000f, 0.121985713169619000f, 0.124740945387051000f, 42b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.127529777813422000f, 0.130352278056244000f, 0.133208513184300000f, 0.136098549737202000f, 43b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.139022453734703000f, 0.141980290685736000f, 0.144972125597231000f, 0.147998022982685000f, 44b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.151058046870511000f, 0.154152260812165000f, 0.157280727890073000f, 0.160443510725344000f, 45b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.163640671485290000f, 0.166872271890766000f, 0.170138373223312000f, 0.173439036332135000f, 46b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.176774321640903000f, 0.180144289154390000f, 0.183548998464951000f, 0.186988508758844000f, 47b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.190462878822409000f, 0.193972167048093000f, 0.197516431440340000f, 0.201095729621346000f, 48b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.204710118836677000f, 0.208359655960767000f, 0.212044397502288000f, 0.215764399609395000f, 49b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.219519718074868000f, 0.223310408341127000f, 0.227136525505149000f, 0.230998124323267000f, 50b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.234895259215880000f, 0.238827984272048000f, 0.242796353254002000f, 0.246800419601550000f, 51b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.250840236436400000f, 0.254915856566385000f, 0.259027332489606000f, 0.263174716398492000f, 52b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.267358060183772000f, 0.271577415438375000f, 0.275832833461245000f, 0.280124365261085000f, 53b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.284452061560024000f, 0.288815972797219000f, 0.293216149132375000f, 0.297652640449211000f, 54b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.302125496358853000f, 0.306634766203158000f, 0.311180499057984000f, 0.315762743736397000f, 55b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.320381548791810000f, 0.325036962521076000f, 0.329729032967515000f, 0.334457807923889000f, 56b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.339223334935327000f, 0.344025661302187000f, 0.348864834082879000f, 0.353740900096629000f, 57b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.358653905926199000f, 0.363603897920553000f, 0.368590922197487000f, 0.373615024646202000f, 58b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.378676250929840000f, 0.383774646487975000f, 0.388910256539059000f, 0.394083126082829000f, 59b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.399293299902674000f, 0.404540822567962000f, 0.409825738436323000f, 0.415148091655907000f, 60b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.420507926167587000f, 0.425905285707146000f, 0.431340213807410000f, 0.436812753800359000f, 61b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.442322948819202000f, 0.447870841800410000f, 0.453456475485731000f, 0.459079892424160000f, 62b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.464741134973889000f, 0.470440245304218000f, 0.476177265397440000f, 0.481952237050698000f, 63b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.487765201877811000f, 0.493616201311074000f, 0.499505276603030000f, 0.505432468828216000f, 64b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.511397818884880000f, 0.517401367496673000f, 0.523443155214325000f, 0.529523222417277000f, 65b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.535641609315311000f, 0.541798355950137000f, 0.547993502196972000f, 0.554227087766085000f, 66b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.560499152204328000f, 0.566809734896638000f, 0.573158875067523000f, 0.579546611782525000f, 67b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.585972983949661000f, 0.592438030320847000f, 0.598941789493296000f, 0.605484299910907000f, 68b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.612065599865624000f, 0.618685727498780000f, 0.625344720802427000f, 0.632042617620641000f, 69b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.638779455650817000f, 0.645555272444935000f, 0.652370105410821000f, 0.659223991813387000f, 70b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.666116968775851000f, 0.673049073280942000f, 0.680020342172095000f, 0.687030812154625000f, 71b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.694080519796882000f, 0.701169501531402000f, 0.708297793656032000f, 0.715465432335048000f, 72b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.722672453600255000f, 0.729918893352071000f, 0.737204787360605000f, 0.744530171266715000f, 73b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.751895080583051000f, 0.759299550695091000f, 0.766743616862161000f, 0.774227314218442000f, 74b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.781750677773962000f, 0.789313742415586000f, 0.796916542907978000f, 0.804559113894567000f, 75b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.812241489898490000f, 0.819963705323528000f, 0.827725794455034000f, 0.835527791460841000f, 76b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.843369730392169000f, 0.851251645184515000f, 0.859173569658532000f, 0.867135537520905000f, 77b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.875137582365205000f, 0.883179737672745000f, 0.891262036813419000f, 0.899384513046529000f, 78b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.907547199521614000f, 0.915750129279253000f, 0.923993335251873000f, 0.932276850264543000f, 79b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.940600707035753000f, 0.948964938178195000f, 0.957369576199527000f, 0.965814653503130000f, 80b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.974300202388861000f, 0.982826255053791000f, 0.991392843592940000f, 1.000000000000000000f, 81b39067696ad08a26bbe49b71a71f0546dc42a075msarett}; 82b39067696ad08a26bbe49b71a71f0546dc42a075msarett 836006f678e78af7b6f67a454cd4bc213048983f9dmsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 846006f678e78af7b6f67a454cd4bc213048983f9dmsarett 8515ee3deee8aca2bf6e658449f25ee34a8153e6eemsarettstatic void build_table_linear_from_gamma(float* outTable, float exponent) { 8615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { 8715ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett *outTable++ = powf(x, exponent); 8815ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett } 8915ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett} 9015ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett 9115ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett// Interpolating lookup in a variably sized table. 9215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarettstatic float interp_lut(float input, const float* table, int tableSize) { 9315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett float index = input * (tableSize - 1); 9415ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett float diff = index - sk_float_floor2int(index); 9515ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett return table[(int) sk_float_floor2int(index)] * (1.0f - diff) + 9615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett table[(int) sk_float_ceil2int(index)] * diff; 9715ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett} 9815ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett 9915ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett// outTable is always 256 entries, inTable may be larger or smaller. 10015ee3deee8aca2bf6e658449f25ee34a8153e6eemsarettstatic void build_table_linear_from_gamma(float* outTable, const float* inTable, 10115ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett int inTableSize) { 10215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett if (256 == inTableSize) { 10315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett memcpy(outTable, inTable, sizeof(float) * 256); 10415ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett return; 10515ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett } 10615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett 10715ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { 10815ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett *outTable++ = interp_lut(x, inTable, inTableSize); 10915ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett } 11015ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett} 11115ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett 11215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarettstatic void build_table_linear_from_gamma(float* outTable, float g, float a, float b, float c, 11315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett float d, float e, float f) { 11415ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett // Y = (aX + b)^g + c for X >= d 11515ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett // Y = eX + f otherwise 11615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { 11715ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett if (x >= d) { 11815ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett *outTable++ = powf(a * x + b, g) + c; 11915ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett } else { 12015ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett *outTable++ = e * x + f; 12115ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett } 12215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett } 12315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett} 12415ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett 12515ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 12615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett 127a9e878c836994bce695274b4c28890290139dcdfmsarett// Expand range from 0-1 to 0-255, then convert. 128b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic uint8_t clamp_normalized_float_to_byte(float v) { 129dea0340cadb759932e53416a657f5ea75fee8b5fmsarett // The ordering of the logic is a little strange here in order 130dea0340cadb759932e53416a657f5ea75fee8b5fmsarett // to make sure we convert NaNs to 0. 1319876ac5b3016e5353c072378ac1545a0a2270757msarett v = v * 255.0f; 132a9e878c836994bce695274b4c28890290139dcdfmsarett if (v >= 254.5f) { 1339876ac5b3016e5353c072378ac1545a0a2270757msarett return 255; 134dea0340cadb759932e53416a657f5ea75fee8b5fmsarett } else if (v >= 0.5f) { 1359876ac5b3016e5353c072378ac1545a0a2270757msarett return (uint8_t) (v + 0.5f); 136dea0340cadb759932e53416a657f5ea75fee8b5fmsarett } else { 137dea0340cadb759932e53416a657f5ea75fee8b5fmsarett return 0; 1389876ac5b3016e5353c072378ac1545a0a2270757msarett } 1399876ac5b3016e5353c072378ac1545a0a2270757msarett} 1409876ac5b3016e5353c072378ac1545a0a2270757msarett 1413418c0e797e2ee841d1c031ca9d7a5ba73205f51msarettstatic const int kDstGammaTableSize = 1428bbcd5aab81dc0742c3367479c0c9d97363b1203msarett SkColorSpaceXform_Base<kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch> 143200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett ::kDstGammaTableSize; 1443418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett 1451b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, float exponent) { 146b39067696ad08a26bbe49b71a71f0546dc42a075msarett float toGammaExp = 1.0f / exponent; 147b39067696ad08a26bbe49b71a71f0546dc42a075msarett 1483418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett for (int i = 0; i < kDstGammaTableSize; i++) { 1493418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett float x = ((float) i) * (1.0f / ((float) (kDstGammaTableSize - 1))); 150b39067696ad08a26bbe49b71a71f0546dc42a075msarett outTable[i] = clamp_normalized_float_to_byte(powf(x, toGammaExp)); 151b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 152dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett} 153dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 154dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett// Inverse table lookup. Ex: what index corresponds to the input value? This will 155dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett// have strange results when the table is non-increasing. But any sane gamma 156dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett// function will be increasing. 1571b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic float inverse_interp_lut(float input, const float* table, int tableSize) { 158dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett if (input <= table[0]) { 159dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett return table[0]; 160dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } else if (input >= table[tableSize - 1]) { 161dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett return 1.0f; 162dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } 163dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 164b39067696ad08a26bbe49b71a71f0546dc42a075msarett for (int i = 1; i < tableSize; i++) { 165dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett if (table[i] >= input) { 166dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett // We are guaranteed that input is greater than table[i - 1]. 167dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett float diff = input - table[i - 1]; 168dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett float distance = table[i] - table[i - 1]; 169dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett float index = (i - 1) + diff / distance; 170dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett return index / (tableSize - 1); 171dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } 172dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } 173dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 174dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett // Should be unreachable, since we'll return before the loop if input is 175dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett // larger than the last entry. 176dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett SkASSERT(false); 177dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett return 0.0f; 178dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett} 179dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 1801b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, const float* inTable, 181b39067696ad08a26bbe49b71a71f0546dc42a075msarett int inTableSize) { 1823418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett for (int i = 0; i < kDstGammaTableSize; i++) { 1833418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett float x = ((float) i) * (1.0f / ((float) (kDstGammaTableSize - 1))); 184b39067696ad08a26bbe49b71a71f0546dc42a075msarett float y = inverse_interp_lut(x, inTable, inTableSize); 185b39067696ad08a26bbe49b71a71f0546dc42a075msarett outTable[i] = clamp_normalized_float_to_byte(y); 186b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 187b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 188dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 189b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic float inverse_parametric(float x, float g, float a, float b, float c, float d, float e, 190b39067696ad08a26bbe49b71a71f0546dc42a075msarett float f) { 191b39067696ad08a26bbe49b71a71f0546dc42a075msarett // We need to take the inverse of the following piecewise function. 192b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Y = (aX + b)^g + c for X >= d 193b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Y = eX + f otherwise 194b39067696ad08a26bbe49b71a71f0546dc42a075msarett 195b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Assume that the gamma function is continuous, or this won't make much sense anyway. 196b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Plug in |d| to the first equation to calculate the new piecewise interval. 197b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Then simply use the inverse of the original functions. 198b39067696ad08a26bbe49b71a71f0546dc42a075msarett float interval = e * d + f; 199b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (x < interval) { 200b39067696ad08a26bbe49b71a71f0546dc42a075msarett // X = (Y - F) / E 201b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (0.0f == e) { 202b39067696ad08a26bbe49b71a71f0546dc42a075msarett // The gamma curve for this segment is constant, so the inverse is undefined. 203b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Since this is the lower segment, guess zero. 204b39067696ad08a26bbe49b71a71f0546dc42a075msarett return 0.0f; 205b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 206b39067696ad08a26bbe49b71a71f0546dc42a075msarett 207b39067696ad08a26bbe49b71a71f0546dc42a075msarett return (x - f) / e; 208b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 209b39067696ad08a26bbe49b71a71f0546dc42a075msarett 210b39067696ad08a26bbe49b71a71f0546dc42a075msarett // X = ((Y - C)^(1 / G) - B) / A 211b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (0.0f == a || 0.0f == g) { 212b39067696ad08a26bbe49b71a71f0546dc42a075msarett // The gamma curve for this segment is constant, so the inverse is undefined. 213b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Since this is the upper segment, guess one. 214b39067696ad08a26bbe49b71a71f0546dc42a075msarett return 1.0f; 215b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 216b39067696ad08a26bbe49b71a71f0546dc42a075msarett 217b39067696ad08a26bbe49b71a71f0546dc42a075msarett return (powf(x - c, 1.0f / g) - b) / a; 218b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 219b39067696ad08a26bbe49b71a71f0546dc42a075msarett 2201b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, float g, float a, 221b39067696ad08a26bbe49b71a71f0546dc42a075msarett float b, float c, float d, float e, float f) { 2223418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett for (int i = 0; i < kDstGammaTableSize; i++) { 2233418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett float x = ((float) i) * (1.0f / ((float) (kDstGammaTableSize - 1))); 224b39067696ad08a26bbe49b71a71f0546dc42a075msarett float y = inverse_parametric(x, g, a, b, c, d, e, f); 225b39067696ad08a26bbe49b71a71f0546dc42a075msarett outTable[i] = clamp_normalized_float_to_byte(y); 226b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 227b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 228b39067696ad08a26bbe49b71a71f0546dc42a075msarett 2296006f678e78af7b6f67a454cd4bc213048983f9dmsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 2306006f678e78af7b6f67a454cd4bc213048983f9dmsarett 2311b93bd1e6eba3d14593490e4e24a34546638c8damsaretttemplate <typename T> 2321b93bd1e6eba3d14593490e4e24a34546638c8damsarettstruct GammaFns { 2331b93bd1e6eba3d14593490e4e24a34546638c8damsarett const T* fSRGBTable; 2341b93bd1e6eba3d14593490e4e24a34546638c8damsarett const T* f2Dot2Table; 2351b93bd1e6eba3d14593490e4e24a34546638c8damsarett void (*fBuildFromValue)(T*, float); 2361b93bd1e6eba3d14593490e4e24a34546638c8damsarett void (*fBuildFromTable)(T*, const float*, int); 2371b93bd1e6eba3d14593490e4e24a34546638c8damsarett void (*fBuildFromParam)(T*, float, float, float, float, float, float, float); 2381b93bd1e6eba3d14593490e4e24a34546638c8damsarett}; 2391b93bd1e6eba3d14593490e4e24a34546638c8damsarett 2401b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic const GammaFns<float> kToLinear { 2411b93bd1e6eba3d14593490e4e24a34546638c8damsarett sk_linear_from_srgb, 2421b93bd1e6eba3d14593490e4e24a34546638c8damsarett sk_linear_from_2dot2, 2431b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_from_gamma, 2441b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_from_gamma, 2451b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_from_gamma, 2461b93bd1e6eba3d14593490e4e24a34546638c8damsarett}; 2471b93bd1e6eba3d14593490e4e24a34546638c8damsarett 2481b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic const GammaFns<uint8_t> kFromLinear { 24955bcc8e0af3415601b3d62252a0d579fbe87c85amsarett nullptr, 25055bcc8e0af3415601b3d62252a0d579fbe87c85amsarett nullptr, 2511b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_to_gamma, 2521b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_to_gamma, 2531b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_to_gamma, 2541b93bd1e6eba3d14593490e4e24a34546638c8damsarett}; 2551b93bd1e6eba3d14593490e4e24a34546638c8damsarett 2561b93bd1e6eba3d14593490e4e24a34546638c8damsarett// Build tables to transform src gamma to linear. 2571b93bd1e6eba3d14593490e4e24a34546638c8damsaretttemplate <typename T> 2581b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, int gammaTableSize, 2597bbda991af353fbe6b34132132d211d23a3dba8cmsarett const sk_sp<SkColorSpace>& space, const GammaFns<T>& fns, 2607bbda991af353fbe6b34132132d211d23a3dba8cmsarett bool gammasAreMatching) { 261600c737b64eae2c7379442ae2c852853cce3a278msarett switch (as_CSB(space)->gammaNamed()) { 262600c737b64eae2c7379442ae2c852853cce3a278msarett case kSRGB_SkGammaNamed: 2631b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.fSRGBTable; 2641b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 265600c737b64eae2c7379442ae2c852853cce3a278msarett case k2Dot2Curve_SkGammaNamed: 2661b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.f2Dot2Table; 2671b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 268600c737b64eae2c7379442ae2c852853cce3a278msarett case kLinear_SkGammaNamed: 2698bbcd5aab81dc0742c3367479c0c9d97363b1203msarett outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = nullptr; 2701b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 2711b93bd1e6eba3d14593490e4e24a34546638c8damsarett default: { 2721b93bd1e6eba3d14593490e4e24a34546638c8damsarett const SkGammas* gammas = as_CSB(space)->gammas(); 2731b93bd1e6eba3d14593490e4e24a34546638c8damsarett SkASSERT(gammas); 2741b93bd1e6eba3d14593490e4e24a34546638c8damsarett 2757bbda991af353fbe6b34132132d211d23a3dba8cmsarett auto build_table = [=](int i) { 2761b93bd1e6eba3d14593490e4e24a34546638c8damsarett if (gammas->isNamed(i)) { 2771b93bd1e6eba3d14593490e4e24a34546638c8damsarett switch (gammas->data(i).fNamed) { 278600c737b64eae2c7379442ae2c852853cce3a278msarett case kSRGB_SkGammaNamed: 27955bcc8e0af3415601b3d62252a0d579fbe87c85amsarett (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize], 2.4f, 28055bcc8e0af3415601b3d62252a0d579fbe87c85amsarett (1.0f / 1.055f), (0.055f / 1.055f), 0.0f, 28155bcc8e0af3415601b3d62252a0d579fbe87c85amsarett 0.04045f, (1.0f / 12.92f), 0.0f); 28255bcc8e0af3415601b3d62252a0d579fbe87c85amsarett outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; 2831b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 284600c737b64eae2c7379442ae2c852853cce3a278msarett case k2Dot2Curve_SkGammaNamed: 28555bcc8e0af3415601b3d62252a0d579fbe87c85amsarett (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 2.2f); 28655bcc8e0af3415601b3d62252a0d579fbe87c85amsarett outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; 2871b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 288600c737b64eae2c7379442ae2c852853cce3a278msarett case kLinear_SkGammaNamed: 2891b93bd1e6eba3d14593490e4e24a34546638c8damsarett (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 1.0f); 2901b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; 2911b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 2921b93bd1e6eba3d14593490e4e24a34546638c8damsarett default: 2931b93bd1e6eba3d14593490e4e24a34546638c8damsarett SkASSERT(false); 2941b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 2951b93bd1e6eba3d14593490e4e24a34546638c8damsarett } 2961b93bd1e6eba3d14593490e4e24a34546638c8damsarett } else if (gammas->isValue(i)) { 2971b93bd1e6eba3d14593490e4e24a34546638c8damsarett (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 2981b93bd1e6eba3d14593490e4e24a34546638c8damsarett gammas->data(i).fValue); 2991b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; 3001b93bd1e6eba3d14593490e4e24a34546638c8damsarett } else if (gammas->isTable(i)) { 3011b93bd1e6eba3d14593490e4e24a34546638c8damsarett (*fns.fBuildFromTable)(&gammaTableStorage[i * gammaTableSize], gammas->table(i), 3021b93bd1e6eba3d14593490e4e24a34546638c8damsarett gammas->data(i).fTable.fSize); 3031b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; 3041b93bd1e6eba3d14593490e4e24a34546638c8damsarett } else { 3051b93bd1e6eba3d14593490e4e24a34546638c8damsarett SkASSERT(gammas->isParametric(i)); 3061b93bd1e6eba3d14593490e4e24a34546638c8damsarett const SkGammas::Params& params = gammas->params(i); 3071b93bd1e6eba3d14593490e4e24a34546638c8damsarett (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize], params.fG, 3081b93bd1e6eba3d14593490e4e24a34546638c8damsarett params.fA, params.fB, params.fC, params.fD, params.fE, 3091b93bd1e6eba3d14593490e4e24a34546638c8damsarett params.fF); 3101b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; 3111b93bd1e6eba3d14593490e4e24a34546638c8damsarett } 3127bbda991af353fbe6b34132132d211d23a3dba8cmsarett }; 3137bbda991af353fbe6b34132132d211d23a3dba8cmsarett 3147bbda991af353fbe6b34132132d211d23a3dba8cmsarett if (gammasAreMatching) { 3157bbda991af353fbe6b34132132d211d23a3dba8cmsarett build_table(0); 3167bbda991af353fbe6b34132132d211d23a3dba8cmsarett outGammaTables[1] = outGammaTables[0]; 3177bbda991af353fbe6b34132132d211d23a3dba8cmsarett outGammaTables[2] = outGammaTables[0]; 3187bbda991af353fbe6b34132132d211d23a3dba8cmsarett } else { 3197bbda991af353fbe6b34132132d211d23a3dba8cmsarett build_table(0); 3207bbda991af353fbe6b34132132d211d23a3dba8cmsarett build_table(1); 3217bbda991af353fbe6b34132132d211d23a3dba8cmsarett build_table(2); 3221b93bd1e6eba3d14593490e4e24a34546638c8damsarett } 3237bbda991af353fbe6b34132132d211d23a3dba8cmsarett 3247bbda991af353fbe6b34132132d211d23a3dba8cmsarett break; 3251b93bd1e6eba3d14593490e4e24a34546638c8damsarett } 3261b93bd1e6eba3d14593490e4e24a34546638c8damsarett } 3271b93bd1e6eba3d14593490e4e24a34546638c8damsarett} 3281b93bd1e6eba3d14593490e4e24a34546638c8damsarett 3291b93bd1e6eba3d14593490e4e24a34546638c8damsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 3301b93bd1e6eba3d14593490e4e24a34546638c8damsarett 331200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline bool is_almost_identity(const SkMatrix44& srcToDst) { 332200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett for (int i = 0; i < 4; i++) { 333200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett for (int j = 0; j < 4; j++) { 334200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett float expected = (i == j) ? 1.0f : 0.0f; 335200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (!color_space_almost_equal(srcToDst.getFloat(i,j), expected)) { 336200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett return false; 337200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 338200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 339200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 340200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett return true; 341200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 342200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 34315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 34415ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett 3456006f678e78af7b6f67a454cd4bc213048983f9dmsarettstd::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(const sk_sp<SkColorSpace>& srcSpace, 3466006f678e78af7b6f67a454cd4bc213048983f9dmsarett const sk_sp<SkColorSpace>& dstSpace) { 3476006f678e78af7b6f67a454cd4bc213048983f9dmsarett if (!srcSpace || !dstSpace) { 3486006f678e78af7b6f67a454cd4bc213048983f9dmsarett // Invalid input 3496006f678e78af7b6f67a454cd4bc213048983f9dmsarett return nullptr; 3506006f678e78af7b6f67a454cd4bc213048983f9dmsarett } 3516006f678e78af7b6f67a454cd4bc213048983f9dmsarett 352200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett ColorSpaceMatch csm = kNone_ColorSpaceMatch; 3536006f678e78af7b6f67a454cd4bc213048983f9dmsarett SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor); 354200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (SkColorSpace::Equals(srcSpace.get(), dstSpace.get())) { 355200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcToDst.setIdentity(); 356200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett csm = kFull_ColorSpaceMatch; 357971cd496b9e25f87f3a75a0015c203322907136abrianosman } else { 358de68d6c4616d86621373d88100002ddfdb9c08e3brianosman srcToDst.setConcat(as_CSB(dstSpace)->fromXYZD50(), srcSpace->toXYZD50()); 359971cd496b9e25f87f3a75a0015c203322907136abrianosman 360971cd496b9e25f87f3a75a0015c203322907136abrianosman if (is_almost_identity(srcToDst)) { 361971cd496b9e25f87f3a75a0015c203322907136abrianosman srcToDst.setIdentity(); 362971cd496b9e25f87f3a75a0015c203322907136abrianosman csm = kGamut_ColorSpaceMatch; 363971cd496b9e25f87f3a75a0015c203322907136abrianosman } 3646006f678e78af7b6f67a454cd4bc213048983f9dmsarett } 3656006f678e78af7b6f67a454cd4bc213048983f9dmsarett 366200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett switch (csm) { 367200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett case kNone_ColorSpaceMatch: 368600c737b64eae2c7379442ae2c852853cce3a278msarett switch (as_CSB(dstSpace)->gammaNamed()) { 369600c737b64eae2c7379442ae2c852853cce3a278msarett case kSRGB_SkGammaNamed: 3708bbcd5aab81dc0742c3367479c0c9d97363b1203msarett if (srcSpace->gammaIsLinear()) { 3718bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 3728bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kLinear_SrcGamma, kSRGB_DstGamma, kNone_ColorSpaceMatch> 3738bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (srcSpace, srcToDst, dstSpace)); 3748bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } else { 3758bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 3768bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kTable_SrcGamma, kSRGB_DstGamma, kNone_ColorSpaceMatch> 3778bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (srcSpace, srcToDst, dstSpace)); 3788bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 379600c737b64eae2c7379442ae2c852853cce3a278msarett case k2Dot2Curve_SkGammaNamed: 3808bbcd5aab81dc0742c3367479c0c9d97363b1203msarett if (srcSpace->gammaIsLinear()) { 3818bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 3828bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kLinear_SrcGamma, k2Dot2_DstGamma, kNone_ColorSpaceMatch> 3838bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (srcSpace, srcToDst, dstSpace)); 3848bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } else { 3858bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 3868bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kTable_SrcGamma, k2Dot2_DstGamma, kNone_ColorSpaceMatch> 3878bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (srcSpace, srcToDst, dstSpace)); 3888bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 3898bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kLinear_SkGammaNamed: 3908bbcd5aab81dc0742c3367479c0c9d97363b1203msarett if (srcSpace->gammaIsLinear()) { 3918bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 3928bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kLinear_SrcGamma, kLinear_DstGamma, kNone_ColorSpaceMatch> 3938bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (srcSpace, srcToDst, dstSpace)); 3948bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } else { 3958bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 3968bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kTable_SrcGamma, kLinear_DstGamma, kNone_ColorSpaceMatch> 3978bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (srcSpace, srcToDst, dstSpace)); 3988bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 399200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett default: 4008bbcd5aab81dc0742c3367479c0c9d97363b1203msarett if (srcSpace->gammaIsLinear()) { 4018bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 4028bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kLinear_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch> 4038bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (srcSpace, srcToDst, dstSpace)); 4048bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } else { 4058bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 4068bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch> 4078bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (srcSpace, srcToDst, dstSpace)); 4088bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 409200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 410200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett case kGamut_ColorSpaceMatch: 411600c737b64eae2c7379442ae2c852853cce3a278msarett switch (as_CSB(dstSpace)->gammaNamed()) { 412600c737b64eae2c7379442ae2c852853cce3a278msarett case kSRGB_SkGammaNamed: 4138bbcd5aab81dc0742c3367479c0c9d97363b1203msarett if (srcSpace->gammaIsLinear()) { 4148bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 4158bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kLinear_SrcGamma, kSRGB_DstGamma, kGamut_ColorSpaceMatch> 4168bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (srcSpace, srcToDst, dstSpace)); 4178bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } else { 4188bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 4198bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kTable_SrcGamma, kSRGB_DstGamma, kGamut_ColorSpaceMatch> 4208bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (srcSpace, srcToDst, dstSpace)); 4218bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 422600c737b64eae2c7379442ae2c852853cce3a278msarett case k2Dot2Curve_SkGammaNamed: 4238bbcd5aab81dc0742c3367479c0c9d97363b1203msarett if (srcSpace->gammaIsLinear()) { 4248bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 4258bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kLinear_SrcGamma, k2Dot2_DstGamma, kGamut_ColorSpaceMatch> 4268bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (srcSpace, srcToDst, dstSpace)); 4278bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } else { 4288bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 4298bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kTable_SrcGamma, k2Dot2_DstGamma, kGamut_ColorSpaceMatch> 4308bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (srcSpace, srcToDst, dstSpace)); 4318bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 4328bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kLinear_SkGammaNamed: 4338bbcd5aab81dc0742c3367479c0c9d97363b1203msarett if (srcSpace->gammaIsLinear()) { 4348bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 4358bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kLinear_SrcGamma, kLinear_DstGamma, kGamut_ColorSpaceMatch> 4368bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (srcSpace, srcToDst, dstSpace)); 4378bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } else { 4388bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 4398bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kTable_SrcGamma, kLinear_DstGamma, kGamut_ColorSpaceMatch> 4408bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (srcSpace, srcToDst, dstSpace)); 4418bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 442200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett default: 4438bbcd5aab81dc0742c3367479c0c9d97363b1203msarett if (srcSpace->gammaIsLinear()) { 4448bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 4458bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kLinear_SrcGamma, kTable_DstGamma, kGamut_ColorSpaceMatch> 4468bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (srcSpace, srcToDst, dstSpace)); 4478bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } else { 4488bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 4498bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kTable_SrcGamma, kTable_DstGamma, kGamut_ColorSpaceMatch> 4508bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (srcSpace, srcToDst, dstSpace)); 4518bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 452200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 453200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett case kFull_ColorSpaceMatch: 454600c737b64eae2c7379442ae2c852853cce3a278msarett switch (as_CSB(dstSpace)->gammaNamed()) { 455600c737b64eae2c7379442ae2c852853cce3a278msarett case kSRGB_SkGammaNamed: 456200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 4578bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kTable_SrcGamma, kSRGB_DstGamma, kFull_ColorSpaceMatch> 458200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett (srcSpace, srcToDst, dstSpace)); 459600c737b64eae2c7379442ae2c852853cce3a278msarett case k2Dot2Curve_SkGammaNamed: 460200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 4618bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kTable_SrcGamma, k2Dot2_DstGamma, kFull_ColorSpaceMatch> 4628bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (srcSpace, srcToDst, dstSpace)); 4638bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kLinear_SkGammaNamed: 4648bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 4658bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kLinear_SrcGamma, kLinear_DstGamma, kFull_ColorSpaceMatch> 466200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett (srcSpace, srcToDst, dstSpace)); 467200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett default: 468200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 4698bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kTable_SrcGamma, kTable_DstGamma, kFull_ColorSpaceMatch> 470200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett (srcSpace, srcToDst, dstSpace)); 471200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 4723418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett default: 473200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett SkASSERT(false); 474200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett return nullptr; 4756006f678e78af7b6f67a454cd4bc213048983f9dmsarett } 4766006f678e78af7b6f67a454cd4bc213048983f9dmsarett} 4776006f678e78af7b6f67a454cd4bc213048983f9dmsarett 4786006f678e78af7b6f67a454cd4bc213048983f9dmsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 4796006f678e78af7b6f67a454cd4bc213048983f9dmsarett 4800f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarettstatic float byte_to_float(uint8_t byte) { 4810f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett return ((float) byte) * (1.0f / 255.0f); 4820f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett} 4830f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 484b39067696ad08a26bbe49b71a71f0546dc42a075msarett// Clamp to the 0-1 range. 485b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic float clamp_normalized_float(float v) { 486b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (v > 1.0f) { 487b39067696ad08a26bbe49b71a71f0546dc42a075msarett return 1.0f; 488b39067696ad08a26bbe49b71a71f0546dc42a075msarett } else if ((v < 0.0f) || (v != v)) { 489b39067696ad08a26bbe49b71a71f0546dc42a075msarett return 0.0f; 490b39067696ad08a26bbe49b71a71f0546dc42a075msarett } else { 491b39067696ad08a26bbe49b71a71f0546dc42a075msarett return v; 492b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 493b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 494b39067696ad08a26bbe49b71a71f0546dc42a075msarett 4950f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarettstatic void interp_3d_clut(float dst[3], float src[3], const SkColorLookUpTable* colorLUT) { 4960f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Call the src components x, y, and z. 4970f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett uint8_t maxX = colorLUT->fGridPoints[0] - 1; 4980f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett uint8_t maxY = colorLUT->fGridPoints[1] - 1; 4990f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett uint8_t maxZ = colorLUT->fGridPoints[2] - 1; 5000f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 5010f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // An approximate index into each of the three dimensions of the table. 5020f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float x = src[0] * maxX; 5030f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float y = src[1] * maxY; 5040f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float z = src[2] * maxZ; 5050f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 5060f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // This gives us the low index for our interpolation. 5070f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett int ix = sk_float_floor2int(x); 5080f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett int iy = sk_float_floor2int(y); 5090f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett int iz = sk_float_floor2int(z); 5100f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 5110f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Make sure the low index is not also the max index. 5120f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett ix = (maxX == ix) ? ix - 1 : ix; 5130f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett iy = (maxY == iy) ? iy - 1 : iy; 5140f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett iz = (maxZ == iz) ? iz - 1 : iz; 5150f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 5160f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Weighting factors for the interpolation. 5170f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float diffX = x - ix; 5180f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float diffY = y - iy; 5190f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float diffZ = z - iz; 5200f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 5210f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Constants to help us navigate the 3D table. 5220f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Ex: Assume x = a, y = b, z = c. 5230f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // table[a * n001 + b * n010 + c * n100] logically equals table[a][b][c]. 5240f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n000 = 0; 5250f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n001 = 3 * colorLUT->fGridPoints[1] * colorLUT->fGridPoints[2]; 5260f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n010 = 3 * colorLUT->fGridPoints[2]; 5270f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n011 = n001 + n010; 5280f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n100 = 3; 5290f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n101 = n100 + n001; 5300f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n110 = n100 + n010; 5310f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n111 = n110 + n001; 5320f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 5330f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Base ptr into the table. 534959d45b43357a40854938586c303177c6aa53220msarett const float* ptr = &(colorLUT->table()[ix*n001 + iy*n010 + iz*n100]); 5350f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 5360f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // The code below performs a tetrahedral interpolation for each of the three 5370f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // dst components. Once the tetrahedron containing the interpolation point is 5380f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // identified, the interpolation is a weighted sum of grid values at the 5390f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // vertices of the tetrahedron. The claim is that tetrahedral interpolation 5400f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // provides a more accurate color conversion. 5410f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // blogs.mathworks.com/steve/2006/11/24/tetrahedral-interpolation-for-colorspace-conversion/ 5420f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // 5430f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // I have one test image, and visually I can't tell the difference between 5440f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // tetrahedral and trilinear interpolation. In terms of computation, the 5450f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // tetrahedral code requires more branches but less computation. The 5460f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // SampleICC library provides an option for the client to choose either 5470f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // tetrahedral or trilinear. 5480f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett for (int i = 0; i < 3; i++) { 5490f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett if (diffZ < diffY) { 5500f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett if (diffZ < diffX) { 5510f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n110] - ptr[n010]) + 5520f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n010] - ptr[n000]) + 5530f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n111] - ptr[n110])); 5540f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } else if (diffY < diffX) { 5550f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n111] - ptr[n011]) + 5560f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n011] - ptr[n001]) + 5570f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n001] - ptr[n000])); 5580f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } else { 5590f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n111] - ptr[n011]) + 5600f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n010] - ptr[n000]) + 5610f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n011] - ptr[n010])); 5620f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } 5630f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } else { 5640f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett if (diffZ < diffX) { 5650f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n101] - ptr[n001]) + 5660f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n111] - ptr[n101]) + 5670f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n001] - ptr[n000])); 5680f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } else if (diffY < diffX) { 5690f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n100] - ptr[n000]) + 5700f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n111] - ptr[n101]) + 5710f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n101] - ptr[n100])); 5720f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } else { 5730f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n100] - ptr[n000]) + 5740f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n110] - ptr[n100]) + 5750f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n111] - ptr[n110])); 5760f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } 5770f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } 5780f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 5790f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Increment the table ptr in order to handle the next component. 5800f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Note that this is the how table is designed: all of nXXX 5810f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // variables are multiples of 3 because there are 3 output 5820f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // components. 5830f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett ptr++; 5840f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } 5850f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett} 5860f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 5873418c0e797e2ee841d1c031ca9d7a5ba73205f51msarettstatic void handle_color_lut(uint32_t* dst, const uint32_t* src, int len, 5883418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett SkColorLookUpTable* colorLUT) { 589b39067696ad08a26bbe49b71a71f0546dc42a075msarett while (len-- > 0) { 5900f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett uint8_t r = (*src >> 0) & 0xFF, 5910f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett g = (*src >> 8) & 0xFF, 5920f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett b = (*src >> 16) & 0xFF; 5930f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 5943418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett float in[3]; 5953418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett float out[3]; 5963418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett in[0] = byte_to_float(r); 5973418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett in[1] = byte_to_float(g); 5983418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett in[2] = byte_to_float(b); 5993418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett interp_3d_clut(out, in, colorLUT); 6000f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6013418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett r = sk_float_round2int(255.0f * clamp_normalized_float(out[0])); 6023418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett g = sk_float_round2int(255.0f * clamp_normalized_float(out[1])); 6033418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett b = sk_float_round2int(255.0f * clamp_normalized_float(out[2])); 6043418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett *dst = SkPackARGB_as_RGBA(0xFF, r, g, b); 6050f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6063418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett src++; 6073418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett dst++; 6083418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett } 6093418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett} 6100f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 611200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void load_matrix(const float matrix[16], 612200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& rXgXbX, Sk4f& rYgYbY, Sk4f& rZgZbZ, Sk4f& rTgTbT) { 613200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rXgXbX = Sk4f::Load(matrix + 0); 614200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rYgYbY = Sk4f::Load(matrix + 4); 615200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rZgZbZ = Sk4f::Load(matrix + 8); 616200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rTgTbT = Sk4f::Load(matrix + 12); 617200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 618200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 619200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void load_rgb_from_tables(const uint32_t* src, 620200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, 621200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett const float* const srcTables[3]) { 622200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett r = { srcTables[0][(src[0] >> 0) & 0xFF], 623200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[0][(src[1] >> 0) & 0xFF], 624200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[0][(src[2] >> 0) & 0xFF], 625200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[0][(src[3] >> 0) & 0xFF], }; 626200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett g = { srcTables[1][(src[0] >> 8) & 0xFF], 627200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[1][(src[1] >> 8) & 0xFF], 628200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[1][(src[2] >> 8) & 0xFF], 629200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[1][(src[3] >> 8) & 0xFF], }; 630200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett b = { srcTables[2][(src[0] >> 16) & 0xFF], 631200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[2][(src[1] >> 16) & 0xFF], 632200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[2][(src[2] >> 16) & 0xFF], 633200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[2][(src[3] >> 16) & 0xFF], }; 634200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett a = 0.0f; // Don't let the compiler complain that |a| is uninitialized. 635200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 636200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 637200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void load_rgba_from_tables(const uint32_t* src, 638200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, 639200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett const float* const srcTables[3]) { 640200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett r = { srcTables[0][(src[0] >> 0) & 0xFF], 641200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[0][(src[1] >> 0) & 0xFF], 642200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[0][(src[2] >> 0) & 0xFF], 643200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[0][(src[3] >> 0) & 0xFF], }; 644200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett g = { srcTables[1][(src[0] >> 8) & 0xFF], 645200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[1][(src[1] >> 8) & 0xFF], 646200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[1][(src[2] >> 8) & 0xFF], 647200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[1][(src[3] >> 8) & 0xFF], }; 648200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett b = { srcTables[2][(src[0] >> 16) & 0xFF], 649200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[2][(src[1] >> 16) & 0xFF], 650200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[2][(src[2] >> 16) & 0xFF], 651200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcTables[2][(src[3] >> 16) & 0xFF], }; 652200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett a = (1.0f / 255.0f) * SkNx_cast<float>(Sk4u::Load(src) >> 24); 653200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 654200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 6558bbcd5aab81dc0742c3367479c0c9d97363b1203msarettstatic inline void load_rgb_linear(const uint32_t* src, 656be362774f9b9e8964544a579281603ed995e6e5amsarett Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, 6578bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const float* const[3]) { 6588bbcd5aab81dc0742c3367479c0c9d97363b1203msarett r = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) ) & 0xFF); 6598bbcd5aab81dc0742c3367479c0c9d97363b1203msarett g = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> 8) & 0xFF); 6608bbcd5aab81dc0742c3367479c0c9d97363b1203msarett b = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> 16) & 0xFF); 661be362774f9b9e8964544a579281603ed995e6e5amsarett a = 0.0f; // Don't let the compiler complain that |a| is uninitialized. 6628bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 6638bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 6648bbcd5aab81dc0742c3367479c0c9d97363b1203msarettstatic inline void load_rgba_linear(const uint32_t* src, 6658bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, 6668bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const float* const[3]) { 6678bbcd5aab81dc0742c3367479c0c9d97363b1203msarett r = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) ) & 0xFF); 6688bbcd5aab81dc0742c3367479c0c9d97363b1203msarett g = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> 8) & 0xFF); 6698bbcd5aab81dc0742c3367479c0c9d97363b1203msarett b = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> 16) & 0xFF); 6708bbcd5aab81dc0742c3367479c0c9d97363b1203msarett a = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> 24) ); 6718bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 6728bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 673200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void load_rgb_from_tables_1(const uint32_t* src, 674200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& r, Sk4f& g, Sk4f& b, Sk4f&, 675200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett const float* const srcTables[3]) { 676200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett // Splat r,g,b across a register each. 677200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett r = Sk4f(srcTables[0][(*src >> 0) & 0xFF]); 678200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett g = Sk4f(srcTables[1][(*src >> 8) & 0xFF]); 679200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett b = Sk4f(srcTables[2][(*src >> 16) & 0xFF]); 680200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 681200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 682200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void load_rgba_from_tables_1(const uint32_t* src, 683200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, 684200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett const float* const srcTables[3]) { 685200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett // Splat r,g,b across a register each. 686200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett r = Sk4f(srcTables[0][(*src >> 0) & 0xFF]); 687200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett g = Sk4f(srcTables[1][(*src >> 8) & 0xFF]); 688200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett b = Sk4f(srcTables[2][(*src >> 16) & 0xFF]); 689200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett a = (1.0f / 255.0f) * Sk4f(*src >> 24); 690200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 691200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 6928bbcd5aab81dc0742c3367479c0c9d97363b1203msarettstatic inline void load_rgb_linear_1(const uint32_t* src, 6938bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Sk4f& r, Sk4f& g, Sk4f& b, Sk4f&, 6948bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const float* const srcTables[3]) { 6958bbcd5aab81dc0742c3367479c0c9d97363b1203msarett // Splat r,g,b across a register each. 6968bbcd5aab81dc0742c3367479c0c9d97363b1203msarett r = Sk4f((1.0f / 255.0f) * ((*src ) & 0xFF)); 6978bbcd5aab81dc0742c3367479c0c9d97363b1203msarett g = Sk4f((1.0f / 255.0f) * ((*src >> 8) & 0xFF)); 6988bbcd5aab81dc0742c3367479c0c9d97363b1203msarett b = Sk4f((1.0f / 255.0f) * ((*src >> 16) & 0xFF)); 6998bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 7008bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 7018bbcd5aab81dc0742c3367479c0c9d97363b1203msarettstatic inline void load_rgba_linear_1(const uint32_t* src, 7028bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, 7038bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const float* const srcTables[3]) { 7048bbcd5aab81dc0742c3367479c0c9d97363b1203msarett // Splat r,g,b,a across a register each. 7058bbcd5aab81dc0742c3367479c0c9d97363b1203msarett r = Sk4f((1.0f / 255.0f) * ((*src ) & 0xFF)); 7068bbcd5aab81dc0742c3367479c0c9d97363b1203msarett g = Sk4f((1.0f / 255.0f) * ((*src >> 8) & 0xFF)); 7078bbcd5aab81dc0742c3367479c0c9d97363b1203msarett b = Sk4f((1.0f / 255.0f) * ((*src >> 16) & 0xFF)); 7088bbcd5aab81dc0742c3367479c0c9d97363b1203msarett a = Sk4f((1.0f / 255.0f) * ((*src >> 24) )); 7098bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 7108bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 711200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void transform_gamut(const Sk4f& r, const Sk4f& g, const Sk4f& b, const Sk4f& a, 712200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett const Sk4f& rXgXbX, const Sk4f& rYgYbY, const Sk4f& rZgZbZ, 713200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f& da) { 714200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = rXgXbX[0]*r + rYgYbY[0]*g + rZgZbZ[0]*b; 715200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = rXgXbX[1]*r + rYgYbY[1]*g + rZgZbZ[1]*b; 716200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = rXgXbX[2]*r + rYgYbY[2]*g + rZgZbZ[2]*b; 717200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett da = a; 718200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 719200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 720200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void transform_gamut_1(const Sk4f& r, const Sk4f& g, const Sk4f& b, 721200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett const Sk4f& rXgXbX, const Sk4f& rYgYbY, const Sk4f& rZgZbZ, 722200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& rgba) { 723200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba = rXgXbX*r + rYgYbY*g + rZgZbZ*b; 724200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 725200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 726200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void translate_gamut(const Sk4f& rTgTbT, Sk4f& dr, Sk4f& dg, Sk4f& db) { 727200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = dr + rTgTbT[0]; 728200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = dg + rTgTbT[1]; 729200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = db + rTgTbT[2]; 730200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 731200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 732200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void translate_gamut_1(const Sk4f& rTgTbT, Sk4f& rgba) { 733200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba = rgba + rTgTbT; 734200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 735200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 736200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void premultiply(Sk4f& dr, Sk4f& dg, Sk4f& db, const Sk4f& da) { 737200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = da * dr; 738200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = da * dg; 739200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = da * db; 740200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 741200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 742200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void premultiply_1(const Sk4f& a, Sk4f& rgba) { 743200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba = a * rgba; 744200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 745200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 7468bbcd5aab81dc0742c3367479c0c9d97363b1203msarettenum SwapRB { 7478bbcd5aab81dc0742c3367479c0c9d97363b1203msarett kNo_SwapRB, 7488bbcd5aab81dc0742c3367479c0c9d97363b1203msarett kYes_SwapRB, 7498bbcd5aab81dc0742c3367479c0c9d97363b1203msarett}; 7508bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 7518bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SwapRB kSwapRB> 752200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_srgb(void* dst, const uint32_t* src, 753200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, 7548bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 755200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett int kRShift = 0; 756200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett int kGShift = 8; 757200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett int kBShift = 16; 758200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kYes_SwapRB == kSwapRB) { 759200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett kBShift = 0; 760200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett kRShift = 16; 761200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 762200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 763200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = sk_linear_to_srgb_needs_trunc(dr); 764200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = sk_linear_to_srgb_needs_trunc(dg); 765200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = sk_linear_to_srgb_needs_trunc(db); 766200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 767200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = sk_clamp_0_255(dr); 768200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = sk_clamp_0_255(dg); 769200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = sk_clamp_0_255(db); 770200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 771200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i da = Sk4i::Load(src) & 0xFF000000; 772200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 773200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i rgba = (SkNx_cast<int>(dr) << kRShift) 774200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | (SkNx_cast<int>(dg) << kGShift) 775200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | (SkNx_cast<int>(db) << kBShift) 776200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | (da ); 777200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba.store(dst); 778200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 779200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 7808bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SwapRB kSwapRB> 781200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_srgb_1(void* dst, const uint32_t* src, 782200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& rgba, const Sk4f&, 7838bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 784200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba = sk_clamp_0_255(sk_linear_to_srgb_needs_trunc(rgba)); 785200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 786200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett uint32_t tmp; 787200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett SkNx_cast<uint8_t>(SkNx_cast<int32_t>(rgba)).store(&tmp); 788200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett tmp = (*src & 0xFF000000) | (tmp & 0x00FFFFFF); 789200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kYes_SwapRB == kSwapRB) { 790200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett tmp = SkSwizzle_RB(tmp); 791200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 792200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 793200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett *(uint32_t*)dst = tmp; 794200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 795200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 796200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline Sk4f linear_to_2dot2(const Sk4f& x) { 797200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett // x^(29/64) is a very good approximation of the true value, x^(1/2.2). 798200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett auto x2 = x.rsqrt(), // x^(-1/2) 799200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett x32 = x2.rsqrt().rsqrt().rsqrt().rsqrt(), // x^(-1/32) 800200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett x64 = x32.rsqrt(); // x^(+1/64) 801200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 802200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett // 29 = 32 - 2 - 1 803200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett return 255.0f * x2.invert() * x32 * x64.invert(); 804200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 805200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 8068bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SwapRB kSwapRB> 807200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_2dot2(void* dst, const uint32_t* src, 808200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, 8098bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 810200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett int kRShift = 0; 811200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett int kGShift = 8; 812200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett int kBShift = 16; 813200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kYes_SwapRB == kSwapRB) { 814200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett kBShift = 0; 815200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett kRShift = 16; 816200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 817200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 818200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = linear_to_2dot2(dr); 819200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = linear_to_2dot2(dg); 820200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = linear_to_2dot2(db); 821200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 822200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = sk_clamp_0_255(dr); 823200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = sk_clamp_0_255(dg); 824200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = sk_clamp_0_255(db); 825200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 826200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i da = Sk4i::Load(src) & 0xFF000000; 827200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 828200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i rgba = (Sk4f_round(dr) << kRShift) 829200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | (Sk4f_round(dg) << kGShift) 830200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | (Sk4f_round(db) << kBShift) 831200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | (da ); 832200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba.store(dst); 833200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 834200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 8358bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SwapRB kSwapRB> 836200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_2dot2_1(void* dst, const uint32_t* src, 837200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& rgba, const Sk4f&, 8388bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 839200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba = sk_clamp_0_255(linear_to_2dot2(rgba)); 840200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 841200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett uint32_t tmp; 842200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett SkNx_cast<uint8_t>(Sk4f_round(rgba)).store(&tmp); 843200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett tmp = (*src & 0xFF000000) | (tmp & 0x00FFFFFF); 844200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kYes_SwapRB == kSwapRB) { 845200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett tmp = SkSwizzle_RB(tmp); 846200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 847200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 848200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett *(uint32_t*)dst = tmp; 849200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 850200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 8518bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SwapRB kSwapRB> 8528bbcd5aab81dc0742c3367479c0c9d97363b1203msarettstatic inline void store_linear(void* dst, const uint32_t* src, 8538bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, 8548bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 8558bbcd5aab81dc0742c3367479c0c9d97363b1203msarett int kRShift = 0; 8568bbcd5aab81dc0742c3367479c0c9d97363b1203msarett int kGShift = 8; 8578bbcd5aab81dc0742c3367479c0c9d97363b1203msarett int kBShift = 16; 8588bbcd5aab81dc0742c3367479c0c9d97363b1203msarett if (kYes_SwapRB == kSwapRB) { 8598bbcd5aab81dc0742c3367479c0c9d97363b1203msarett kBShift = 0; 8608bbcd5aab81dc0742c3367479c0c9d97363b1203msarett kRShift = 16; 8618bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 8628bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 863591971d02a8e22dac0955c0f07b7cf500a89d5ccmsarett dr = sk_clamp_0_255(255.0f * dr); 864591971d02a8e22dac0955c0f07b7cf500a89d5ccmsarett dg = sk_clamp_0_255(255.0f * dg); 865591971d02a8e22dac0955c0f07b7cf500a89d5ccmsarett db = sk_clamp_0_255(255.0f * db); 8668bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 8678bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Sk4i da = Sk4i::Load(src) & 0xFF000000; 8688bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 8698bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Sk4i rgba = (Sk4f_round(dr) << kRShift) 8708bbcd5aab81dc0742c3367479c0c9d97363b1203msarett | (Sk4f_round(dg) << kGShift) 8718bbcd5aab81dc0742c3367479c0c9d97363b1203msarett | (Sk4f_round(db) << kBShift) 8728bbcd5aab81dc0742c3367479c0c9d97363b1203msarett | (da ); 8738bbcd5aab81dc0742c3367479c0c9d97363b1203msarett rgba.store(dst); 8748bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 8758bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 8768bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SwapRB kSwapRB> 8778bbcd5aab81dc0742c3367479c0c9d97363b1203msarettstatic inline void store_linear_1(void* dst, const uint32_t* src, 8788bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Sk4f& rgba, const Sk4f&, 8798bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 880591971d02a8e22dac0955c0f07b7cf500a89d5ccmsarett rgba = sk_clamp_0_255(255.0f * rgba); 8818bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 8828bbcd5aab81dc0742c3367479c0c9d97363b1203msarett uint32_t tmp; 8838bbcd5aab81dc0742c3367479c0c9d97363b1203msarett SkNx_cast<uint8_t>(Sk4f_round(rgba)).store(&tmp); 8848bbcd5aab81dc0742c3367479c0c9d97363b1203msarett tmp = (*src & 0xFF000000) | (tmp & 0x00FFFFFF); 8858bbcd5aab81dc0742c3367479c0c9d97363b1203msarett if (kYes_SwapRB == kSwapRB) { 8868bbcd5aab81dc0742c3367479c0c9d97363b1203msarett tmp = SkSwizzle_RB(tmp); 8878bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 8888bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 8898bbcd5aab81dc0742c3367479c0c9d97363b1203msarett *(uint32_t*)dst = tmp; 8908bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 8918bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 8928bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SwapRB kSwapRB> 893200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_f16(void* dst, const uint32_t* src, 894200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f& da, 8958bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 8968ae991e433d2c0814ea5579613f00173805ff057mtklein Sk4h_store4(dst, SkFloatToHalf_finite_ftz(dr), 8978ae991e433d2c0814ea5579613f00173805ff057mtklein SkFloatToHalf_finite_ftz(dg), 8988ae991e433d2c0814ea5579613f00173805ff057mtklein SkFloatToHalf_finite_ftz(db), 8998ae991e433d2c0814ea5579613f00173805ff057mtklein SkFloatToHalf_finite_ftz(da)); 900200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 901200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 9028bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SwapRB kSwapRB> 903200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_f16_1(void* dst, const uint32_t* src, 904200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& rgba, const Sk4f& a, 9058bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 906200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba = Sk4f(rgba[0], rgba[1], rgba[2], a[3]); 9078ae991e433d2c0814ea5579613f00173805ff057mtklein SkFloatToHalf_finite_ftz(rgba).store((uint64_t*) dst); 908200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 909200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 9108bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SwapRB kSwapRB> 911c0444615ed76360f680619ad4d1f92cda6181a50msarettstatic inline void store_f32(void* dst, const uint32_t* src, 912c0444615ed76360f680619ad4d1f92cda6181a50msarett Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f& da, 913c0444615ed76360f680619ad4d1f92cda6181a50msarett const uint8_t* const[3]) { 914c0444615ed76360f680619ad4d1f92cda6181a50msarett Sk4f_store4(dst, dr, dg, db, da); 915c0444615ed76360f680619ad4d1f92cda6181a50msarett} 916c0444615ed76360f680619ad4d1f92cda6181a50msarett 917c0444615ed76360f680619ad4d1f92cda6181a50msaretttemplate <SwapRB kSwapRB> 918c0444615ed76360f680619ad4d1f92cda6181a50msarettstatic inline void store_f32_1(void* dst, const uint32_t* src, 919c0444615ed76360f680619ad4d1f92cda6181a50msarett Sk4f& rgba, const Sk4f& a, 920c0444615ed76360f680619ad4d1f92cda6181a50msarett const uint8_t* const[3]) { 921c0444615ed76360f680619ad4d1f92cda6181a50msarett rgba = Sk4f(rgba[0], rgba[1], rgba[2], a[3]); 922c0444615ed76360f680619ad4d1f92cda6181a50msarett rgba.store((float*) dst); 923c0444615ed76360f680619ad4d1f92cda6181a50msarett} 924c0444615ed76360f680619ad4d1f92cda6181a50msarett 925c0444615ed76360f680619ad4d1f92cda6181a50msaretttemplate <SwapRB kSwapRB> 926200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_f16_opaque(void* dst, const uint32_t* src, 927c0444615ed76360f680619ad4d1f92cda6181a50msarett Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, 9288bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 9298ae991e433d2c0814ea5579613f00173805ff057mtklein Sk4h_store4(dst, SkFloatToHalf_finite_ftz(dr), 9308ae991e433d2c0814ea5579613f00173805ff057mtklein SkFloatToHalf_finite_ftz(dg), 9318ae991e433d2c0814ea5579613f00173805ff057mtklein SkFloatToHalf_finite_ftz(db), 932200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett SK_Half1); 933200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 934200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 9358bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SwapRB kSwapRB> 936200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_f16_1_opaque(void* dst, const uint32_t* src, 937c0444615ed76360f680619ad4d1f92cda6181a50msarett Sk4f& rgba, const Sk4f&, 9388bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 939200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett uint64_t tmp; 9408ae991e433d2c0814ea5579613f00173805ff057mtklein SkFloatToHalf_finite_ftz(rgba).store(&tmp); 941200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett tmp |= static_cast<uint64_t>(SK_Half1) << 48; 942200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett *((uint64_t*) dst) = tmp; 943200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 944200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 9458bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SwapRB kSwapRB> 946200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_generic(void* dst, const uint32_t* src, 947200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, 9488bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const dstTables[3]) { 949200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett int kRShift = 0; 950200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett int kGShift = 8; 951200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett int kBShift = 16; 952200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kYes_SwapRB == kSwapRB) { 953200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett kBShift = 0; 954200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett kRShift = 16; 955200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 956200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 957200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = Sk4f::Min(Sk4f::Max(1023.0f * dr, 0.0f), 1023.0f); 958200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = Sk4f::Min(Sk4f::Max(1023.0f * dg, 0.0f), 1023.0f); 959200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = Sk4f::Min(Sk4f::Max(1023.0f * db, 0.0f), 1023.0f); 960200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 961200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i ir = Sk4f_round(dr); 962200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i ig = Sk4f_round(dg); 963200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i ib = Sk4f_round(db); 964200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 965200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i da = Sk4i::Load(src) & 0xFF000000; 966200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 967200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett uint32_t* dst32 = (uint32_t*) dst; 968200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dst32[0] = dstTables[0][ir[0]] << kRShift 969200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | dstTables[1][ig[0]] << kGShift 970200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | dstTables[2][ib[0]] << kBShift 971200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | da[0]; 972200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dst32[1] = dstTables[0][ir[1]] << kRShift 973200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | dstTables[1][ig[1]] << kGShift 974200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | dstTables[2][ib[1]] << kBShift 975200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | da[1]; 976200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dst32[2] = dstTables[0][ir[2]] << kRShift 977200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | dstTables[1][ig[2]] << kGShift 978200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | dstTables[2][ib[2]] << kBShift 979200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | da[2]; 980200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dst32[3] = dstTables[0][ir[3]] << kRShift 981200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | dstTables[1][ig[3]] << kGShift 982200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | dstTables[2][ib[3]] << kBShift 983200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | da[3]; 984200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 985200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 9868bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SwapRB kSwapRB> 987200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_generic_1(void* dst, const uint32_t* src, 988200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& rgba, const Sk4f&, 9898bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const dstTables[3]) { 9909dc6cf6b8833d36c29a23d2519989b069745fcd5msarett int kRShift = 0; 9919dc6cf6b8833d36c29a23d2519989b069745fcd5msarett int kGShift = 8; 9929dc6cf6b8833d36c29a23d2519989b069745fcd5msarett int kBShift = 16; 9939dc6cf6b8833d36c29a23d2519989b069745fcd5msarett if (kYes_SwapRB == kSwapRB) { 9949dc6cf6b8833d36c29a23d2519989b069745fcd5msarett kBShift = 0; 9959dc6cf6b8833d36c29a23d2519989b069745fcd5msarett kRShift = 16; 9969dc6cf6b8833d36c29a23d2519989b069745fcd5msarett } 9979dc6cf6b8833d36c29a23d2519989b069745fcd5msarett 998200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba = Sk4f::Min(Sk4f::Max(1023.0f * rgba, 0.0f), 1023.0f); 999200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1000200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i indices = Sk4f_round(rgba); 1001200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 10029dc6cf6b8833d36c29a23d2519989b069745fcd5msarett *((uint32_t*) dst) = dstTables[0][indices[0]] << kRShift 10039dc6cf6b8833d36c29a23d2519989b069745fcd5msarett | dstTables[1][indices[1]] << kGShift 10049dc6cf6b8833d36c29a23d2519989b069745fcd5msarett | dstTables[2][indices[2]] << kBShift 1005200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | (*src & 0xFF000000); 1006200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 1007200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 10088bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttypedef decltype(load_rgb_from_tables )* LoadFn; 10098bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttypedef decltype(load_rgb_from_tables_1 )* Load1Fn; 10108bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttypedef decltype(store_generic<kNo_SwapRB> )* StoreFn; 10118bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttypedef decltype(store_generic_1<kNo_SwapRB>)* Store1Fn; 10128bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 10138bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SkAlphaType kAlphaType, 10148bbcd5aab81dc0742c3367479c0c9d97363b1203msarett ColorSpaceMatch kCSM> 10158bbcd5aab81dc0742c3367479c0c9d97363b1203msarettstatic inline void do_color_xform(void* dst, const uint32_t* src, int len, 10168bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const float* const srcTables[3], const float matrix[16], 10178bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const dstTables[3], LoadFn load, Load1Fn load_1, 10188bbcd5aab81dc0742c3367479c0c9d97363b1203msarett StoreFn store, Store1Fn store_1, size_t sizeOfDstPixel) { 1019200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f rXgXbX, rYgYbY, rZgZbZ, rTgTbT; 1020200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett load_matrix(matrix, rXgXbX, rYgYbY, rZgZbZ, rTgTbT); 1021200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1022200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (len >= 4) { 1023200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett // Naively this would be a loop of load-transform-store, but we found it faster to 1024200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett // move the N+1th load ahead of the Nth store. We don't bother doing this for N<4. 1025200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f r, g, b, a; 1026200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett load(src, r, g, b, a, srcTables); 1027200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett src += 4; 1028200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett len -= 4; 1029200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1030200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f dr, dg, db, da; 1031200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett while (len >= 4) { 1032200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kNone_ColorSpaceMatch == kCSM) { 1033200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett transform_gamut(r, g, b, a, rXgXbX, rYgYbY, rZgZbZ, dr, dg, db, da); 1034200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett translate_gamut(rTgTbT, dr, dg, db); 1035200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } else { 1036200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = r; 1037200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = g; 1038200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = b; 1039200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett da = a; 1040200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1041200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1042200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kPremul_SkAlphaType == kAlphaType) { 1043200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett premultiply(dr, dg, db, da); 1044200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1045200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1046200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett load(src, r, g, b, a, srcTables); 1047200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 10488bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store(dst, src - 4, dr, dg, db, da, dstTables); 1049200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dst = SkTAddOffset<void>(dst, 4 * sizeOfDstPixel); 1050200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett src += 4; 1051200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett len -= 4; 1052200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1053200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1054200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kNone_ColorSpaceMatch == kCSM) { 1055200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett transform_gamut(r, g, b, a, rXgXbX, rYgYbY, rZgZbZ, dr, dg, db, da); 1056200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett translate_gamut(rTgTbT, dr, dg, db); 1057200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } else { 1058200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = r; 1059200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = g; 1060200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = b; 1061200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett da = a; 1062200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1063200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1064200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kPremul_SkAlphaType == kAlphaType) { 1065200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett premultiply(dr, dg, db, da); 1066200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1067200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 10688bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store(dst, src - 4, dr, dg, db, da, dstTables); 1069200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dst = SkTAddOffset<void>(dst, 4 * sizeOfDstPixel); 1070200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1071200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1072200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett while (len > 0) { 1073200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f r, g, b, a; 1074200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett load_1(src, r, g, b, a, srcTables); 1075200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1076200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f rgba; 1077200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kNone_ColorSpaceMatch == kCSM) { 1078200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett transform_gamut_1(r, g, b, rXgXbX, rYgYbY, rZgZbZ, rgba); 1079200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett translate_gamut_1(rTgTbT, rgba); 1080200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } else { 1081200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba = Sk4f(r[0], g[0], b[0], a[0]); 1082200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1083200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1084200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kPremul_SkAlphaType == kAlphaType) { 1085200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett premultiply_1(a, rgba); 1086200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1087200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 10888bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store_1(dst, src, rgba, a, dstTables); 1089200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1090200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett src += 1; 1091200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett len -= 1; 1092200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dst = SkTAddOffset<void>(dst, sizeOfDstPixel); 1093200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1094200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 1095200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 10968bbcd5aab81dc0742c3367479c0c9d97363b1203msarettenum SrcFormat { 10978bbcd5aab81dc0742c3367479c0c9d97363b1203msarett kRGBA_8888_Linear_SrcFormat, 10988bbcd5aab81dc0742c3367479c0c9d97363b1203msarett kRGBA_8888_Table_SrcFormat, 10998bbcd5aab81dc0742c3367479c0c9d97363b1203msarett}; 11008bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 11018bbcd5aab81dc0742c3367479c0c9d97363b1203msarettenum DstFormat { 11028bbcd5aab81dc0742c3367479c0c9d97363b1203msarett k8888_Linear_DstFormat, 11038bbcd5aab81dc0742c3367479c0c9d97363b1203msarett k8888_SRGB_DstFormat, 11048bbcd5aab81dc0742c3367479c0c9d97363b1203msarett k8888_2Dot2_DstFormat, 11058bbcd5aab81dc0742c3367479c0c9d97363b1203msarett k8888_Table_DstFormat, 11068bbcd5aab81dc0742c3367479c0c9d97363b1203msarett kF16_Linear_DstFormat, 1107c0444615ed76360f680619ad4d1f92cda6181a50msarett kF32_Linear_DstFormat, 11088bbcd5aab81dc0742c3367479c0c9d97363b1203msarett}; 11098bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 11108bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SrcFormat kSrc, 11118bbcd5aab81dc0742c3367479c0c9d97363b1203msarett DstFormat kDst, 11128bbcd5aab81dc0742c3367479c0c9d97363b1203msarett SkAlphaType kAlphaType, 11138bbcd5aab81dc0742c3367479c0c9d97363b1203msarett ColorSpaceMatch kCSM, 11148bbcd5aab81dc0742c3367479c0c9d97363b1203msarett SwapRB kSwapRB> 11158bbcd5aab81dc0742c3367479c0c9d97363b1203msarettstatic void color_xform_RGBA(void* dst, const uint32_t* src, int len, 11168bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const float* const srcTables[3], const float matrix[16], 11178bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const dstTables[3]) { 11188bbcd5aab81dc0742c3367479c0c9d97363b1203msarett LoadFn load; 11198bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Load1Fn load_1; 1120c0444615ed76360f680619ad4d1f92cda6181a50msarett static constexpr bool loadAlpha = (kPremul_SkAlphaType == kAlphaType) || 1121c0444615ed76360f680619ad4d1f92cda6181a50msarett (kF16_Linear_DstFormat == kDst) || 1122c0444615ed76360f680619ad4d1f92cda6181a50msarett (kF32_Linear_DstFormat == kDst); 11238bbcd5aab81dc0742c3367479c0c9d97363b1203msarett switch (kSrc) { 11248bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kRGBA_8888_Linear_SrcFormat: 1125c0444615ed76360f680619ad4d1f92cda6181a50msarett if (loadAlpha) { 11268bbcd5aab81dc0742c3367479c0c9d97363b1203msarett load = load_rgba_linear; 11278bbcd5aab81dc0742c3367479c0c9d97363b1203msarett load_1 = load_rgba_linear_1; 11288bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } else { 11298bbcd5aab81dc0742c3367479c0c9d97363b1203msarett load = load_rgb_linear; 11308bbcd5aab81dc0742c3367479c0c9d97363b1203msarett load_1 = load_rgb_linear_1; 11318bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 11328bbcd5aab81dc0742c3367479c0c9d97363b1203msarett break; 11338bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kRGBA_8888_Table_SrcFormat: 1134c0444615ed76360f680619ad4d1f92cda6181a50msarett if (loadAlpha) { 11358bbcd5aab81dc0742c3367479c0c9d97363b1203msarett load = load_rgba_from_tables; 11368bbcd5aab81dc0742c3367479c0c9d97363b1203msarett load_1 = load_rgba_from_tables_1; 11378bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } else { 11388bbcd5aab81dc0742c3367479c0c9d97363b1203msarett load = load_rgb_from_tables; 11398bbcd5aab81dc0742c3367479c0c9d97363b1203msarett load_1 = load_rgb_from_tables_1; 11408bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 11418bbcd5aab81dc0742c3367479c0c9d97363b1203msarett break; 11428bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 11438bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 11448bbcd5aab81dc0742c3367479c0c9d97363b1203msarett StoreFn store; 11458bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Store1Fn store_1; 11468bbcd5aab81dc0742c3367479c0c9d97363b1203msarett size_t sizeOfDstPixel; 11478bbcd5aab81dc0742c3367479c0c9d97363b1203msarett switch (kDst) { 11488bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case k8888_Linear_DstFormat: 11498bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store = store_linear<kSwapRB>; 11508bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store_1 = store_linear_1<kSwapRB>; 11518bbcd5aab81dc0742c3367479c0c9d97363b1203msarett sizeOfDstPixel = 4; 11528bbcd5aab81dc0742c3367479c0c9d97363b1203msarett break; 11538bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case k8888_SRGB_DstFormat: 11548bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store = store_srgb<kSwapRB>; 11558bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store_1 = store_srgb_1<kSwapRB>; 11568bbcd5aab81dc0742c3367479c0c9d97363b1203msarett sizeOfDstPixel = 4; 11578bbcd5aab81dc0742c3367479c0c9d97363b1203msarett break; 11588bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case k8888_2Dot2_DstFormat: 11598bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store = store_2dot2<kSwapRB>; 11608bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store_1 = store_2dot2_1<kSwapRB>; 11618bbcd5aab81dc0742c3367479c0c9d97363b1203msarett sizeOfDstPixel = 4; 11628bbcd5aab81dc0742c3367479c0c9d97363b1203msarett break; 11638bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case k8888_Table_DstFormat: 11648bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store = store_generic<kSwapRB>; 11658bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store_1 = store_generic_1<kSwapRB>; 11668bbcd5aab81dc0742c3367479c0c9d97363b1203msarett sizeOfDstPixel = 4; 11678bbcd5aab81dc0742c3367479c0c9d97363b1203msarett break; 11688bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kF16_Linear_DstFormat: 11698bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store = (kOpaque_SkAlphaType == kAlphaType) ? store_f16_opaque<kSwapRB> : 11708bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store_f16<kSwapRB>; 11718bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store_1 = (kOpaque_SkAlphaType == kAlphaType) ? store_f16_1_opaque<kSwapRB> : 11728bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store_f16_1<kSwapRB>; 11738bbcd5aab81dc0742c3367479c0c9d97363b1203msarett sizeOfDstPixel = 8; 11748bbcd5aab81dc0742c3367479c0c9d97363b1203msarett break; 1175c0444615ed76360f680619ad4d1f92cda6181a50msarett case kF32_Linear_DstFormat: 1176c0444615ed76360f680619ad4d1f92cda6181a50msarett store = store_f32<kSwapRB>; 1177c0444615ed76360f680619ad4d1f92cda6181a50msarett store_1 = store_f32_1<kSwapRB>; 1178c0444615ed76360f680619ad4d1f92cda6181a50msarett sizeOfDstPixel = 16; 1179c0444615ed76360f680619ad4d1f92cda6181a50msarett break; 11808bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 11818bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 11828bbcd5aab81dc0742c3367479c0c9d97363b1203msarett do_color_xform<kAlphaType, kCSM> 11838bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, srcTables, matrix, dstTables, load, load_1, store, store_1, 11848bbcd5aab81dc0742c3367479c0c9d97363b1203msarett sizeOfDstPixel); 11858bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 11868bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 11873418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett/////////////////////////////////////////////////////////////////////////////////////////////////// 11880f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 11897bbda991af353fbe6b34132132d211d23a3dba8cmsarettstatic inline int num_tables(SkColorSpace* space) { 11907bbda991af353fbe6b34132132d211d23a3dba8cmsarett switch (as_CSB(space)->gammaNamed()) { 11917bbda991af353fbe6b34132132d211d23a3dba8cmsarett case kSRGB_SkGammaNamed: 11927bbda991af353fbe6b34132132d211d23a3dba8cmsarett case k2Dot2Curve_SkGammaNamed: 11937bbda991af353fbe6b34132132d211d23a3dba8cmsarett case kLinear_SkGammaNamed: 11947bbda991af353fbe6b34132132d211d23a3dba8cmsarett return 0; 11957bbda991af353fbe6b34132132d211d23a3dba8cmsarett default: { 11967bbda991af353fbe6b34132132d211d23a3dba8cmsarett const SkGammas* gammas = as_CSB(space)->gammas(); 11977bbda991af353fbe6b34132132d211d23a3dba8cmsarett SkASSERT(gammas); 11987bbda991af353fbe6b34132132d211d23a3dba8cmsarett 11997bbda991af353fbe6b34132132d211d23a3dba8cmsarett bool gammasAreMatching = (gammas->type(0) == gammas->type(1)) && 12007bbda991af353fbe6b34132132d211d23a3dba8cmsarett (gammas->data(0) == gammas->data(1)) && 12017bbda991af353fbe6b34132132d211d23a3dba8cmsarett (gammas->type(0) == gammas->type(2)) && 12027bbda991af353fbe6b34132132d211d23a3dba8cmsarett (gammas->data(0) == gammas->data(2)); 12037bbda991af353fbe6b34132132d211d23a3dba8cmsarett 12047bbda991af353fbe6b34132132d211d23a3dba8cmsarett // It's likely that each component will have the same gamma. In this case, 12057bbda991af353fbe6b34132132d211d23a3dba8cmsarett // we only need to build one table. 12067bbda991af353fbe6b34132132d211d23a3dba8cmsarett return gammasAreMatching ? 1 : 3; 12077bbda991af353fbe6b34132132d211d23a3dba8cmsarett } 12087bbda991af353fbe6b34132132d211d23a3dba8cmsarett } 12097bbda991af353fbe6b34132132d211d23a3dba8cmsarett} 12107bbda991af353fbe6b34132132d211d23a3dba8cmsarett 12118bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM> 12128bbcd5aab81dc0742c3367479c0c9d97363b1203msarettSkColorSpaceXform_Base<kSrc, kDst, kCSM> 12138bbcd5aab81dc0742c3367479c0c9d97363b1203msarett::SkColorSpaceXform_Base(const sk_sp<SkColorSpace>& srcSpace, const SkMatrix44& srcToDst, 12148bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const sk_sp<SkColorSpace>& dstSpace) 12153418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett : fColorLUT(sk_ref_sp((SkColorLookUpTable*) as_CSB(srcSpace)->colorLUT())) 12163418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett{ 1217de68d6c4616d86621373d88100002ddfdb9c08e3brianosman srcToDst.asColMajorf(fSrcToDst); 12187bbda991af353fbe6b34132132d211d23a3dba8cmsarett 12197bbda991af353fbe6b34132132d211d23a3dba8cmsarett const int numSrcTables = num_tables(srcSpace.get()); 12207bbda991af353fbe6b34132132d211d23a3dba8cmsarett const int numDstTables = num_tables(dstSpace.get()); 12217bbda991af353fbe6b34132132d211d23a3dba8cmsarett const size_t srcTableBytes = numSrcTables * 256 * sizeof(float); 12227bbda991af353fbe6b34132132d211d23a3dba8cmsarett const size_t dstTableBytes = numDstTables * kDstGammaTableSize * sizeof(uint8_t); 12237bbda991af353fbe6b34132132d211d23a3dba8cmsarett fStorage.reset(srcTableBytes + dstTableBytes); 12247bbda991af353fbe6b34132132d211d23a3dba8cmsarett float* srcStorage = (float*) fStorage.get(); 12257bbda991af353fbe6b34132132d211d23a3dba8cmsarett uint8_t* dstStorage = SkTAddOffset<uint8_t>(fStorage.get(), srcTableBytes); 12267bbda991af353fbe6b34132132d211d23a3dba8cmsarett 12277bbda991af353fbe6b34132132d211d23a3dba8cmsarett const bool srcGammasAreMatching = (1 >= numSrcTables); 12287bbda991af353fbe6b34132132d211d23a3dba8cmsarett const bool dstGammasAreMatching = (1 >= numDstTables); 12297bbda991af353fbe6b34132132d211d23a3dba8cmsarett build_gamma_tables(fSrcGammaTables, srcStorage, 256, srcSpace, kToLinear, srcGammasAreMatching); 12307bbda991af353fbe6b34132132d211d23a3dba8cmsarett build_gamma_tables(fDstGammaTables, dstStorage, kDstGammaTableSize, dstSpace, kFromLinear, 12317bbda991af353fbe6b34132132d211d23a3dba8cmsarett dstGammasAreMatching); 12323418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett} 1233dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 12347bbda991af353fbe6b34132132d211d23a3dba8cmsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 12357bbda991af353fbe6b34132132d211d23a3dba8cmsarett 12368bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SrcFormat kSrc, DstFormat kDst, ColorSpaceMatch kCSM, SwapRB kSwap> 12378bbcd5aab81dc0742c3367479c0c9d97363b1203msarettstatic inline void apply_set_alpha(void* dst, const uint32_t* src, int len, SkAlphaType alphaType, 12388bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const float* const srcTables[3], const float matrix[16], 12398bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const dstTables[3]) { 12408bbcd5aab81dc0742c3367479c0c9d97363b1203msarett switch (alphaType) { 12418bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kOpaque_SkAlphaType: 12428bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return color_xform_RGBA<kSrc, kDst, kOpaque_SkAlphaType, kCSM, kSwap> 12438bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, srcTables, matrix, dstTables); 12448bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kPremul_SkAlphaType: 12458bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return color_xform_RGBA<kSrc, kDst, kPremul_SkAlphaType, kCSM, kSwap> 12468bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, srcTables, matrix, dstTables); 12478bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kUnpremul_SkAlphaType: 12488bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return color_xform_RGBA<kSrc, kDst, kUnpremul_SkAlphaType, kCSM, kSwap> 12498bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, srcTables, matrix, dstTables); 12508bbcd5aab81dc0742c3367479c0c9d97363b1203msarett default: 12518bbcd5aab81dc0742c3367479c0c9d97363b1203msarett SkASSERT(false); 12528bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return; 12538bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 12548bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 12558bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 12568bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SrcGamma kSrc, DstFormat kDst, ColorSpaceMatch kCSM, SwapRB kSwap> 12578bbcd5aab81dc0742c3367479c0c9d97363b1203msarettstatic inline void apply_set_src(void* dst, const uint32_t* src, int len, SkAlphaType alphaType, 12588bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const float* const srcTables[3], const float matrix[16], 12598bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const dstTables[3]) { 12608bbcd5aab81dc0742c3367479c0c9d97363b1203msarett switch (kSrc) { 12618bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kLinear_SrcGamma: 12628bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return apply_set_alpha<kRGBA_8888_Linear_SrcFormat, kDst, kCSM, kSwap> 12638bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, alphaType, nullptr, matrix, dstTables); 12648bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kTable_SrcGamma: 12658bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return apply_set_alpha<kRGBA_8888_Table_SrcFormat, kDst, kCSM, kSwap> 12668bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, alphaType, srcTables, matrix, dstTables); 12678bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 12688bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 12698bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 12708bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM> 12718bbcd5aab81dc0742c3367479c0c9d97363b1203msarettvoid SkColorSpaceXform_Base<kSrc, kDst, kCSM> 1272c0444615ed76360f680619ad4d1f92cda6181a50msarett::apply(void* dst, const uint32_t* src, int len, ColorFormat dstColorFormat, SkAlphaType alphaType) 1273d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarettconst 12743418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett{ 1275200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kFull_ColorSpaceMatch == kCSM) { 12768bbcd5aab81dc0742c3367479c0c9d97363b1203msarett switch (alphaType) { 1277200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett case kPremul_SkAlphaType: 1278200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett // We can't skip the xform since we need to perform a premultiply in the 1279200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett // linear space. 1280200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett break; 1281200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett default: 1282c0444615ed76360f680619ad4d1f92cda6181a50msarett switch (dstColorFormat) { 1283c0444615ed76360f680619ad4d1f92cda6181a50msarett case kRGBA_8888_ColorFormat: 1284200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett return (void) memcpy(dst, src, len * sizeof(uint32_t)); 1285c0444615ed76360f680619ad4d1f92cda6181a50msarett case kBGRA_8888_ColorFormat: 1286200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett return SkOpts::RGBA_to_BGRA((uint32_t*) dst, src, len); 1287c0444615ed76360f680619ad4d1f92cda6181a50msarett case kRGBA_F16_ColorFormat: 1288c0444615ed76360f680619ad4d1f92cda6181a50msarett case kRGBA_F32_ColorFormat: 1289c0444615ed76360f680619ad4d1f92cda6181a50msarett // There's still work to do to xform to linear floats. 1290200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett break; 1291200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett default: 1292200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett SkASSERT(false); 1293200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett return; 1294200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1295200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1296200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1297200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 12983418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett if (fColorLUT) { 1299d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett size_t storageBytes = len * sizeof(uint32_t); 13003418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett#if defined(GOOGLE3) 13013418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett // Stack frame size is limited in GOOGLE3. 1302d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett SkAutoSMalloc<256 * sizeof(uint32_t)> storage(storageBytes); 13033418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett#else 1304d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett SkAutoSMalloc<1024 * sizeof(uint32_t)> storage(storageBytes); 13053418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett#endif 13063418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett 1307d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett handle_color_lut((uint32_t*) storage.get(), src, len, fColorLUT.get()); 1308d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett src = (const uint32_t*) storage.get(); 13093418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett } 13103418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett 1311c0444615ed76360f680619ad4d1f92cda6181a50msarett switch (dstColorFormat) { 1312c0444615ed76360f680619ad4d1f92cda6181a50msarett case kRGBA_8888_ColorFormat: 13138bbcd5aab81dc0742c3367479c0c9d97363b1203msarett switch (kDst) { 13148bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kLinear_DstGamma: 13158bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return apply_set_src<kSrc, k8888_Linear_DstFormat, kCSM, kNo_SwapRB> 13168bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr); 13178bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kSRGB_DstGamma: 13188bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return apply_set_src<kSrc, k8888_SRGB_DstFormat, kCSM, kNo_SwapRB> 13198bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr); 13208bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case k2Dot2_DstGamma: 13218bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return apply_set_src<kSrc, k8888_2Dot2_DstFormat, kCSM, kNo_SwapRB> 13228bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr); 13238bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kTable_DstGamma: 13248bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return apply_set_src<kSrc, k8888_Table_DstFormat, kCSM, kNo_SwapRB> 13258bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, fDstGammaTables); 1326d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett } 1327c0444615ed76360f680619ad4d1f92cda6181a50msarett case kBGRA_8888_ColorFormat: 13288bbcd5aab81dc0742c3367479c0c9d97363b1203msarett switch (kDst) { 13298bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kLinear_DstGamma: 13308bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return apply_set_src<kSrc, k8888_Linear_DstFormat, kCSM, kYes_SwapRB> 13318bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr); 13328bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kSRGB_DstGamma: 13338bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return apply_set_src<kSrc, k8888_SRGB_DstFormat, kCSM, kYes_SwapRB> 13348bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr); 13358bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case k2Dot2_DstGamma: 13368bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return apply_set_src<kSrc, k8888_2Dot2_DstFormat, kCSM, kYes_SwapRB> 13378bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr); 13388bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kTable_DstGamma: 13398bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return apply_set_src<kSrc, k8888_Table_DstFormat, kCSM, kYes_SwapRB> 13408bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, fDstGammaTables); 1341d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett } 1342c0444615ed76360f680619ad4d1f92cda6181a50msarett case kRGBA_F16_ColorFormat: 13438bbcd5aab81dc0742c3367479c0c9d97363b1203msarett switch (kDst) { 13448bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kLinear_DstGamma: 13458bbcd5aab81dc0742c3367479c0c9d97363b1203msarett return apply_set_src<kSrc, kF16_Linear_DstFormat, kCSM, kNo_SwapRB> 13468bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr); 1347d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett default: 1348d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett SkASSERT(false); 1349d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett return; 1350d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett } 1351c0444615ed76360f680619ad4d1f92cda6181a50msarett case kRGBA_F32_ColorFormat: 1352c0444615ed76360f680619ad4d1f92cda6181a50msarett switch (kDst) { 1353c0444615ed76360f680619ad4d1f92cda6181a50msarett case kLinear_DstGamma: 1354c0444615ed76360f680619ad4d1f92cda6181a50msarett return apply_set_src<kSrc, kF32_Linear_DstFormat, kCSM, kNo_SwapRB> 1355c0444615ed76360f680619ad4d1f92cda6181a50msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr); 1356c0444615ed76360f680619ad4d1f92cda6181a50msarett default: 1357c0444615ed76360f680619ad4d1f92cda6181a50msarett SkASSERT(false); 1358c0444615ed76360f680619ad4d1f92cda6181a50msarett return; 1359c0444615ed76360f680619ad4d1f92cda6181a50msarett } 1360d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett default: 1361d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett SkASSERT(false); 1362d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett return; 1363d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett } 13649ce3a543c92a73e6daca420defc042886b3f2019msarett} 13659dc6cf6b8833d36c29a23d2519989b069745fcd5msarett 13667bbda991af353fbe6b34132132d211d23a3dba8cmsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 13677bbda991af353fbe6b34132132d211d23a3dba8cmsarett 13689dc6cf6b8833d36c29a23d2519989b069745fcd5msarettstd::unique_ptr<SkColorSpaceXform> SlowIdentityXform(const sk_sp<SkColorSpace>& space) { 13699dc6cf6b8833d36c29a23d2519989b069745fcd5msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 13708bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch> 13719dc6cf6b8833d36c29a23d2519989b069745fcd5msarett (space, SkMatrix::I(), space)); 13729dc6cf6b8833d36c29a23d2519989b069745fcd5msarett} 1373