SkColorSpaceXform.cpp revision df44fc5f2bb282557df291e20dbd26c070533aa6
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" 1131d097e865f266c8398f45114e4c75c0dfdef058msarett#include "SkColorSpaceXform_Base.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, 2594be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarett SkColorSpace* space, const GammaFns<T>& fns, bool gammasAreMatching) 2604be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarett{ 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)); 306df44fc5f2bb282557df291e20dbd26c070533aa6Matt Sarett const SkColorSpaceTransferFn& 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 3454be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarettstd::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace, 3464be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarett 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); 3544be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarett if (SkColorSpace::Equals(srcSpace, dstSpace)) { 355200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett srcToDst.setIdentity(); 356200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett csm = kFull_ColorSpaceMatch; 357971cd496b9e25f87f3a75a0015c203322907136abrianosman } else { 3587802c3db24effa6f3186bff7490a2a8dd85d2a70msarett srcToDst.setConcat(as_CSB(dstSpace)->fromXYZD50(), as_CSB(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 58731d097e865f266c8398f45114e4c75c0dfdef058msarettstatic void handle_color_lut(uint32_t* dst, const void* vsrc, int len, 5883418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett SkColorLookUpTable* colorLUT) { 58931d097e865f266c8398f45114e4c75c0dfdef058msarett const uint32_t* src = (const uint32_t*) vsrc; 590b39067696ad08a26bbe49b71a71f0546dc42a075msarett while (len-- > 0) { 5910f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett uint8_t r = (*src >> 0) & 0xFF, 5920f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett g = (*src >> 8) & 0xFF, 5930f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett b = (*src >> 16) & 0xFF; 5940f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 5953418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett float in[3]; 5963418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett float out[3]; 5973418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett in[0] = byte_to_float(r); 5983418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett in[1] = byte_to_float(g); 5993418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett in[2] = byte_to_float(b); 6003418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett interp_3d_clut(out, in, colorLUT); 6010f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6023418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett r = sk_float_round2int(255.0f * clamp_normalized_float(out[0])); 6033418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett g = sk_float_round2int(255.0f * clamp_normalized_float(out[1])); 6043418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett b = sk_float_round2int(255.0f * clamp_normalized_float(out[2])); 6053418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett *dst = SkPackARGB_as_RGBA(0xFF, r, g, b); 6060f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6073418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett src++; 6083418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett dst++; 6093418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett } 6103418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett} 6110f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 612200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void load_matrix(const float matrix[16], 613200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& rXgXbX, Sk4f& rYgYbY, Sk4f& rZgZbZ, Sk4f& rTgTbT) { 614200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rXgXbX = Sk4f::Load(matrix + 0); 615200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rYgYbY = Sk4f::Load(matrix + 4); 616200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rZgZbZ = Sk4f::Load(matrix + 8); 617200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rTgTbT = Sk4f::Load(matrix + 12); 618200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 619200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 620cf7b877d62537672b67449bc96858cc1262be5f8msarettenum Order { 621cf7b877d62537672b67449bc96858cc1262be5f8msarett kRGBA_Order, 622cf7b877d62537672b67449bc96858cc1262be5f8msarett kBGRA_Order, 623cf7b877d62537672b67449bc96858cc1262be5f8msarett}; 624cf7b877d62537672b67449bc96858cc1262be5f8msarett 625cf7b877d62537672b67449bc96858cc1262be5f8msarettstatic inline void set_rb_shifts(Order kOrder, int* kRShift, int* kBShift) { 626cf7b877d62537672b67449bc96858cc1262be5f8msarett if (kRGBA_Order == kOrder) { 627cf7b877d62537672b67449bc96858cc1262be5f8msarett *kRShift = 0; 628cf7b877d62537672b67449bc96858cc1262be5f8msarett *kBShift = 16; 629cf7b877d62537672b67449bc96858cc1262be5f8msarett } else { 630cf7b877d62537672b67449bc96858cc1262be5f8msarett *kRShift = 16; 631cf7b877d62537672b67449bc96858cc1262be5f8msarett *kBShift = 0; 632cf7b877d62537672b67449bc96858cc1262be5f8msarett } 633cf7b877d62537672b67449bc96858cc1262be5f8msarett} 634cf7b877d62537672b67449bc96858cc1262be5f8msarett 635cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 636200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void load_rgb_from_tables(const uint32_t* src, 637200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, 638200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett const float* const srcTables[3]) { 639cf7b877d62537672b67449bc96858cc1262be5f8msarett int kRShift, kGShift = 8, kBShift; 640cf7b877d62537672b67449bc96858cc1262be5f8msarett set_rb_shifts(kOrder, &kRShift, &kBShift); 641cf7b877d62537672b67449bc96858cc1262be5f8msarett r = { srcTables[0][(src[0] >> kRShift) & 0xFF], 642cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[0][(src[1] >> kRShift) & 0xFF], 643cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[0][(src[2] >> kRShift) & 0xFF], 644cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[0][(src[3] >> kRShift) & 0xFF], }; 645cf7b877d62537672b67449bc96858cc1262be5f8msarett g = { srcTables[1][(src[0] >> kGShift) & 0xFF], 646cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[1][(src[1] >> kGShift) & 0xFF], 647cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[1][(src[2] >> kGShift) & 0xFF], 648cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[1][(src[3] >> kGShift) & 0xFF], }; 649cf7b877d62537672b67449bc96858cc1262be5f8msarett b = { srcTables[2][(src[0] >> kBShift) & 0xFF], 650cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[2][(src[1] >> kBShift) & 0xFF], 651cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[2][(src[2] >> kBShift) & 0xFF], 652cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[2][(src[3] >> kBShift) & 0xFF], }; 653200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett a = 0.0f; // Don't let the compiler complain that |a| is uninitialized. 654200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 655200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 656cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 657200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void load_rgba_from_tables(const uint32_t* src, 658200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, 659200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett const float* const srcTables[3]) { 660cf7b877d62537672b67449bc96858cc1262be5f8msarett int kRShift, kGShift = 8, kBShift; 661cf7b877d62537672b67449bc96858cc1262be5f8msarett set_rb_shifts(kOrder, &kRShift, &kBShift); 662cf7b877d62537672b67449bc96858cc1262be5f8msarett r = { srcTables[0][(src[0] >> kRShift) & 0xFF], 663cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[0][(src[1] >> kRShift) & 0xFF], 664cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[0][(src[2] >> kRShift) & 0xFF], 665cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[0][(src[3] >> kRShift) & 0xFF], }; 6665414be06935ce0f990a2df5dccaf9ddec78ec553msarett g = { srcTables[1][(src[0] >> kGShift) & 0xFF], 667cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[1][(src[1] >> kGShift) & 0xFF], 668cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[1][(src[2] >> kGShift) & 0xFF], 669cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[1][(src[3] >> kGShift) & 0xFF], }; 670cf7b877d62537672b67449bc96858cc1262be5f8msarett b = { srcTables[2][(src[0] >> kBShift) & 0xFF], 671cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[2][(src[1] >> kBShift) & 0xFF], 672cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[2][(src[2] >> kBShift) & 0xFF], 673cf7b877d62537672b67449bc96858cc1262be5f8msarett srcTables[2][(src[3] >> kBShift) & 0xFF], }; 674200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett a = (1.0f / 255.0f) * SkNx_cast<float>(Sk4u::Load(src) >> 24); 675200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 676200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 677cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 6788bbcd5aab81dc0742c3367479c0c9d97363b1203msarettstatic inline void load_rgb_linear(const uint32_t* src, 679be362774f9b9e8964544a579281603ed995e6e5amsarett Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, 6808bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const float* const[3]) { 681cf7b877d62537672b67449bc96858cc1262be5f8msarett int kRShift, kGShift = 8, kBShift; 682cf7b877d62537672b67449bc96858cc1262be5f8msarett set_rb_shifts(kOrder, &kRShift, &kBShift); 683cf7b877d62537672b67449bc96858cc1262be5f8msarett r = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kRShift) & 0xFF); 684cf7b877d62537672b67449bc96858cc1262be5f8msarett g = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kGShift) & 0xFF); 685cf7b877d62537672b67449bc96858cc1262be5f8msarett b = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kBShift) & 0xFF); 686be362774f9b9e8964544a579281603ed995e6e5amsarett a = 0.0f; // Don't let the compiler complain that |a| is uninitialized. 6878bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 6888bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 689cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 6908bbcd5aab81dc0742c3367479c0c9d97363b1203msarettstatic inline void load_rgba_linear(const uint32_t* src, 6918bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, 6928bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const float* const[3]) { 693cf7b877d62537672b67449bc96858cc1262be5f8msarett int kRShift, kGShift = 8, kBShift; 694cf7b877d62537672b67449bc96858cc1262be5f8msarett set_rb_shifts(kOrder, &kRShift, &kBShift); 695cf7b877d62537672b67449bc96858cc1262be5f8msarett r = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kRShift) & 0xFF); 696cf7b877d62537672b67449bc96858cc1262be5f8msarett g = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kGShift) & 0xFF); 697cf7b877d62537672b67449bc96858cc1262be5f8msarett b = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kBShift) & 0xFF); 698cf7b877d62537672b67449bc96858cc1262be5f8msarett a = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> 24)); 6998bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 7008bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 701cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 702200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void load_rgb_from_tables_1(const uint32_t* src, 703200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& r, Sk4f& g, Sk4f& b, Sk4f&, 704200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett const float* const srcTables[3]) { 705cf7b877d62537672b67449bc96858cc1262be5f8msarett int kRShift, kGShift = 8, kBShift; 706cf7b877d62537672b67449bc96858cc1262be5f8msarett set_rb_shifts(kOrder, &kRShift, &kBShift); 707cf7b877d62537672b67449bc96858cc1262be5f8msarett r = Sk4f(srcTables[0][(*src >> kRShift) & 0xFF]); 708cf7b877d62537672b67449bc96858cc1262be5f8msarett g = Sk4f(srcTables[1][(*src >> kGShift) & 0xFF]); 709cf7b877d62537672b67449bc96858cc1262be5f8msarett b = Sk4f(srcTables[2][(*src >> kBShift) & 0xFF]); 710200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 711200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 712cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 713200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void load_rgba_from_tables_1(const uint32_t* src, 714200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, 715200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett const float* const srcTables[3]) { 716cf7b877d62537672b67449bc96858cc1262be5f8msarett int kRShift, kGShift = 8, kBShift; 717cf7b877d62537672b67449bc96858cc1262be5f8msarett set_rb_shifts(kOrder, &kRShift, &kBShift); 718cf7b877d62537672b67449bc96858cc1262be5f8msarett r = Sk4f(srcTables[0][(*src >> kRShift) & 0xFF]); 719cf7b877d62537672b67449bc96858cc1262be5f8msarett g = Sk4f(srcTables[1][(*src >> kGShift) & 0xFF]); 720cf7b877d62537672b67449bc96858cc1262be5f8msarett b = Sk4f(srcTables[2][(*src >> kBShift) & 0xFF]); 721200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett a = (1.0f / 255.0f) * Sk4f(*src >> 24); 722200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 723200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 724cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 7258bbcd5aab81dc0742c3367479c0c9d97363b1203msarettstatic inline void load_rgb_linear_1(const uint32_t* src, 7268bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Sk4f& r, Sk4f& g, Sk4f& b, Sk4f&, 7278bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const float* const srcTables[3]) { 728cf7b877d62537672b67449bc96858cc1262be5f8msarett int kRShift, kGShift = 8, kBShift; 729cf7b877d62537672b67449bc96858cc1262be5f8msarett set_rb_shifts(kOrder, &kRShift, &kBShift); 730cf7b877d62537672b67449bc96858cc1262be5f8msarett r = Sk4f((1.0f / 255.0f) * ((*src >> kRShift) & 0xFF)); 731cf7b877d62537672b67449bc96858cc1262be5f8msarett g = Sk4f((1.0f / 255.0f) * ((*src >> kGShift) & 0xFF)); 732cf7b877d62537672b67449bc96858cc1262be5f8msarett b = Sk4f((1.0f / 255.0f) * ((*src >> kBShift) & 0xFF)); 7338bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 7348bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 735cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 7368bbcd5aab81dc0742c3367479c0c9d97363b1203msarettstatic inline void load_rgba_linear_1(const uint32_t* src, 7378bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, 7388bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const float* const srcTables[3]) { 739cf7b877d62537672b67449bc96858cc1262be5f8msarett int kRShift, kGShift = 8, kBShift; 740cf7b877d62537672b67449bc96858cc1262be5f8msarett set_rb_shifts(kOrder, &kRShift, &kBShift); 741cf7b877d62537672b67449bc96858cc1262be5f8msarett r = Sk4f((1.0f / 255.0f) * ((*src >> kRShift) & 0xFF)); 742cf7b877d62537672b67449bc96858cc1262be5f8msarett g = Sk4f((1.0f / 255.0f) * ((*src >> kGShift) & 0xFF)); 743cf7b877d62537672b67449bc96858cc1262be5f8msarett b = Sk4f((1.0f / 255.0f) * ((*src >> kBShift) & 0xFF)); 744cf7b877d62537672b67449bc96858cc1262be5f8msarett a = Sk4f((1.0f / 255.0f) * ((*src >> 24))); 7458bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 7468bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 747200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void transform_gamut(const Sk4f& r, const Sk4f& g, const Sk4f& b, const Sk4f& a, 748200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett const Sk4f& rXgXbX, const Sk4f& rYgYbY, const Sk4f& rZgZbZ, 749200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f& da) { 750200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = rXgXbX[0]*r + rYgYbY[0]*g + rZgZbZ[0]*b; 751200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = rXgXbX[1]*r + rYgYbY[1]*g + rZgZbZ[1]*b; 752200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = rXgXbX[2]*r + rYgYbY[2]*g + rZgZbZ[2]*b; 753200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett da = a; 754200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 755200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 756200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void transform_gamut_1(const Sk4f& r, const Sk4f& g, const Sk4f& b, 757200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett const Sk4f& rXgXbX, const Sk4f& rYgYbY, const Sk4f& rZgZbZ, 758200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& rgba) { 759200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba = rXgXbX*r + rYgYbY*g + rZgZbZ*b; 760200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 761200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 762200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void translate_gamut(const Sk4f& rTgTbT, Sk4f& dr, Sk4f& dg, Sk4f& db) { 763200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = dr + rTgTbT[0]; 764200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = dg + rTgTbT[1]; 765200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = db + rTgTbT[2]; 766200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 767200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 768200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void translate_gamut_1(const Sk4f& rTgTbT, Sk4f& rgba) { 769200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba = rgba + rTgTbT; 770200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 771200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 772200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void premultiply(Sk4f& dr, Sk4f& dg, Sk4f& db, const Sk4f& da) { 773200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = da * dr; 774200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = da * dg; 775200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = da * db; 776200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 777200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 778200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void premultiply_1(const Sk4f& a, Sk4f& rgba) { 779200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba = a * rgba; 780200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 781200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 782cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 783200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_srgb(void* dst, const uint32_t* src, 784200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, 7858bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 786cf7b877d62537672b67449bc96858cc1262be5f8msarett int kRShift, kGShift = 8, kBShift; 787cf7b877d62537672b67449bc96858cc1262be5f8msarett set_rb_shifts(kOrder, &kRShift, &kBShift); 788200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = sk_linear_to_srgb_needs_trunc(dr); 789200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = sk_linear_to_srgb_needs_trunc(dg); 790200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = sk_linear_to_srgb_needs_trunc(db); 791200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 792200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = sk_clamp_0_255(dr); 793200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = sk_clamp_0_255(dg); 794200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = sk_clamp_0_255(db); 795200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 796200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i da = Sk4i::Load(src) & 0xFF000000; 797200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 798200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i rgba = (SkNx_cast<int>(dr) << kRShift) 799200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | (SkNx_cast<int>(dg) << kGShift) 800200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | (SkNx_cast<int>(db) << kBShift) 801200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | (da ); 802200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba.store(dst); 803200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 804200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 805cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 806200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_srgb_1(void* dst, const uint32_t* src, 807200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& rgba, const Sk4f&, 8088bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 809200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba = sk_clamp_0_255(sk_linear_to_srgb_needs_trunc(rgba)); 810200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 811200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett uint32_t tmp; 812200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett SkNx_cast<uint8_t>(SkNx_cast<int32_t>(rgba)).store(&tmp); 813200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett tmp = (*src & 0xFF000000) | (tmp & 0x00FFFFFF); 814cf7b877d62537672b67449bc96858cc1262be5f8msarett if (kBGRA_Order == kOrder) { 815200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett tmp = SkSwizzle_RB(tmp); 816200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 817200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 818200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett *(uint32_t*)dst = tmp; 819200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 820200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 821200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline Sk4f linear_to_2dot2(const Sk4f& x) { 822200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett // x^(29/64) is a very good approximation of the true value, x^(1/2.2). 823200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett auto x2 = x.rsqrt(), // x^(-1/2) 824200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett x32 = x2.rsqrt().rsqrt().rsqrt().rsqrt(), // x^(-1/32) 825200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett x64 = x32.rsqrt(); // x^(+1/64) 826200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 827200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett // 29 = 32 - 2 - 1 828200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett return 255.0f * x2.invert() * x32 * x64.invert(); 829200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 830200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 831cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 832200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_2dot2(void* dst, const uint32_t* src, 833200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, 8348bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 835cf7b877d62537672b67449bc96858cc1262be5f8msarett int kRShift, kGShift = 8, kBShift; 836cf7b877d62537672b67449bc96858cc1262be5f8msarett set_rb_shifts(kOrder, &kRShift, &kBShift); 837200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = linear_to_2dot2(dr); 838200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = linear_to_2dot2(dg); 839200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = linear_to_2dot2(db); 840200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 841200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = sk_clamp_0_255(dr); 842200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = sk_clamp_0_255(dg); 843200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = sk_clamp_0_255(db); 844200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 845200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i da = Sk4i::Load(src) & 0xFF000000; 846200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 847200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i rgba = (Sk4f_round(dr) << kRShift) 848200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | (Sk4f_round(dg) << kGShift) 849200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | (Sk4f_round(db) << kBShift) 850200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | (da ); 851200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba.store(dst); 852200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 853200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 854cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 855200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_2dot2_1(void* dst, const uint32_t* src, 856200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& rgba, const Sk4f&, 8578bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 858200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba = sk_clamp_0_255(linear_to_2dot2(rgba)); 859200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 860200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett uint32_t tmp; 861200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett SkNx_cast<uint8_t>(Sk4f_round(rgba)).store(&tmp); 862200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett tmp = (*src & 0xFF000000) | (tmp & 0x00FFFFFF); 863cf7b877d62537672b67449bc96858cc1262be5f8msarett if (kBGRA_Order == kOrder) { 864200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett tmp = SkSwizzle_RB(tmp); 865200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 866200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 867200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett *(uint32_t*)dst = tmp; 868200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 869200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 870cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 8718bbcd5aab81dc0742c3367479c0c9d97363b1203msarettstatic inline void store_linear(void* dst, const uint32_t* src, 8728bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, 8738bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 874cf7b877d62537672b67449bc96858cc1262be5f8msarett int kRShift, kGShift = 8, kBShift; 875cf7b877d62537672b67449bc96858cc1262be5f8msarett set_rb_shifts(kOrder, &kRShift, &kBShift); 876591971d02a8e22dac0955c0f07b7cf500a89d5ccmsarett dr = sk_clamp_0_255(255.0f * dr); 877591971d02a8e22dac0955c0f07b7cf500a89d5ccmsarett dg = sk_clamp_0_255(255.0f * dg); 878591971d02a8e22dac0955c0f07b7cf500a89d5ccmsarett db = sk_clamp_0_255(255.0f * db); 8798bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 8808bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Sk4i da = Sk4i::Load(src) & 0xFF000000; 8818bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 8828bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Sk4i rgba = (Sk4f_round(dr) << kRShift) 8838bbcd5aab81dc0742c3367479c0c9d97363b1203msarett | (Sk4f_round(dg) << kGShift) 8848bbcd5aab81dc0742c3367479c0c9d97363b1203msarett | (Sk4f_round(db) << kBShift) 8858bbcd5aab81dc0742c3367479c0c9d97363b1203msarett | (da ); 8868bbcd5aab81dc0742c3367479c0c9d97363b1203msarett rgba.store(dst); 8878bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 8888bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 889cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 8908bbcd5aab81dc0742c3367479c0c9d97363b1203msarettstatic inline void store_linear_1(void* dst, const uint32_t* src, 8918bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Sk4f& rgba, const Sk4f&, 8928bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 893591971d02a8e22dac0955c0f07b7cf500a89d5ccmsarett rgba = sk_clamp_0_255(255.0f * rgba); 8948bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 8958bbcd5aab81dc0742c3367479c0c9d97363b1203msarett uint32_t tmp; 8968bbcd5aab81dc0742c3367479c0c9d97363b1203msarett SkNx_cast<uint8_t>(Sk4f_round(rgba)).store(&tmp); 8978bbcd5aab81dc0742c3367479c0c9d97363b1203msarett tmp = (*src & 0xFF000000) | (tmp & 0x00FFFFFF); 898cf7b877d62537672b67449bc96858cc1262be5f8msarett if (kBGRA_Order == kOrder) { 8998bbcd5aab81dc0742c3367479c0c9d97363b1203msarett tmp = SkSwizzle_RB(tmp); 9008bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 9018bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 9028bbcd5aab81dc0742c3367479c0c9d97363b1203msarett *(uint32_t*)dst = tmp; 9038bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 9048bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 905cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 906200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_f16(void* dst, const uint32_t* src, 907200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f& da, 9088bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 90933cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein Sk4h::Store4(dst, SkFloatToHalf_finite_ftz(dr), 91033cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein SkFloatToHalf_finite_ftz(dg), 91133cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein SkFloatToHalf_finite_ftz(db), 91233cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein SkFloatToHalf_finite_ftz(da)); 913200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 914200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 915cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 916200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_f16_1(void* dst, const uint32_t* src, 917200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& rgba, const Sk4f& a, 9188bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 919200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba = Sk4f(rgba[0], rgba[1], rgba[2], a[3]); 9208ae991e433d2c0814ea5579613f00173805ff057mtklein SkFloatToHalf_finite_ftz(rgba).store((uint64_t*) dst); 921200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 922200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 923cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 924c0444615ed76360f680619ad4d1f92cda6181a50msarettstatic inline void store_f32(void* dst, const uint32_t* src, 925c0444615ed76360f680619ad4d1f92cda6181a50msarett Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f& da, 926c0444615ed76360f680619ad4d1f92cda6181a50msarett const uint8_t* const[3]) { 92733cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein Sk4f::Store4(dst, dr, dg, db, da); 928c0444615ed76360f680619ad4d1f92cda6181a50msarett} 929c0444615ed76360f680619ad4d1f92cda6181a50msarett 930cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 931c0444615ed76360f680619ad4d1f92cda6181a50msarettstatic inline void store_f32_1(void* dst, const uint32_t* src, 932c0444615ed76360f680619ad4d1f92cda6181a50msarett Sk4f& rgba, const Sk4f& a, 933c0444615ed76360f680619ad4d1f92cda6181a50msarett const uint8_t* const[3]) { 934c0444615ed76360f680619ad4d1f92cda6181a50msarett rgba = Sk4f(rgba[0], rgba[1], rgba[2], a[3]); 935c0444615ed76360f680619ad4d1f92cda6181a50msarett rgba.store((float*) dst); 936c0444615ed76360f680619ad4d1f92cda6181a50msarett} 937c0444615ed76360f680619ad4d1f92cda6181a50msarett 938cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 939200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_f16_opaque(void* dst, const uint32_t* src, 940c0444615ed76360f680619ad4d1f92cda6181a50msarett Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, 9418bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 94233cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein Sk4h::Store4(dst, SkFloatToHalf_finite_ftz(dr), 94333cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein SkFloatToHalf_finite_ftz(dg), 94433cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein SkFloatToHalf_finite_ftz(db), 94533cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein SK_Half1); 946200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 947200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 948cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 949200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_f16_1_opaque(void* dst, const uint32_t* src, 950c0444615ed76360f680619ad4d1f92cda6181a50msarett Sk4f& rgba, const Sk4f&, 9518bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const[3]) { 952200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett uint64_t tmp; 9538ae991e433d2c0814ea5579613f00173805ff057mtklein SkFloatToHalf_finite_ftz(rgba).store(&tmp); 954200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett tmp |= static_cast<uint64_t>(SK_Half1) << 48; 955200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett *((uint64_t*) dst) = tmp; 956200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 957200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 958cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 959200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_generic(void* dst, const uint32_t* src, 960200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, 9618bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const dstTables[3]) { 962cf7b877d62537672b67449bc96858cc1262be5f8msarett int kRShift, kGShift = 8, kBShift; 963cf7b877d62537672b67449bc96858cc1262be5f8msarett set_rb_shifts(kOrder, &kRShift, &kBShift); 964200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = Sk4f::Min(Sk4f::Max(1023.0f * dr, 0.0f), 1023.0f); 965200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = Sk4f::Min(Sk4f::Max(1023.0f * dg, 0.0f), 1023.0f); 966200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = Sk4f::Min(Sk4f::Max(1023.0f * db, 0.0f), 1023.0f); 967200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 968200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i ir = Sk4f_round(dr); 969200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i ig = Sk4f_round(dg); 970200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i ib = Sk4f_round(db); 971200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 972200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i da = Sk4i::Load(src) & 0xFF000000; 973200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 974200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett uint32_t* dst32 = (uint32_t*) dst; 975200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dst32[0] = dstTables[0][ir[0]] << kRShift 976200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | dstTables[1][ig[0]] << kGShift 977200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | dstTables[2][ib[0]] << kBShift 978200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | da[0]; 979200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dst32[1] = dstTables[0][ir[1]] << kRShift 980200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | dstTables[1][ig[1]] << kGShift 981200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | dstTables[2][ib[1]] << kBShift 982200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | da[1]; 983200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dst32[2] = dstTables[0][ir[2]] << kRShift 984200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | dstTables[1][ig[2]] << kGShift 985200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | dstTables[2][ib[2]] << kBShift 986200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | da[2]; 987200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dst32[3] = dstTables[0][ir[3]] << kRShift 988200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | dstTables[1][ig[3]] << kGShift 989200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | dstTables[2][ib[3]] << kBShift 990200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | da[3]; 991200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 992200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 993cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder> 994200877eecaba782e56a1dd9e13a92f36d7b1ba12msarettstatic inline void store_generic_1(void* dst, const uint32_t* src, 995200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f& rgba, const Sk4f&, 9968bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const dstTables[3]) { 997cf7b877d62537672b67449bc96858cc1262be5f8msarett int kRShift, kGShift = 8, kBShift; 998cf7b877d62537672b67449bc96858cc1262be5f8msarett set_rb_shifts(kOrder, &kRShift, &kBShift); 999200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba = Sk4f::Min(Sk4f::Max(1023.0f * rgba, 0.0f), 1023.0f); 1000200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1001200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4i indices = Sk4f_round(rgba); 1002200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 10039dc6cf6b8833d36c29a23d2519989b069745fcd5msarett *((uint32_t*) dst) = dstTables[0][indices[0]] << kRShift 10049dc6cf6b8833d36c29a23d2519989b069745fcd5msarett | dstTables[1][indices[1]] << kGShift 10059dc6cf6b8833d36c29a23d2519989b069745fcd5msarett | dstTables[2][indices[2]] << kBShift 1006200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett | (*src & 0xFF000000); 1007200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 1008200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1009cf7b877d62537672b67449bc96858cc1262be5f8msaretttypedef decltype(load_rgb_from_tables<kRGBA_Order> )* LoadFn; 1010cf7b877d62537672b67449bc96858cc1262be5f8msaretttypedef decltype(load_rgb_from_tables_1<kRGBA_Order>)* Load1Fn; 1011cf7b877d62537672b67449bc96858cc1262be5f8msaretttypedef decltype(store_generic<kRGBA_Order> )* StoreFn; 1012cf7b877d62537672b67449bc96858cc1262be5f8msaretttypedef decltype(store_generic_1<kRGBA_Order> )* Store1Fn; 10138bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 10148bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SkAlphaType kAlphaType, 10158bbcd5aab81dc0742c3367479c0c9d97363b1203msarett ColorSpaceMatch kCSM> 101631d097e865f266c8398f45114e4c75c0dfdef058msarettstatic inline void do_color_xform(void* dst, const void* vsrc, int len, 10178bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const float* const srcTables[3], const float matrix[16], 10188bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const dstTables[3], LoadFn load, Load1Fn load_1, 10198bbcd5aab81dc0742c3367479c0c9d97363b1203msarett StoreFn store, Store1Fn store_1, size_t sizeOfDstPixel) { 102031d097e865f266c8398f45114e4c75c0dfdef058msarett const uint32_t* src = (const uint32_t*) vsrc; 1021200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f rXgXbX, rYgYbY, rZgZbZ, rTgTbT; 1022200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett load_matrix(matrix, rXgXbX, rYgYbY, rZgZbZ, rTgTbT); 1023200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1024200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (len >= 4) { 1025200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett // Naively this would be a loop of load-transform-store, but we found it faster to 1026200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett // move the N+1th load ahead of the Nth store. We don't bother doing this for N<4. 1027200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f r, g, b, a; 1028200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett load(src, r, g, b, a, srcTables); 1029200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett src += 4; 1030200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett len -= 4; 1031200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1032200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f dr, dg, db, da; 1033200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett while (len >= 4) { 1034200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kNone_ColorSpaceMatch == kCSM) { 1035200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett transform_gamut(r, g, b, a, rXgXbX, rYgYbY, rZgZbZ, dr, dg, db, da); 1036200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett translate_gamut(rTgTbT, dr, dg, db); 1037200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } else { 1038200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = r; 1039200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = g; 1040200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = b; 1041200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett da = a; 1042200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1043200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1044200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kPremul_SkAlphaType == kAlphaType) { 1045200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett premultiply(dr, dg, db, da); 1046200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1047200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1048200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett load(src, r, g, b, a, srcTables); 1049200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 10508bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store(dst, src - 4, dr, dg, db, da, dstTables); 1051200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dst = SkTAddOffset<void>(dst, 4 * sizeOfDstPixel); 1052200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett src += 4; 1053200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett len -= 4; 1054200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1055200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1056200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kNone_ColorSpaceMatch == kCSM) { 1057200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett transform_gamut(r, g, b, a, rXgXbX, rYgYbY, rZgZbZ, dr, dg, db, da); 1058200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett translate_gamut(rTgTbT, dr, dg, db); 1059200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } else { 1060200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dr = r; 1061200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dg = g; 1062200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett db = b; 1063200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett da = a; 1064200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1065200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1066200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kPremul_SkAlphaType == kAlphaType) { 1067200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett premultiply(dr, dg, db, da); 1068200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1069200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 10708bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store(dst, src - 4, dr, dg, db, da, dstTables); 1071200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dst = SkTAddOffset<void>(dst, 4 * sizeOfDstPixel); 1072200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1073200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1074200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett while (len > 0) { 1075200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f r, g, b, a; 1076200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett load_1(src, r, g, b, a, srcTables); 1077200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1078200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett Sk4f rgba; 1079200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kNone_ColorSpaceMatch == kCSM) { 1080200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett transform_gamut_1(r, g, b, rXgXbX, rYgYbY, rZgZbZ, rgba); 1081200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett translate_gamut_1(rTgTbT, rgba); 1082200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } else { 1083200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett rgba = Sk4f(r[0], g[0], b[0], a[0]); 1084200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1085200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1086200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kPremul_SkAlphaType == kAlphaType) { 1087200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett premultiply_1(a, rgba); 1088200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1089200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 10908bbcd5aab81dc0742c3367479c0c9d97363b1203msarett store_1(dst, src, rgba, a, dstTables); 1091200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 1092200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett src += 1; 1093200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett len -= 1; 1094200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett dst = SkTAddOffset<void>(dst, sizeOfDstPixel); 1095200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1096200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett} 1097200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 10988bbcd5aab81dc0742c3367479c0c9d97363b1203msarettenum SrcFormat { 10998bbcd5aab81dc0742c3367479c0c9d97363b1203msarett kRGBA_8888_Linear_SrcFormat, 11008bbcd5aab81dc0742c3367479c0c9d97363b1203msarett kRGBA_8888_Table_SrcFormat, 1101cf7b877d62537672b67449bc96858cc1262be5f8msarett kBGRA_8888_Linear_SrcFormat, 1102cf7b877d62537672b67449bc96858cc1262be5f8msarett kBGRA_8888_Table_SrcFormat, 11038bbcd5aab81dc0742c3367479c0c9d97363b1203msarett}; 11048bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 11058bbcd5aab81dc0742c3367479c0c9d97363b1203msarettenum DstFormat { 1106cf7b877d62537672b67449bc96858cc1262be5f8msarett kRGBA_8888_Linear_DstFormat, 1107cf7b877d62537672b67449bc96858cc1262be5f8msarett kRGBA_8888_SRGB_DstFormat, 1108cf7b877d62537672b67449bc96858cc1262be5f8msarett kRGBA_8888_2Dot2_DstFormat, 1109cf7b877d62537672b67449bc96858cc1262be5f8msarett kRGBA_8888_Table_DstFormat, 1110cf7b877d62537672b67449bc96858cc1262be5f8msarett kBGRA_8888_Linear_DstFormat, 1111cf7b877d62537672b67449bc96858cc1262be5f8msarett kBGRA_8888_SRGB_DstFormat, 1112cf7b877d62537672b67449bc96858cc1262be5f8msarett kBGRA_8888_2Dot2_DstFormat, 1113cf7b877d62537672b67449bc96858cc1262be5f8msarett kBGRA_8888_Table_DstFormat, 11148bbcd5aab81dc0742c3367479c0c9d97363b1203msarett kF16_Linear_DstFormat, 1115c0444615ed76360f680619ad4d1f92cda6181a50msarett kF32_Linear_DstFormat, 11168bbcd5aab81dc0742c3367479c0c9d97363b1203msarett}; 11178bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 11188bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SrcFormat kSrc, 11198bbcd5aab81dc0742c3367479c0c9d97363b1203msarett DstFormat kDst, 11208bbcd5aab81dc0742c3367479c0c9d97363b1203msarett SkAlphaType kAlphaType, 1121cf7b877d62537672b67449bc96858cc1262be5f8msarett ColorSpaceMatch kCSM> 112231d097e865f266c8398f45114e4c75c0dfdef058msarettstatic void color_xform_RGBA(void* dst, const void* src, int len, 11238bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const float* const srcTables[3], const float matrix[16], 11248bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const dstTables[3]) { 11258bbcd5aab81dc0742c3367479c0c9d97363b1203msarett LoadFn load; 11268bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Load1Fn load_1; 1127c0444615ed76360f680619ad4d1f92cda6181a50msarett static constexpr bool loadAlpha = (kPremul_SkAlphaType == kAlphaType) || 1128c0444615ed76360f680619ad4d1f92cda6181a50msarett (kF16_Linear_DstFormat == kDst) || 1129c0444615ed76360f680619ad4d1f92cda6181a50msarett (kF32_Linear_DstFormat == kDst); 11308bbcd5aab81dc0742c3367479c0c9d97363b1203msarett switch (kSrc) { 11318bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kRGBA_8888_Linear_SrcFormat: 1132c0444615ed76360f680619ad4d1f92cda6181a50msarett if (loadAlpha) { 1133cf7b877d62537672b67449bc96858cc1262be5f8msarett load = load_rgba_linear<kRGBA_Order>; 1134cf7b877d62537672b67449bc96858cc1262be5f8msarett load_1 = load_rgba_linear_1<kRGBA_Order>; 11358bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } else { 1136cf7b877d62537672b67449bc96858cc1262be5f8msarett load = load_rgb_linear<kRGBA_Order>; 1137cf7b877d62537672b67449bc96858cc1262be5f8msarett load_1 = load_rgb_linear_1<kRGBA_Order>; 11388bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 11398bbcd5aab81dc0742c3367479c0c9d97363b1203msarett break; 11408bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kRGBA_8888_Table_SrcFormat: 1141c0444615ed76360f680619ad4d1f92cda6181a50msarett if (loadAlpha) { 1142cf7b877d62537672b67449bc96858cc1262be5f8msarett load = load_rgba_from_tables<kRGBA_Order>; 1143cf7b877d62537672b67449bc96858cc1262be5f8msarett load_1 = load_rgba_from_tables_1<kRGBA_Order>; 11448bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } else { 1145cf7b877d62537672b67449bc96858cc1262be5f8msarett load = load_rgb_from_tables<kRGBA_Order>; 1146cf7b877d62537672b67449bc96858cc1262be5f8msarett load_1 = load_rgb_from_tables_1<kRGBA_Order>; 1147cf7b877d62537672b67449bc96858cc1262be5f8msarett } 1148cf7b877d62537672b67449bc96858cc1262be5f8msarett break; 1149cf7b877d62537672b67449bc96858cc1262be5f8msarett case kBGRA_8888_Linear_SrcFormat: 1150cf7b877d62537672b67449bc96858cc1262be5f8msarett if (loadAlpha) { 1151cf7b877d62537672b67449bc96858cc1262be5f8msarett load = load_rgba_linear<kBGRA_Order>; 1152cf7b877d62537672b67449bc96858cc1262be5f8msarett load_1 = load_rgba_linear_1<kBGRA_Order>; 1153cf7b877d62537672b67449bc96858cc1262be5f8msarett } else { 1154cf7b877d62537672b67449bc96858cc1262be5f8msarett load = load_rgb_linear<kBGRA_Order>; 1155cf7b877d62537672b67449bc96858cc1262be5f8msarett load_1 = load_rgb_linear_1<kBGRA_Order>; 1156cf7b877d62537672b67449bc96858cc1262be5f8msarett } 1157cf7b877d62537672b67449bc96858cc1262be5f8msarett break; 1158cf7b877d62537672b67449bc96858cc1262be5f8msarett case kBGRA_8888_Table_SrcFormat: 1159cf7b877d62537672b67449bc96858cc1262be5f8msarett if (loadAlpha) { 1160cf7b877d62537672b67449bc96858cc1262be5f8msarett load = load_rgba_from_tables<kBGRA_Order>; 1161cf7b877d62537672b67449bc96858cc1262be5f8msarett load_1 = load_rgba_from_tables_1<kBGRA_Order>; 1162cf7b877d62537672b67449bc96858cc1262be5f8msarett } else { 1163cf7b877d62537672b67449bc96858cc1262be5f8msarett load = load_rgb_from_tables<kBGRA_Order>; 1164cf7b877d62537672b67449bc96858cc1262be5f8msarett load_1 = load_rgb_from_tables_1<kBGRA_Order>; 11658bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 11668bbcd5aab81dc0742c3367479c0c9d97363b1203msarett break; 11678bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 11688bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 11698bbcd5aab81dc0742c3367479c0c9d97363b1203msarett StoreFn store; 11708bbcd5aab81dc0742c3367479c0c9d97363b1203msarett Store1Fn store_1; 11718bbcd5aab81dc0742c3367479c0c9d97363b1203msarett size_t sizeOfDstPixel; 11728bbcd5aab81dc0742c3367479c0c9d97363b1203msarett switch (kDst) { 1173cf7b877d62537672b67449bc96858cc1262be5f8msarett case kRGBA_8888_Linear_DstFormat: 1174cf7b877d62537672b67449bc96858cc1262be5f8msarett store = store_linear<kRGBA_Order>; 1175cf7b877d62537672b67449bc96858cc1262be5f8msarett store_1 = store_linear_1<kRGBA_Order>; 1176cf7b877d62537672b67449bc96858cc1262be5f8msarett sizeOfDstPixel = 4; 1177cf7b877d62537672b67449bc96858cc1262be5f8msarett break; 1178cf7b877d62537672b67449bc96858cc1262be5f8msarett case kRGBA_8888_SRGB_DstFormat: 1179cf7b877d62537672b67449bc96858cc1262be5f8msarett store = store_srgb<kRGBA_Order>; 1180cf7b877d62537672b67449bc96858cc1262be5f8msarett store_1 = store_srgb_1<kRGBA_Order>; 1181cf7b877d62537672b67449bc96858cc1262be5f8msarett sizeOfDstPixel = 4; 1182cf7b877d62537672b67449bc96858cc1262be5f8msarett break; 1183cf7b877d62537672b67449bc96858cc1262be5f8msarett case kRGBA_8888_2Dot2_DstFormat: 1184cf7b877d62537672b67449bc96858cc1262be5f8msarett store = store_2dot2<kRGBA_Order>; 1185cf7b877d62537672b67449bc96858cc1262be5f8msarett store_1 = store_2dot2_1<kRGBA_Order>; 11868bbcd5aab81dc0742c3367479c0c9d97363b1203msarett sizeOfDstPixel = 4; 11878bbcd5aab81dc0742c3367479c0c9d97363b1203msarett break; 1188cf7b877d62537672b67449bc96858cc1262be5f8msarett case kRGBA_8888_Table_DstFormat: 1189cf7b877d62537672b67449bc96858cc1262be5f8msarett store = store_generic<kRGBA_Order>; 1190cf7b877d62537672b67449bc96858cc1262be5f8msarett store_1 = store_generic_1<kRGBA_Order>; 11918bbcd5aab81dc0742c3367479c0c9d97363b1203msarett sizeOfDstPixel = 4; 11928bbcd5aab81dc0742c3367479c0c9d97363b1203msarett break; 1193cf7b877d62537672b67449bc96858cc1262be5f8msarett case kBGRA_8888_Linear_DstFormat: 1194cf7b877d62537672b67449bc96858cc1262be5f8msarett store = store_linear<kBGRA_Order>; 1195cf7b877d62537672b67449bc96858cc1262be5f8msarett store_1 = store_linear_1<kBGRA_Order>; 11968bbcd5aab81dc0742c3367479c0c9d97363b1203msarett sizeOfDstPixel = 4; 11978bbcd5aab81dc0742c3367479c0c9d97363b1203msarett break; 1198cf7b877d62537672b67449bc96858cc1262be5f8msarett case kBGRA_8888_SRGB_DstFormat: 1199cf7b877d62537672b67449bc96858cc1262be5f8msarett store = store_srgb<kBGRA_Order>; 1200cf7b877d62537672b67449bc96858cc1262be5f8msarett store_1 = store_srgb_1<kBGRA_Order>; 1201cf7b877d62537672b67449bc96858cc1262be5f8msarett sizeOfDstPixel = 4; 1202cf7b877d62537672b67449bc96858cc1262be5f8msarett break; 1203cf7b877d62537672b67449bc96858cc1262be5f8msarett case kBGRA_8888_2Dot2_DstFormat: 1204cf7b877d62537672b67449bc96858cc1262be5f8msarett store = store_2dot2<kBGRA_Order>; 1205cf7b877d62537672b67449bc96858cc1262be5f8msarett store_1 = store_2dot2_1<kBGRA_Order>; 1206cf7b877d62537672b67449bc96858cc1262be5f8msarett sizeOfDstPixel = 4; 1207cf7b877d62537672b67449bc96858cc1262be5f8msarett break; 1208cf7b877d62537672b67449bc96858cc1262be5f8msarett case kBGRA_8888_Table_DstFormat: 1209cf7b877d62537672b67449bc96858cc1262be5f8msarett store = store_generic<kBGRA_Order>; 1210cf7b877d62537672b67449bc96858cc1262be5f8msarett store_1 = store_generic_1<kBGRA_Order>; 12118bbcd5aab81dc0742c3367479c0c9d97363b1203msarett sizeOfDstPixel = 4; 12128bbcd5aab81dc0742c3367479c0c9d97363b1203msarett break; 12138bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kF16_Linear_DstFormat: 1214cf7b877d62537672b67449bc96858cc1262be5f8msarett store = (kOpaque_SkAlphaType == kAlphaType) ? store_f16_opaque<kRGBA_Order> : 1215cf7b877d62537672b67449bc96858cc1262be5f8msarett store_f16<kRGBA_Order>; 1216cf7b877d62537672b67449bc96858cc1262be5f8msarett store_1 = (kOpaque_SkAlphaType == kAlphaType) ? store_f16_1_opaque<kRGBA_Order> : 1217cf7b877d62537672b67449bc96858cc1262be5f8msarett store_f16_1<kRGBA_Order>; 12188bbcd5aab81dc0742c3367479c0c9d97363b1203msarett sizeOfDstPixel = 8; 12198bbcd5aab81dc0742c3367479c0c9d97363b1203msarett break; 1220c0444615ed76360f680619ad4d1f92cda6181a50msarett case kF32_Linear_DstFormat: 1221cf7b877d62537672b67449bc96858cc1262be5f8msarett store = store_f32<kRGBA_Order>; 1222cf7b877d62537672b67449bc96858cc1262be5f8msarett store_1 = store_f32_1<kRGBA_Order>; 1223c0444615ed76360f680619ad4d1f92cda6181a50msarett sizeOfDstPixel = 16; 1224c0444615ed76360f680619ad4d1f92cda6181a50msarett break; 12258bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 12268bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 12278bbcd5aab81dc0742c3367479c0c9d97363b1203msarett do_color_xform<kAlphaType, kCSM> 12288bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, srcTables, matrix, dstTables, load, load_1, store, store_1, 12298bbcd5aab81dc0742c3367479c0c9d97363b1203msarett sizeOfDstPixel); 12308bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 12318bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 12323418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett/////////////////////////////////////////////////////////////////////////////////////////////////// 12330f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 12347bbda991af353fbe6b34132132d211d23a3dba8cmsarettstatic inline int num_tables(SkColorSpace* space) { 12357bbda991af353fbe6b34132132d211d23a3dba8cmsarett switch (as_CSB(space)->gammaNamed()) { 12367bbda991af353fbe6b34132132d211d23a3dba8cmsarett case kSRGB_SkGammaNamed: 12377bbda991af353fbe6b34132132d211d23a3dba8cmsarett case k2Dot2Curve_SkGammaNamed: 12387bbda991af353fbe6b34132132d211d23a3dba8cmsarett case kLinear_SkGammaNamed: 12397bbda991af353fbe6b34132132d211d23a3dba8cmsarett return 0; 12407bbda991af353fbe6b34132132d211d23a3dba8cmsarett default: { 12417bbda991af353fbe6b34132132d211d23a3dba8cmsarett const SkGammas* gammas = as_CSB(space)->gammas(); 12427bbda991af353fbe6b34132132d211d23a3dba8cmsarett SkASSERT(gammas); 12437bbda991af353fbe6b34132132d211d23a3dba8cmsarett 12447bbda991af353fbe6b34132132d211d23a3dba8cmsarett bool gammasAreMatching = (gammas->type(0) == gammas->type(1)) && 12457bbda991af353fbe6b34132132d211d23a3dba8cmsarett (gammas->data(0) == gammas->data(1)) && 12467bbda991af353fbe6b34132132d211d23a3dba8cmsarett (gammas->type(0) == gammas->type(2)) && 12477bbda991af353fbe6b34132132d211d23a3dba8cmsarett (gammas->data(0) == gammas->data(2)); 12487bbda991af353fbe6b34132132d211d23a3dba8cmsarett 12497bbda991af353fbe6b34132132d211d23a3dba8cmsarett // It's likely that each component will have the same gamma. In this case, 12507bbda991af353fbe6b34132132d211d23a3dba8cmsarett // we only need to build one table. 12517bbda991af353fbe6b34132132d211d23a3dba8cmsarett return gammasAreMatching ? 1 : 3; 12527bbda991af353fbe6b34132132d211d23a3dba8cmsarett } 12537bbda991af353fbe6b34132132d211d23a3dba8cmsarett } 12547bbda991af353fbe6b34132132d211d23a3dba8cmsarett} 12557bbda991af353fbe6b34132132d211d23a3dba8cmsarett 12568bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM> 12578bbcd5aab81dc0742c3367479c0c9d97363b1203msarettSkColorSpaceXform_Base<kSrc, kDst, kCSM> 12584be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarett::SkColorSpaceXform_Base(SkColorSpace* srcSpace, const SkMatrix44& srcToDst, SkColorSpace* dstSpace) 12593418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett : fColorLUT(sk_ref_sp((SkColorLookUpTable*) as_CSB(srcSpace)->colorLUT())) 12603418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett{ 1261de68d6c4616d86621373d88100002ddfdb9c08e3brianosman srcToDst.asColMajorf(fSrcToDst); 12627bbda991af353fbe6b34132132d211d23a3dba8cmsarett 12634be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarett const int numSrcTables = num_tables(srcSpace); 12644be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarett const int numDstTables = num_tables(dstSpace); 12657bbda991af353fbe6b34132132d211d23a3dba8cmsarett const size_t srcTableBytes = numSrcTables * 256 * sizeof(float); 12667bbda991af353fbe6b34132132d211d23a3dba8cmsarett const size_t dstTableBytes = numDstTables * kDstGammaTableSize * sizeof(uint8_t); 12677bbda991af353fbe6b34132132d211d23a3dba8cmsarett fStorage.reset(srcTableBytes + dstTableBytes); 12687bbda991af353fbe6b34132132d211d23a3dba8cmsarett float* srcStorage = (float*) fStorage.get(); 12697bbda991af353fbe6b34132132d211d23a3dba8cmsarett uint8_t* dstStorage = SkTAddOffset<uint8_t>(fStorage.get(), srcTableBytes); 12707bbda991af353fbe6b34132132d211d23a3dba8cmsarett 12717bbda991af353fbe6b34132132d211d23a3dba8cmsarett const bool srcGammasAreMatching = (1 >= numSrcTables); 12727bbda991af353fbe6b34132132d211d23a3dba8cmsarett const bool dstGammasAreMatching = (1 >= numDstTables); 12737bbda991af353fbe6b34132132d211d23a3dba8cmsarett build_gamma_tables(fSrcGammaTables, srcStorage, 256, srcSpace, kToLinear, srcGammasAreMatching); 12747bbda991af353fbe6b34132132d211d23a3dba8cmsarett build_gamma_tables(fDstGammaTables, dstStorage, kDstGammaTableSize, dstSpace, kFromLinear, 12757bbda991af353fbe6b34132132d211d23a3dba8cmsarett dstGammasAreMatching); 12763418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett} 1277dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 12787bbda991af353fbe6b34132132d211d23a3dba8cmsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 12797bbda991af353fbe6b34132132d211d23a3dba8cmsarett 1280cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <SrcFormat kSrc, DstFormat kDst, ColorSpaceMatch kCSM> 128131d097e865f266c8398f45114e4c75c0dfdef058msarettstatic inline bool apply_set_alpha(void* dst, const void* src, int len, SkAlphaType alphaType, 12828bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const float* const srcTables[3], const float matrix[16], 12838bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const uint8_t* const dstTables[3]) { 12848bbcd5aab81dc0742c3367479c0c9d97363b1203msarett switch (alphaType) { 12858bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kOpaque_SkAlphaType: 128631d097e865f266c8398f45114e4c75c0dfdef058msarett color_xform_RGBA<kSrc, kDst, kOpaque_SkAlphaType, kCSM> 12878bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, srcTables, matrix, dstTables); 128831d097e865f266c8398f45114e4c75c0dfdef058msarett return true; 12898bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kPremul_SkAlphaType: 129031d097e865f266c8398f45114e4c75c0dfdef058msarett color_xform_RGBA<kSrc, kDst, kPremul_SkAlphaType, kCSM> 12918bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, srcTables, matrix, dstTables); 129231d097e865f266c8398f45114e4c75c0dfdef058msarett return true; 12938bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kUnpremul_SkAlphaType: 129431d097e865f266c8398f45114e4c75c0dfdef058msarett color_xform_RGBA<kSrc, kDst, kUnpremul_SkAlphaType, kCSM> 12958bbcd5aab81dc0742c3367479c0c9d97363b1203msarett (dst, src, len, srcTables, matrix, dstTables); 129631d097e865f266c8398f45114e4c75c0dfdef058msarett return true; 12978bbcd5aab81dc0742c3367479c0c9d97363b1203msarett default: 129831d097e865f266c8398f45114e4c75c0dfdef058msarett return false; 12998bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 13008bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 13018bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 1302cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <SrcGamma kSrc, DstFormat kDst, ColorSpaceMatch kCSM> 130331d097e865f266c8398f45114e4c75c0dfdef058msarettstatic inline bool apply_set_src(void* dst, const void* src, int len, SkAlphaType alphaType, 13048bbcd5aab81dc0742c3367479c0c9d97363b1203msarett const float* const srcTables[3], const float matrix[16], 1305cf7b877d62537672b67449bc96858cc1262be5f8msarett const uint8_t* const dstTables[3], 1306cf7b877d62537672b67449bc96858cc1262be5f8msarett SkColorSpaceXform::ColorFormat srcColorFormat) { 1307cf7b877d62537672b67449bc96858cc1262be5f8msarett switch (srcColorFormat) { 1308cf7b877d62537672b67449bc96858cc1262be5f8msarett case SkColorSpaceXform::kRGBA_8888_ColorFormat: 1309cf7b877d62537672b67449bc96858cc1262be5f8msarett switch (kSrc) { 1310cf7b877d62537672b67449bc96858cc1262be5f8msarett case kLinear_SrcGamma: 1311cf7b877d62537672b67449bc96858cc1262be5f8msarett return apply_set_alpha<kRGBA_8888_Linear_SrcFormat, kDst, kCSM> 1312cf7b877d62537672b67449bc96858cc1262be5f8msarett (dst, src, len, alphaType, nullptr, matrix, dstTables); 1313cf7b877d62537672b67449bc96858cc1262be5f8msarett case kTable_SrcGamma: 1314cf7b877d62537672b67449bc96858cc1262be5f8msarett return apply_set_alpha<kRGBA_8888_Table_SrcFormat, kDst, kCSM> 1315cf7b877d62537672b67449bc96858cc1262be5f8msarett (dst, src, len, alphaType, srcTables, matrix, dstTables); 1316cf7b877d62537672b67449bc96858cc1262be5f8msarett } 1317cf7b877d62537672b67449bc96858cc1262be5f8msarett case SkColorSpaceXform::kBGRA_8888_ColorFormat: 1318cf7b877d62537672b67449bc96858cc1262be5f8msarett switch (kSrc) { 1319cf7b877d62537672b67449bc96858cc1262be5f8msarett case kLinear_SrcGamma: 1320cf7b877d62537672b67449bc96858cc1262be5f8msarett return apply_set_alpha<kBGRA_8888_Linear_SrcFormat, kDst, kCSM> 1321cf7b877d62537672b67449bc96858cc1262be5f8msarett (dst, src, len, alphaType, nullptr, matrix, dstTables); 1322cf7b877d62537672b67449bc96858cc1262be5f8msarett case kTable_SrcGamma: 1323cf7b877d62537672b67449bc96858cc1262be5f8msarett return apply_set_alpha<kBGRA_8888_Table_SrcFormat, kDst, kCSM> 1324cf7b877d62537672b67449bc96858cc1262be5f8msarett (dst, src, len, alphaType, srcTables, matrix, dstTables); 1325cf7b877d62537672b67449bc96858cc1262be5f8msarett } 1326cf7b877d62537672b67449bc96858cc1262be5f8msarett default: 132731d097e865f266c8398f45114e4c75c0dfdef058msarett return false; 13288bbcd5aab81dc0742c3367479c0c9d97363b1203msarett } 13298bbcd5aab81dc0742c3367479c0c9d97363b1203msarett} 13308bbcd5aab81dc0742c3367479c0c9d97363b1203msarett 13318bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM> 133231d097e865f266c8398f45114e4c75c0dfdef058msarettbool SkColorSpaceXform_Base<kSrc, kDst, kCSM> 133331d097e865f266c8398f45114e4c75c0dfdef058msarett::onApply(ColorFormat dstColorFormat, void* dst, ColorFormat srcColorFormat, const void* src, 133431d097e865f266c8398f45114e4c75c0dfdef058msarett int len, SkAlphaType alphaType) const 13353418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett{ 1336200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett if (kFull_ColorSpaceMatch == kCSM) { 13378bbcd5aab81dc0742c3367479c0c9d97363b1203msarett switch (alphaType) { 1338200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett case kPremul_SkAlphaType: 1339200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett // We can't skip the xform since we need to perform a premultiply in the 1340200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett // linear space. 1341200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett break; 1342200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett default: 1343c0444615ed76360f680619ad4d1f92cda6181a50msarett switch (dstColorFormat) { 1344c0444615ed76360f680619ad4d1f92cda6181a50msarett case kRGBA_8888_ColorFormat: 134531d097e865f266c8398f45114e4c75c0dfdef058msarett memcpy(dst, src, len * sizeof(uint32_t)); 134631d097e865f266c8398f45114e4c75c0dfdef058msarett return true; 1347c0444615ed76360f680619ad4d1f92cda6181a50msarett case kBGRA_8888_ColorFormat: 134831d097e865f266c8398f45114e4c75c0dfdef058msarett SkOpts::RGBA_to_BGRA((uint32_t*) dst, src, len); 134931d097e865f266c8398f45114e4c75c0dfdef058msarett return true; 1350c0444615ed76360f680619ad4d1f92cda6181a50msarett case kRGBA_F16_ColorFormat: 1351c0444615ed76360f680619ad4d1f92cda6181a50msarett case kRGBA_F32_ColorFormat: 1352c0444615ed76360f680619ad4d1f92cda6181a50msarett // There's still work to do to xform to linear floats. 1353200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett break; 1354200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett default: 135531d097e865f266c8398f45114e4c75c0dfdef058msarett return false; 1356200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1357200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1358200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett } 1359200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett 13603418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett#if defined(GOOGLE3) 1361c6cc28c35be30f9ea144f433f3f04273674e29edraftias // Stack frame size is limited in GOOGLE3. 1362c6cc28c35be30f9ea144f433f3f04273674e29edraftias SkAutoSMalloc<256 * sizeof(uint32_t)> storage; 13633418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett#else 1364c6cc28c35be30f9ea144f433f3f04273674e29edraftias SkAutoSMalloc<1024 * sizeof(uint32_t)> storage; 13653418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett#endif 1366c6cc28c35be30f9ea144f433f3f04273674e29edraftias if (fColorLUT) { 1367c6cc28c35be30f9ea144f433f3f04273674e29edraftias size_t storageBytes = len * sizeof(uint32_t); 1368c6cc28c35be30f9ea144f433f3f04273674e29edraftias storage.reset(storageBytes); 1369d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett handle_color_lut((uint32_t*) storage.get(), src, len, fColorLUT.get()); 1370d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett src = (const uint32_t*) storage.get(); 13713418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett } 13723418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett 1373c0444615ed76360f680619ad4d1f92cda6181a50msarett switch (dstColorFormat) { 1374c0444615ed76360f680619ad4d1f92cda6181a50msarett case kRGBA_8888_ColorFormat: 13758bbcd5aab81dc0742c3367479c0c9d97363b1203msarett switch (kDst) { 13768bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kLinear_DstGamma: 1377cf7b877d62537672b67449bc96858cc1262be5f8msarett return apply_set_src<kSrc, kRGBA_8888_Linear_DstFormat, kCSM> 1378cf7b877d62537672b67449bc96858cc1262be5f8msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr, 1379cf7b877d62537672b67449bc96858cc1262be5f8msarett srcColorFormat); 13808bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kSRGB_DstGamma: 1381cf7b877d62537672b67449bc96858cc1262be5f8msarett return apply_set_src<kSrc, kRGBA_8888_SRGB_DstFormat, kCSM> 1382cf7b877d62537672b67449bc96858cc1262be5f8msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr, 1383cf7b877d62537672b67449bc96858cc1262be5f8msarett srcColorFormat); 13848bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case k2Dot2_DstGamma: 1385cf7b877d62537672b67449bc96858cc1262be5f8msarett return apply_set_src<kSrc, kRGBA_8888_2Dot2_DstFormat, kCSM> 1386cf7b877d62537672b67449bc96858cc1262be5f8msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr, 1387cf7b877d62537672b67449bc96858cc1262be5f8msarett srcColorFormat); 13888bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kTable_DstGamma: 1389cf7b877d62537672b67449bc96858cc1262be5f8msarett return apply_set_src<kSrc, kRGBA_8888_Table_DstFormat, kCSM> 1390cf7b877d62537672b67449bc96858cc1262be5f8msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, fDstGammaTables, 1391cf7b877d62537672b67449bc96858cc1262be5f8msarett srcColorFormat); 1392d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett } 1393c0444615ed76360f680619ad4d1f92cda6181a50msarett case kBGRA_8888_ColorFormat: 13948bbcd5aab81dc0742c3367479c0c9d97363b1203msarett switch (kDst) { 13958bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kLinear_DstGamma: 1396cf7b877d62537672b67449bc96858cc1262be5f8msarett return apply_set_src<kSrc, kBGRA_8888_Linear_DstFormat, kCSM> 1397cf7b877d62537672b67449bc96858cc1262be5f8msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr, 1398cf7b877d62537672b67449bc96858cc1262be5f8msarett srcColorFormat); 13998bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kSRGB_DstGamma: 1400cf7b877d62537672b67449bc96858cc1262be5f8msarett return apply_set_src<kSrc, kBGRA_8888_SRGB_DstFormat, kCSM> 1401cf7b877d62537672b67449bc96858cc1262be5f8msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr, 1402cf7b877d62537672b67449bc96858cc1262be5f8msarett srcColorFormat); 14038bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case k2Dot2_DstGamma: 1404cf7b877d62537672b67449bc96858cc1262be5f8msarett return apply_set_src<kSrc, kBGRA_8888_2Dot2_DstFormat, kCSM> 1405cf7b877d62537672b67449bc96858cc1262be5f8msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr, 1406cf7b877d62537672b67449bc96858cc1262be5f8msarett srcColorFormat); 14078bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kTable_DstGamma: 1408cf7b877d62537672b67449bc96858cc1262be5f8msarett return apply_set_src<kSrc, kBGRA_8888_Table_DstFormat, kCSM> 1409cf7b877d62537672b67449bc96858cc1262be5f8msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, fDstGammaTables, 1410cf7b877d62537672b67449bc96858cc1262be5f8msarett srcColorFormat); 1411d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett } 1412c0444615ed76360f680619ad4d1f92cda6181a50msarett case kRGBA_F16_ColorFormat: 14138bbcd5aab81dc0742c3367479c0c9d97363b1203msarett switch (kDst) { 14148bbcd5aab81dc0742c3367479c0c9d97363b1203msarett case kLinear_DstGamma: 1415cf7b877d62537672b67449bc96858cc1262be5f8msarett return apply_set_src<kSrc, kF16_Linear_DstFormat, kCSM> 1416cf7b877d62537672b67449bc96858cc1262be5f8msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr, 1417cf7b877d62537672b67449bc96858cc1262be5f8msarett srcColorFormat); 1418d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett default: 141931d097e865f266c8398f45114e4c75c0dfdef058msarett return false; 1420d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett } 1421c0444615ed76360f680619ad4d1f92cda6181a50msarett case kRGBA_F32_ColorFormat: 1422c0444615ed76360f680619ad4d1f92cda6181a50msarett switch (kDst) { 1423c0444615ed76360f680619ad4d1f92cda6181a50msarett case kLinear_DstGamma: 1424cf7b877d62537672b67449bc96858cc1262be5f8msarett return apply_set_src<kSrc, kF32_Linear_DstFormat, kCSM> 1425cf7b877d62537672b67449bc96858cc1262be5f8msarett (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr, 1426cf7b877d62537672b67449bc96858cc1262be5f8msarett srcColorFormat); 1427c0444615ed76360f680619ad4d1f92cda6181a50msarett default: 142831d097e865f266c8398f45114e4c75c0dfdef058msarett return false; 1429c0444615ed76360f680619ad4d1f92cda6181a50msarett } 1430d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett default: 143131d097e865f266c8398f45114e4c75c0dfdef058msarett return false; 1432d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett } 14339ce3a543c92a73e6daca420defc042886b3f2019msarett} 14349dc6cf6b8833d36c29a23d2519989b069745fcd5msarett 14357bbda991af353fbe6b34132132d211d23a3dba8cmsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 14367bbda991af353fbe6b34132132d211d23a3dba8cmsarett 14374be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarettstd::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace* space) { 14389dc6cf6b8833d36c29a23d2519989b069745fcd5msarett return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base 14398bbcd5aab81dc0742c3367479c0c9d97363b1203msarett <kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch> 14409dc6cf6b8833d36c29a23d2519989b069745fcd5msarett (space, SkMatrix::I(), space)); 14419dc6cf6b8833d36c29a23d2519989b069745fcd5msarett} 1442