| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * Copyright 2016 Google Inc. | 2  * Copyright 2016 Google Inc. | 
| 3  * | 3  * | 
| 4  * Use of this source code is governed by a BSD-style license that can be | 4  * Use of this source code is governed by a BSD-style license that can be | 
| 5  * found in the LICENSE file. | 5  * found in the LICENSE file. | 
| 6  */ | 6  */ | 
| 7 | 7 | 
| 8 #include "SkColorSpace.h" | 8 #include "SkColorSpace.h" | 
| 9 #include "SkColorSpace_Base.h" | 9 #include "SkColorSpace_Base.h" | 
| 10 #include "SkEndian.h" | 10 #include "SkEndian.h" | 
| 11 #include "SkOnce.h" | 11 #include "SkOnce.h" | 
| 12 | 12 | 
|  | 13 #define SkColorSpacePrintf(...) | 
|  | 14 | 
| 13 static bool color_space_almost_equal(float a, float b) { | 15 static bool color_space_almost_equal(float a, float b) { | 
| 14     return SkTAbs(a - b) < 0.01f; | 16     return SkTAbs(a - b) < 0.01f; | 
| 15 } | 17 } | 
| 16 | 18 | 
| 17 ////////////////////////////////////////////////////////////////////////////////
      ////////////////// | 19 ////////////////////////////////////////////////////////////////////////////////
      ////////////////// | 
| 18 | 20 | 
| 19 SkColorSpace::SkColorSpace(GammaNamed gammaNamed, const SkMatrix44& toXYZD50, Na
      med named) | 21 SkColorSpace::SkColorSpace(GammaNamed gammaNamed, const SkMatrix44& toXYZD50, Na
      med named) | 
| 20     : fGammaNamed(gammaNamed) | 22     : fGammaNamed(gammaNamed) | 
| 21     , fToXYZD50(toXYZD50) | 23     , fToXYZD50(toXYZD50) | 
| 22     , fNamed(named) | 24     , fNamed(named) | 
| 23 {} | 25 {} | 
| 24 | 26 | 
| 25 SkColorSpace_Base::SkColorSpace_Base(sk_sp<SkGammas> gammas, const SkMatrix44& t
      oXYZD50, | 27 SkColorSpace_Base::SkColorSpace_Base(GammaNamed gammaNamed, const SkMatrix44& to
      XYZD50, Named named, | 
| 26                                      Named named, sk_sp<SkData> profileData) | 28                                      sk_sp<SkData> profileData) | 
| 27     : INHERITED(kNonStandard_GammaNamed, toXYZD50, named) | 29     : INHERITED(gammaNamed, toXYZD50, named) | 
| 28     , fGammas(std::move(gammas)) | 30     , fGammas(nullptr) | 
| 29     , fProfileData(std::move(profileData)) | 31     , fProfileData(std::move(profileData)) | 
| 30 {} | 32 {} | 
| 31 | 33 | 
| 32 SkColorSpace_Base::SkColorSpace_Base(sk_sp<SkGammas> gammas, GammaNamed gammaNam
      ed, |  | 
| 33                                      const SkMatrix44& toXYZD50, Named named, |  | 
| 34                                      sk_sp<SkData> profileData) |  | 
| 35     : INHERITED(gammaNamed, toXYZD50, named) |  | 
| 36     , fGammas(std::move(gammas)) |  | 
| 37     , fProfileData(std::move(profileData)) |  | 
| 38 {} |  | 
| 39 |  | 
| 40 SkColorSpace_Base::SkColorSpace_Base(SkColorLookUpTable* colorLUT, sk_sp<SkGamma
      s> gammas, | 34 SkColorSpace_Base::SkColorSpace_Base(SkColorLookUpTable* colorLUT, sk_sp<SkGamma
      s> gammas, | 
| 41                                      const SkMatrix44& toXYZD50, sk_sp<SkData> p
      rofileData) | 35                                      const SkMatrix44& toXYZD50, sk_sp<SkData> p
      rofileData) | 
| 42     : INHERITED(kNonStandard_GammaNamed, toXYZD50, kUnknown_Named) | 36     : INHERITED(kNonStandard_GammaNamed, toXYZD50, kUnknown_Named) | 
| 43     , fColorLUT(colorLUT) | 37     , fColorLUT(colorLUT) | 
| 44     , fGammas(std::move(gammas)) | 38     , fGammas(std::move(gammas)) | 
| 45     , fProfileData(std::move(profileData)) | 39     , fProfileData(std::move(profileData)) | 
| 46 {} | 40 {} | 
| 47 | 41 | 
| 48 static constexpr float gSRGB_toXYZD50[] { | 42 static constexpr float gSRGB_toXYZD50[] { | 
| 49     0.4358f, 0.2224f, 0.0139f,    // * R | 43     0.4358f, 0.2224f, 0.0139f,    // * R | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
| 75            color_space_almost_equal(toXYZD50.getFloat(2, 2), standard[8]) && | 69            color_space_almost_equal(toXYZD50.getFloat(2, 2), standard[8]) && | 
| 76            color_space_almost_equal(toXYZD50.getFloat(0, 3), 0.0f) && | 70            color_space_almost_equal(toXYZD50.getFloat(0, 3), 0.0f) && | 
| 77            color_space_almost_equal(toXYZD50.getFloat(1, 3), 0.0f) && | 71            color_space_almost_equal(toXYZD50.getFloat(1, 3), 0.0f) && | 
| 78            color_space_almost_equal(toXYZD50.getFloat(2, 3), 0.0f) && | 72            color_space_almost_equal(toXYZD50.getFloat(2, 3), 0.0f) && | 
| 79            color_space_almost_equal(toXYZD50.getFloat(3, 0), 0.0f) && | 73            color_space_almost_equal(toXYZD50.getFloat(3, 0), 0.0f) && | 
| 80            color_space_almost_equal(toXYZD50.getFloat(3, 1), 0.0f) && | 74            color_space_almost_equal(toXYZD50.getFloat(3, 1), 0.0f) && | 
| 81            color_space_almost_equal(toXYZD50.getFloat(3, 2), 0.0f) && | 75            color_space_almost_equal(toXYZD50.getFloat(3, 2), 0.0f) && | 
| 82            color_space_almost_equal(toXYZD50.getFloat(3, 3), 1.0f); | 76            color_space_almost_equal(toXYZD50.getFloat(3, 3), 1.0f); | 
| 83 } | 77 } | 
| 84 | 78 | 
| 85 static SkOnce g2Dot2CurveGammasOnce; | 79 static void set_gamma_value(SkGammaCurve* gamma, float value) { | 
| 86 static SkGammas* g2Dot2CurveGammas; | 80     if (color_space_almost_equal(2.2f, value)) { | 
| 87 static SkOnce gLinearGammasOnce; | 81         gamma->fNamed = SkColorSpace::k2Dot2Curve_GammaNamed; | 
| 88 static SkGammas* gLinearGammas; | 82     } else if (color_space_almost_equal(1.0f, value)) { | 
| 89 | 83         gamma->fNamed = SkColorSpace::kLinear_GammaNamed; | 
| 90 sk_sp<SkColorSpace> SkColorSpace::NewRGB(const float gammaVals[3], const SkMatri
      x44& toXYZD50) { | 84     } else if (color_space_almost_equal(0.0f, value)) { | 
| 91     return SkColorSpace_Base::NewRGB(gammaVals, toXYZD50, nullptr); | 85         SkColorSpacePrintf("Treating invalid zero gamma as linear."); | 
|  | 86         gamma->fNamed = SkColorSpace::kLinear_GammaNamed; | 
|  | 87     } else { | 
|  | 88         gamma->fValue = value; | 
|  | 89     } | 
| 92 } | 90 } | 
| 93 | 91 | 
| 94 sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(const float gammaVals[3], const Sk
      Matrix44& toXYZD50, | 92 sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(float values[3], const SkMatrix44&
       toXYZD50) { | 
| 95                                               sk_sp<SkData> profileData) { | 93     SkGammaCurve curves[3]; | 
| 96     sk_sp<SkGammas> gammas = nullptr; | 94     set_gamma_value(&curves[0], values[0]); | 
| 97     GammaNamed gammaNamed = kNonStandard_GammaNamed; | 95     set_gamma_value(&curves[1], values[1]); | 
|  | 96     set_gamma_value(&curves[2], values[2]); | 
| 98 | 97 | 
| 99     // Check if we really have sRGB or Adobe RGB | 98     GammaNamed gammaNamed = SkGammas::Named(curves); | 
| 100     if (color_space_almost_equal(2.2f, gammaVals[0]) && | 99     if (kNonStandard_GammaNamed == gammaNamed) { | 
| 101         color_space_almost_equal(2.2f, gammaVals[1]) && | 100         sk_sp<SkGammas> gammas(new SkGammas(std::move(curves[0]), std::move(curv
      es[1]), | 
| 102         color_space_almost_equal(2.2f, gammaVals[2])) | 101                                             std::move(curves[2]))); | 
| 103     { | 102         return sk_sp<SkColorSpace>(new SkColorSpace_Base(nullptr, gammas, toXYZD
      50, nullptr)); | 
| 104         g2Dot2CurveGammasOnce([] { |  | 
| 105                 g2Dot2CurveGammas = new SkGammas(2.2f, 2.2f, 2.2f); |  | 
| 106         }); |  | 
| 107         gammas = sk_ref_sp(g2Dot2CurveGammas); |  | 
| 108         gammaNamed = k2Dot2Curve_GammaNamed; |  | 
| 109 |  | 
| 110         if (xyz_almost_equal(toXYZD50, gSRGB_toXYZD50)) { |  | 
| 111             return SkColorSpace::NewNamed(kSRGB_Named); |  | 
| 112         } else if (xyz_almost_equal(toXYZD50, gAdobeRGB_toXYZD50)) { |  | 
| 113             return SkColorSpace::NewNamed(kAdobeRGB_Named); |  | 
| 114         } |  | 
| 115     } else if (color_space_almost_equal(1.0f, gammaVals[0]) && |  | 
| 116                color_space_almost_equal(1.0f, gammaVals[1]) && |  | 
| 117                color_space_almost_equal(1.0f, gammaVals[2])) |  | 
| 118     { |  | 
| 119         gLinearGammasOnce([] { |  | 
| 120             gLinearGammas = new SkGammas(1.0f, 1.0f, 1.0f); |  | 
| 121         }); |  | 
| 122         gammas = sk_ref_sp(gLinearGammas); |  | 
| 123         gammaNamed = kLinear_GammaNamed; |  | 
| 124     } | 103     } | 
| 125 | 104 | 
| 126     if (!gammas) { | 105     return SkColorSpace_Base::NewRGB(gammaNamed, toXYZD50, nullptr); | 
| 127         gammas = sk_sp<SkGammas>(new SkGammas(gammaVals[0], gammaVals[1], gammaV
      als[2])); | 106 } | 
|  | 107 | 
|  | 108 sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(GammaNamed gammaNamed, const SkMat
      rix44& toXYZD50, | 
|  | 109                                               sk_sp<SkData> profileData) { | 
|  | 110     switch (gammaNamed) { | 
|  | 111         case kSRGB_GammaNamed: | 
|  | 112             if (xyz_almost_equal(toXYZD50, gSRGB_toXYZD50)) { | 
|  | 113                 return SkColorSpace::NewNamed(kSRGB_Named); | 
|  | 114             } | 
|  | 115             break; | 
|  | 116         case k2Dot2Curve_GammaNamed: | 
|  | 117             if (xyz_almost_equal(toXYZD50, gAdobeRGB_toXYZD50)) { | 
|  | 118                 return SkColorSpace::NewNamed(kAdobeRGB_Named); | 
|  | 119             } | 
|  | 120             break; | 
|  | 121         case kNonStandard_GammaNamed: | 
|  | 122             // This is not allowed. | 
|  | 123             return nullptr; | 
|  | 124         default: | 
|  | 125             break; | 
| 128     } | 126     } | 
| 129     return sk_sp<SkColorSpace>(new SkColorSpace_Base(gammas, gammaNamed, toXYZD5
      0, kUnknown_Named, | 127 | 
| 130                                                      std::move(profileData))); | 128     return sk_sp<SkColorSpace>(new SkColorSpace_Base(gammaNamed, toXYZD50, kUnkn
      own_Named, | 
|  | 129                                                      profileData)); | 
|  | 130 } | 
|  | 131 | 
|  | 132 sk_sp<SkColorSpace> SkColorSpace::NewRGB(GammaNamed gammaNamed, const SkMatrix44
      & toXYZD50) { | 
|  | 133     return SkColorSpace_Base::NewRGB(gammaNamed, toXYZD50, nullptr); | 
| 131 } | 134 } | 
| 132 | 135 | 
| 133 sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) { | 136 sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) { | 
| 134     static SkOnce sRGBOnce; | 137     static SkOnce sRGBOnce; | 
| 135     static SkColorSpace* sRGB; | 138     static SkColorSpace* sRGB; | 
| 136     static SkOnce adobeRGBOnce; | 139     static SkOnce adobeRGBOnce; | 
| 137     static SkColorSpace* adobeRGB; | 140     static SkColorSpace* adobeRGB; | 
| 138 | 141 | 
| 139     switch (named) { | 142     switch (named) { | 
| 140         case kSRGB_Named: { | 143         case kSRGB_Named: { | 
| 141             g2Dot2CurveGammasOnce([] { |  | 
| 142                 g2Dot2CurveGammas = new SkGammas(2.2f, 2.2f, 2.2f); |  | 
| 143             }); |  | 
| 144 |  | 
| 145             sRGBOnce([] { | 144             sRGBOnce([] { | 
| 146                 SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor); | 145                 SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor); | 
| 147                 srgbToxyzD50.set3x3ColMajorf(gSRGB_toXYZD50); | 146                 srgbToxyzD50.set3x3ColMajorf(gSRGB_toXYZD50); | 
| 148                 sRGB = new SkColorSpace_Base(sk_ref_sp(g2Dot2CurveGammas), k2Dot
      2Curve_GammaNamed, | 147                 sRGB = new SkColorSpace_Base(kSRGB_GammaNamed, srgbToxyzD50, kSR
      GB_Named, nullptr); | 
| 149                                              srgbToxyzD50, kSRGB_Named, nullptr)
      ; |  | 
| 150             }); | 148             }); | 
| 151             return sk_ref_sp(sRGB); | 149             return sk_ref_sp(sRGB); | 
| 152         } | 150         } | 
| 153         case kAdobeRGB_Named: { | 151         case kAdobeRGB_Named: { | 
| 154             g2Dot2CurveGammasOnce([] { |  | 
| 155                 g2Dot2CurveGammas = new SkGammas(2.2f, 2.2f, 2.2f); |  | 
| 156             }); |  | 
| 157 |  | 
| 158             adobeRGBOnce([] { | 152             adobeRGBOnce([] { | 
| 159                 SkMatrix44 adobergbToxyzD50(SkMatrix44::kUninitialized_Construct
      or); | 153                 SkMatrix44 adobergbToxyzD50(SkMatrix44::kUninitialized_Construct
      or); | 
| 160                 adobergbToxyzD50.set3x3ColMajorf(gAdobeRGB_toXYZD50); | 154                 adobergbToxyzD50.set3x3ColMajorf(gAdobeRGB_toXYZD50); | 
| 161                 adobeRGB = new SkColorSpace_Base(sk_ref_sp(g2Dot2CurveGammas), | 155                 adobeRGB = new SkColorSpace_Base(k2Dot2Curve_GammaNamed, adoberg
      bToxyzD50, | 
| 162                                                  k2Dot2Curve_GammaNamed, adoberg
      bToxyzD50, |  | 
| 163                                                  kAdobeRGB_Named, nullptr); | 156                                                  kAdobeRGB_Named, nullptr); | 
| 164             }); | 157             }); | 
| 165             return sk_ref_sp(adobeRGB); | 158             return sk_ref_sp(adobeRGB); | 
| 166         } | 159         } | 
| 167         default: | 160         default: | 
| 168             break; | 161             break; | 
| 169     } | 162     } | 
| 170     return nullptr; | 163     return nullptr; | 
| 171 } | 164 } | 
| 172 | 165 | 
| 173 ////////////////////////////////////////////////////////////////////////////////
      /////////////////// | 166 ////////////////////////////////////////////////////////////////////////////////
      /////////////////// | 
| 174 | 167 | 
| 175 #include "SkFixed.h" | 168 #include "SkFixed.h" | 
| 176 #include "SkTemplates.h" | 169 #include "SkTemplates.h" | 
| 177 | 170 | 
| 178 #define SkColorSpacePrintf(...) |  | 
| 179 |  | 
| 180 #define return_if_false(pred, msg)                                   \ | 171 #define return_if_false(pred, msg)                                   \ | 
| 181     do {                                                             \ | 172     do {                                                             \ | 
| 182         if (!(pred)) {                                               \ | 173         if (!(pred)) {                                               \ | 
| 183             SkColorSpacePrintf("Invalid ICC Profile: %s.\n", (msg)); \ | 174             SkColorSpacePrintf("Invalid ICC Profile: %s.\n", (msg)); \ | 
| 184             return false;                                            \ | 175             return false;                                            \ | 
| 185         }                                                            \ | 176         }                                                            \ | 
| 186     } while (0) | 177     } while (0) | 
| 187 | 178 | 
| 188 #define return_null(msg)                                             \ | 179 #define return_null(msg)                                             \ | 
| 189     do {                                                             \ | 180     do {                                                             \ | 
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 363 }; | 354 }; | 
| 364 | 355 | 
| 365 static constexpr uint32_t kTAG_rXYZ = SkSetFourByteTag('r', 'X', 'Y', 'Z'); | 356 static constexpr uint32_t kTAG_rXYZ = SkSetFourByteTag('r', 'X', 'Y', 'Z'); | 
| 366 static constexpr uint32_t kTAG_gXYZ = SkSetFourByteTag('g', 'X', 'Y', 'Z'); | 357 static constexpr uint32_t kTAG_gXYZ = SkSetFourByteTag('g', 'X', 'Y', 'Z'); | 
| 367 static constexpr uint32_t kTAG_bXYZ = SkSetFourByteTag('b', 'X', 'Y', 'Z'); | 358 static constexpr uint32_t kTAG_bXYZ = SkSetFourByteTag('b', 'X', 'Y', 'Z'); | 
| 368 static constexpr uint32_t kTAG_rTRC = SkSetFourByteTag('r', 'T', 'R', 'C'); | 359 static constexpr uint32_t kTAG_rTRC = SkSetFourByteTag('r', 'T', 'R', 'C'); | 
| 369 static constexpr uint32_t kTAG_gTRC = SkSetFourByteTag('g', 'T', 'R', 'C'); | 360 static constexpr uint32_t kTAG_gTRC = SkSetFourByteTag('g', 'T', 'R', 'C'); | 
| 370 static constexpr uint32_t kTAG_bTRC = SkSetFourByteTag('b', 'T', 'R', 'C'); | 361 static constexpr uint32_t kTAG_bTRC = SkSetFourByteTag('b', 'T', 'R', 'C'); | 
| 371 static constexpr uint32_t kTAG_A2B0 = SkSetFourByteTag('A', '2', 'B', '0'); | 362 static constexpr uint32_t kTAG_A2B0 = SkSetFourByteTag('A', '2', 'B', '0'); | 
| 372 | 363 | 
| 373 bool load_xyz(float dst[3], const uint8_t* src, size_t len) { | 364 static bool load_xyz(float dst[3], const uint8_t* src, size_t len) { | 
| 374     if (len < 20) { | 365     if (len < 20) { | 
| 375         SkColorSpacePrintf("XYZ tag is too small (%d bytes)", len); | 366         SkColorSpacePrintf("XYZ tag is too small (%d bytes)", len); | 
| 376         return false; | 367         return false; | 
| 377     } | 368     } | 
| 378 | 369 | 
| 379     dst[0] = SkFixedToFloat(read_big_endian_int(src + 8)); | 370     dst[0] = SkFixedToFloat(read_big_endian_int(src + 8)); | 
| 380     dst[1] = SkFixedToFloat(read_big_endian_int(src + 12)); | 371     dst[1] = SkFixedToFloat(read_big_endian_int(src + 12)); | 
| 381     dst[2] = SkFixedToFloat(read_big_endian_int(src + 16)); | 372     dst[2] = SkFixedToFloat(read_big_endian_int(src + 16)); | 
| 382     SkColorSpacePrintf("XYZ %g %g %g\n", dst[0], dst[1], dst[2]); | 373     SkColorSpacePrintf("XYZ %g %g %g\n", dst[0], dst[1], dst[2]); | 
| 383     return true; | 374     return true; | 
| 384 } | 375 } | 
| 385 | 376 | 
| 386 static constexpr uint32_t kTAG_CurveType     = SkSetFourByteTag('c', 'u', 'r', '
      v'); | 377 static constexpr uint32_t kTAG_CurveType     = SkSetFourByteTag('c', 'u', 'r', '
      v'); | 
| 387 static constexpr uint32_t kTAG_ParaCurveType = SkSetFourByteTag('p', 'a', 'r', '
      a'); | 378 static constexpr uint32_t kTAG_ParaCurveType = SkSetFourByteTag('p', 'a', 'r', '
      a'); | 
| 388 | 379 | 
| 389 bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s
      ize_t len) { | 380 static bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t*
       src, size_t len) { | 
| 390     for (uint32_t i = 0; i < numGammas; i++) { | 381     for (uint32_t i = 0; i < numGammas; i++) { | 
| 391         if (len < 12) { | 382         if (len < 12) { | 
| 392             // FIXME (msarett): | 383             // FIXME (msarett): | 
| 393             // We could potentially return false here after correctly parsing *s
      ome* of the | 384             // We could potentially return false here after correctly parsing *s
      ome* of the | 
| 394             // gammas correctly.  Should we somehow try to indicate a partial su
      ccess? | 385             // gammas correctly.  Should we somehow try to indicate a partial su
      ccess? | 
| 395             SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); | 386             SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); | 
| 396             return false; | 387             return false; | 
| 397         } | 388         } | 
| 398 | 389 | 
| 399         // We need to count the number of bytes in the tag, so we are able to mo
      ve to the | 390         // We need to count the number of bytes in the tag, so we are able to mo
      ve to the | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 411                     !safe_add((size_t) 12, tagBytes, &tagBytes)) | 402                     !safe_add((size_t) 12, tagBytes, &tagBytes)) | 
| 412                 { | 403                 { | 
| 413                     SkColorSpacePrintf("Invalid gamma count"); | 404                     SkColorSpacePrintf("Invalid gamma count"); | 
| 414                     return false; | 405                     return false; | 
| 415                 } | 406                 } | 
| 416 | 407 | 
| 417                 if (0 == count) { | 408                 if (0 == count) { | 
| 418                     // Some tags require a gamma curve, but the author doesn't a
      ctually want | 409                     // Some tags require a gamma curve, but the author doesn't a
      ctually want | 
| 419                     // to transform the data.  In this case, it is common to see
       a curve with | 410                     // to transform the data.  In this case, it is common to see
       a curve with | 
| 420                     // a count of 0. | 411                     // a count of 0. | 
| 421                     gammas[i].fValue = 1.0f; | 412                     gammas[i].fNamed = SkColorSpace::kLinear_GammaNamed; | 
| 422                     break; | 413                     break; | 
| 423                 } else if (len < tagBytes) { | 414                 } else if (len < tagBytes) { | 
| 424                     SkColorSpacePrintf("gamma tag is too small (%d bytes)", len)
      ; | 415                     SkColorSpacePrintf("gamma tag is too small (%d bytes)", len)
      ; | 
| 425                     return false; | 416                     return false; | 
| 426                 } | 417                 } | 
| 427 | 418 | 
| 428                 const uint16_t* table = (const uint16_t*) (src + 12); | 419                 const uint16_t* table = (const uint16_t*) (src + 12); | 
| 429                 if (1 == count) { | 420                 if (1 == count) { | 
| 430                     // The table entry is the gamma (with a bias of 256). | 421                     // The table entry is the gamma (with a bias of 256). | 
| 431                     uint16_t value = read_big_endian_short((const uint8_t*) tabl
      e); | 422                     float value = (read_big_endian_short((const uint8_t*) table)
      ) / 256.0f; | 
| 432                     gammas[i].fValue = value / 256.0f; | 423                     set_gamma_value(&gammas[i], value); | 
| 433                     if (0.0f == gammas[i].fValue) { | 424                     SkColorSpacePrintf("gamma %g\n", value); | 
| 434                         SkColorSpacePrintf("Cannot have zero gamma value"); |  | 
| 435                         return false; |  | 
| 436                     } |  | 
| 437                     SkColorSpacePrintf("gamma %d %g\n", value, gammas[i].fValue)
      ; |  | 
| 438                     break; | 425                     break; | 
| 439                 } | 426                 } | 
| 440 | 427 | 
| 441                 // Check for frequently occurring curves and use a fast approxim
      ation. | 428                 // Check for frequently occurring sRGB curves. | 
| 442                 // We do this by sampling a few values and see if they match our
       expectation. | 429                 // We do this by sampling a few values and see if they match our
       expectation. | 
| 443                 // A more robust solution would be to compare each value in this
       curve against | 430                 // A more robust solution would be to compare each value in this
       curve against | 
| 444                 // a 2.2f curve see if we remain below an error threshold.  At t
      his time, | 431                 // an sRGB curve to see if we remain below an error threshold.  
      At this time, | 
| 445                 // we haven't seen any images in the wild that make this kind of | 432                 // we haven't seen any images in the wild that make this kind of | 
| 446                 // calculation necessary.  We encounter identical gamma curves o
      ver and | 433                 // calculation necessary.  We encounter identical gamma curves o
      ver and | 
| 447                 // over again, but relatively few variations. | 434                 // over again, but relatively few variations. | 
| 448                 if (1024 == count) { | 435                 if (1024 == count) { | 
| 449                     // The magic values were chosen because they match a very co
      mmon sRGB | 436                     // The magic values were chosen because they match a very co
      mmon sRGB | 
| 450                     // gamma table and the less common Canon sRGB gamma table (w
      hich use | 437                     // gamma table and the less common Canon sRGB gamma table (w
      hich use | 
| 451                     // different rounding rules). | 438                     // different rounding rules). | 
| 452                     if (0 == read_big_endian_short((const uint8_t*) &table[0]) &
      & | 439                     if (0 == read_big_endian_short((const uint8_t*) &table[0]) &
      & | 
| 453                             3366 == read_big_endian_short((const uint8_t*) &tabl
      e[257]) && | 440                             3366 == read_big_endian_short((const uint8_t*) &tabl
      e[257]) && | 
| 454                             14116 == read_big_endian_short((const uint8_t*) &tab
      le[513]) && | 441                             14116 == read_big_endian_short((const uint8_t*) &tab
      le[513]) && | 
| 455                             34318 == read_big_endian_short((const uint8_t*) &tab
      le[768]) && | 442                             34318 == read_big_endian_short((const uint8_t*) &tab
      le[768]) && | 
| 456                             65535 == read_big_endian_short((const uint8_t*) &tab
      le[1023])) { | 443                             65535 == read_big_endian_short((const uint8_t*) &tab
      le[1023])) { | 
| 457                         gammas[i].fValue = 2.2f; | 444                         gammas[i].fNamed = SkColorSpace::kSRGB_GammaNamed; | 
| 458                         break; | 445                         break; | 
| 459                     } | 446                     } | 
| 460                 } else if (26 == count) { | 447                 } else if (26 == count) { | 
| 461                     // The magic values were chosen because they match a very co
      mmon sRGB | 448                     // The magic values were chosen because they match a very co
      mmon sRGB | 
| 462                     // gamma table. | 449                     // gamma table. | 
| 463                     if (0 == read_big_endian_short((const uint8_t*) &table[0]) &
      & | 450                     if (0 == read_big_endian_short((const uint8_t*) &table[0]) &
      & | 
| 464                             3062 == read_big_endian_short((const uint8_t*) &tabl
      e[6]) && | 451                             3062 == read_big_endian_short((const uint8_t*) &tabl
      e[6]) && | 
| 465                             12824 == read_big_endian_short((const uint8_t*) &tab
      le[12]) && | 452                             12824 == read_big_endian_short((const uint8_t*) &tab
      le[12]) && | 
| 466                             31237 == read_big_endian_short((const uint8_t*) &tab
      le[18]) && | 453                             31237 == read_big_endian_short((const uint8_t*) &tab
      le[18]) && | 
| 467                             65535 == read_big_endian_short((const uint8_t*) &tab
      le[25])) { | 454                             65535 == read_big_endian_short((const uint8_t*) &tab
      le[25])) { | 
| 468                         gammas[i].fValue = 2.2f; | 455                         gammas[i].fNamed = SkColorSpace::kSRGB_GammaNamed; | 
| 469                         break; | 456                         break; | 
| 470                     } | 457                     } | 
| 471                 } else if (4096 == count) { | 458                 } else if (4096 == count) { | 
| 472                     // The magic values were chosen because they match Nikon, Ep
      son, and | 459                     // The magic values were chosen because they match Nikon, Ep
      son, and | 
| 473                     // LCMS sRGB gamma tables (all of which use different roundi
      ng rules). | 460                     // LCMS sRGB gamma tables (all of which use different roundi
      ng rules). | 
| 474                     if (0 == read_big_endian_short((const uint8_t*) &table[0]) &
      & | 461                     if (0 == read_big_endian_short((const uint8_t*) &table[0]) &
      & | 
| 475                             950 == read_big_endian_short((const uint8_t*) &table
      [515]) && | 462                             950 == read_big_endian_short((const uint8_t*) &table
      [515]) && | 
| 476                             3342 == read_big_endian_short((const uint8_t*) &tabl
      e[1025]) && | 463                             3342 == read_big_endian_short((const uint8_t*) &tabl
      e[1025]) && | 
| 477                             14079 == read_big_endian_short((const uint8_t*) &tab
      le[2051]) && | 464                             14079 == read_big_endian_short((const uint8_t*) &tab
      le[2051]) && | 
| 478                             65535 == read_big_endian_short((const uint8_t*) &tab
      le[4095])) { | 465                             65535 == read_big_endian_short((const uint8_t*) &tab
      le[4095])) { | 
| 479                         gammas[i].fValue = 2.2f; | 466                         gammas[i].fNamed = SkColorSpace::kSRGB_GammaNamed; | 
| 480                         break; | 467                         break; | 
| 481                     } | 468                     } | 
| 482                 } | 469                 } | 
| 483 | 470 | 
| 484                 // Otherwise, fill in the interpolation table. | 471                 // Otherwise, fill in the interpolation table. | 
| 485                 gammas[i].fTableSize = count; | 472                 gammas[i].fTableSize = count; | 
| 486                 gammas[i].fTable = std::unique_ptr<float[]>(new float[count]); | 473                 gammas[i].fTable = std::unique_ptr<float[]>(new float[count]); | 
| 487                 for (uint32_t j = 0; j < count; j++) { | 474                 for (uint32_t j = 0; j < count; j++) { | 
| 488                     gammas[i].fTable[j] = | 475                     gammas[i].fTable[j] = | 
| 489                             (read_big_endian_short((const uint8_t*) &table[j])) 
      / 65535.0f; | 476                             (read_big_endian_short((const uint8_t*) &table[j])) 
      / 65535.0f; | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 503                 uint16_t format = read_big_endian_short(src + 8); | 490                 uint16_t format = read_big_endian_short(src + 8); | 
| 504                 if (kExponential_ParaCurveType == format) { | 491                 if (kExponential_ParaCurveType == format) { | 
| 505                     tagBytes = 12 + 4; | 492                     tagBytes = 12 + 4; | 
| 506                     if (len < tagBytes) { | 493                     if (len < tagBytes) { | 
| 507                         SkColorSpacePrintf("gamma tag is too small (%d bytes)", 
      len); | 494                         SkColorSpacePrintf("gamma tag is too small (%d bytes)", 
      len); | 
| 508                         return false; | 495                         return false; | 
| 509                     } | 496                     } | 
| 510 | 497 | 
| 511                     // Y = X^g | 498                     // Y = X^g | 
| 512                     int32_t g = read_big_endian_int(src + 12); | 499                     int32_t g = read_big_endian_int(src + 12); | 
| 513                     gammas[i].fValue = SkFixedToFloat(g); | 500                     set_gamma_value(&gammas[i], SkFixedToFloat(g)); | 
| 514                 } else { | 501                 } else { | 
| 515                     // Here's where the real parametric gammas start.  There are
       many | 502                     // Here's where the real parametric gammas start.  There are
       many | 
| 516                     // permutations of the same equations. | 503                     // permutations of the same equations. | 
| 517                     // | 504                     // | 
| 518                     // Y = (aX + b)^g + c  for X >= d | 505                     // Y = (aX + b)^g + c  for X >= d | 
| 519                     // Y = eX + f          otherwise | 506                     // Y = eX + f          otherwise | 
| 520                     // | 507                     // | 
| 521                     // We will fill in with zeros as necessary to always match t
      he above form. | 508                     // We will fill in with zeros as necessary to always match t
      he above form. | 
| 522                     float g = 0.0f, a = 0.0f, b = 0.0f, c = 0.0f, d = 0.0f, e = 
      0.0f, f = 0.0f; | 509                     float g = 0.0f, a = 0.0f, b = 0.0f, c = 0.0f, d = 0.0f, e = 
      0.0f, f = 0.0f; | 
| 523                     switch(format) { | 510                     switch(format) { | 
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 600                     } | 587                     } | 
| 601 | 588 | 
| 602                     // Recognize and simplify a very common parametric represent
      ation of sRGB gamma. | 589                     // Recognize and simplify a very common parametric represent
      ation of sRGB gamma. | 
| 603                     if (color_space_almost_equal(0.9479f, a) && | 590                     if (color_space_almost_equal(0.9479f, a) && | 
| 604                             color_space_almost_equal(0.0521f, b) && | 591                             color_space_almost_equal(0.0521f, b) && | 
| 605                             color_space_almost_equal(0.0000f, c) && | 592                             color_space_almost_equal(0.0000f, c) && | 
| 606                             color_space_almost_equal(0.0405f, d) && | 593                             color_space_almost_equal(0.0405f, d) && | 
| 607                             color_space_almost_equal(0.0774f, e) && | 594                             color_space_almost_equal(0.0774f, e) && | 
| 608                             color_space_almost_equal(0.0000f, f) && | 595                             color_space_almost_equal(0.0000f, f) && | 
| 609                             color_space_almost_equal(2.4000f, g)) { | 596                             color_space_almost_equal(2.4000f, g)) { | 
| 610                         gammas[i].fValue = 2.2f; | 597                         gammas[i].fNamed = SkColorSpace::kSRGB_GammaNamed; | 
| 611                     } else { | 598                     } else { | 
| 612                         // Fail on invalid gammas. | 599                         // Fail on invalid gammas. | 
| 613                         if (d <= 0.0f) { | 600                         if (d <= 0.0f) { | 
| 614                             // Y = (aX + b)^g + c  for always | 601                             // Y = (aX + b)^g + c  for always | 
| 615                             if (0.0f == a || 0.0f == g) { | 602                             if (0.0f == a || 0.0f == g) { | 
| 616                                 SkColorSpacePrintf("A or G is zero, constant gam
      ma function " | 603                                 SkColorSpacePrintf("A or G is zero, constant gam
      ma function " | 
| 617                                                    "is nonsense"); | 604                                                    "is nonsense"); | 
| 618                                 return false; | 605                                 return false; | 
| 619                             } | 606                             } | 
| 620                         } else if (d >= 1.0f) { | 607                         } else if (d >= 1.0f) { | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 641                 } | 628                 } | 
| 642 | 629 | 
| 643                 break; | 630                 break; | 
| 644             } | 631             } | 
| 645             default: | 632             default: | 
| 646                 SkColorSpacePrintf("Unsupported gamma tag type %d\n", type); | 633                 SkColorSpacePrintf("Unsupported gamma tag type %d\n", type); | 
| 647                 return false; | 634                 return false; | 
| 648         } | 635         } | 
| 649 | 636 | 
| 650         // Ensure that we have successfully read a gamma representation. | 637         // Ensure that we have successfully read a gamma representation. | 
| 651         SkASSERT(gammas[i].isValue() || gammas[i].isTable() || gammas[i].isParam
      etric()); | 638         SkASSERT(gammas[i].isNamed() || gammas[i].isValue() || gammas[i].isTable
      () || | 
|  | 639                  gammas[i].isParametric()); | 
| 652 | 640 | 
| 653         // Adjust src and len if there is another gamma curve to load. | 641         // Adjust src and len if there is another gamma curve to load. | 
| 654         if (i != numGammas - 1) { | 642         if (i != numGammas - 1) { | 
| 655             // Each curve is padded to 4-byte alignment. | 643             // Each curve is padded to 4-byte alignment. | 
| 656             tagBytes = SkAlign4(tagBytes); | 644             tagBytes = SkAlign4(tagBytes); | 
| 657             if (len < tagBytes) { | 645             if (len < tagBytes) { | 
| 658                 return false; | 646                 return false; | 
| 659             } | 647             } | 
| 660 | 648 | 
| 661             src += tagBytes; | 649             src += tagBytes; | 
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 789     if (0 != offsetToColorLUT && offsetToColorLUT < len) { | 777     if (0 != offsetToColorLUT && offsetToColorLUT < len) { | 
| 790         if (!load_color_lut(colorLUT, inputChannels, outputChannels, src + offse
      tToColorLUT, | 778         if (!load_color_lut(colorLUT, inputChannels, outputChannels, src + offse
      tToColorLUT, | 
| 791                             len - offsetToColorLUT)) { | 779                             len - offsetToColorLUT)) { | 
| 792             SkColorSpacePrintf("Failed to read color LUT from A to B tag.\n"); | 780             SkColorSpacePrintf("Failed to read color LUT from A to B tag.\n"); | 
| 793         } | 781         } | 
| 794     } | 782     } | 
| 795 | 783 | 
| 796     uint32_t offsetToMCurves = read_big_endian_int(src + 20); | 784     uint32_t offsetToMCurves = read_big_endian_int(src + 20); | 
| 797     if (0 != offsetToMCurves && offsetToMCurves < len) { | 785     if (0 != offsetToMCurves && offsetToMCurves < len) { | 
| 798         if (!load_gammas(gammas, outputChannels, src + offsetToMCurves, len - of
      fsetToMCurves)) { | 786         if (!load_gammas(gammas, outputChannels, src + offsetToMCurves, len - of
      fsetToMCurves)) { | 
| 799             SkColorSpacePrintf("Failed to read M curves from A to B tag.\n"); | 787             SkColorSpacePrintf("Failed to read M curves from A to B tag.  Using 
      linear gamma.\n"); | 
|  | 788             gammas[0].fNamed = SkColorSpace::kLinear_GammaNamed; | 
|  | 789             gammas[1].fNamed = SkColorSpace::kLinear_GammaNamed; | 
|  | 790             gammas[2].fNamed = SkColorSpace::kLinear_GammaNamed; | 
| 800         } | 791         } | 
| 801     } | 792     } | 
| 802 | 793 | 
| 803     uint32_t offsetToMatrix = read_big_endian_int(src + 16); | 794     uint32_t offsetToMatrix = read_big_endian_int(src + 16); | 
| 804     if (0 != offsetToMatrix && offsetToMatrix < len) { | 795     if (0 != offsetToMatrix && offsetToMatrix < len) { | 
| 805         if (!load_matrix(toXYZ, src + offsetToMatrix, len - offsetToMatrix)) { | 796         if (!load_matrix(toXYZ, src + offsetToMatrix, len - offsetToMatrix)) { | 
| 806             SkColorSpacePrintf("Failed to read matrix from A to B tag.\n"); | 797             SkColorSpacePrintf("Failed to read matrix from A to B tag.\n"); | 
|  | 798             toXYZ->setIdentity(); | 
| 807         } | 799         } | 
| 808     } | 800     } | 
| 809 | 801 | 
| 810     return true; | 802     return true; | 
| 811 } | 803 } | 
| 812 | 804 | 
| 813 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) { | 805 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) { | 
| 814     if (!input || len < kICCHeaderSize) { | 806     if (!input || len < kICCHeaderSize) { | 
| 815         return_null("Data is null or not large enough to contain an ICC profile"
      ); | 807         return_null("Data is null or not large enough to contain an ICC profile"
      ); | 
| 816     } | 808     } | 
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 865             const ICCTag* g = ICCTag::Find(tags.get(), tagCount, kTAG_gXYZ); | 857             const ICCTag* g = ICCTag::Find(tags.get(), tagCount, kTAG_gXYZ); | 
| 866             const ICCTag* b = ICCTag::Find(tags.get(), tagCount, kTAG_bXYZ); | 858             const ICCTag* b = ICCTag::Find(tags.get(), tagCount, kTAG_bXYZ); | 
| 867             if (r && g && b) { | 859             if (r && g && b) { | 
| 868                 float toXYZ[9]; | 860                 float toXYZ[9]; | 
| 869                 if (!load_xyz(&toXYZ[0], r->addr((const uint8_t*) base), r->fLen
      gth) || | 861                 if (!load_xyz(&toXYZ[0], r->addr((const uint8_t*) base), r->fLen
      gth) || | 
| 870                     !load_xyz(&toXYZ[3], g->addr((const uint8_t*) base), g->fLen
      gth) || | 862                     !load_xyz(&toXYZ[3], g->addr((const uint8_t*) base), g->fLen
      gth) || | 
| 871                     !load_xyz(&toXYZ[6], b->addr((const uint8_t*) base), b->fLen
      gth)) | 863                     !load_xyz(&toXYZ[6], b->addr((const uint8_t*) base), b->fLen
      gth)) | 
| 872                 { | 864                 { | 
| 873                     return_null("Need valid rgb tags for XYZ space"); | 865                     return_null("Need valid rgb tags for XYZ space"); | 
| 874                 } | 866                 } | 
|  | 867                 SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor); | 
|  | 868                 mat.set3x3ColMajorf(toXYZ); | 
| 875 | 869 | 
| 876                 // It is not uncommon to see missing or empty gamma tags.  This 
      indicates | 870                 // It is not uncommon to see missing or empty gamma tags.  This 
      indicates | 
| 877                 // that we should use unit gamma. | 871                 // that we should use unit gamma. | 
| 878                 SkGammaCurve curves[3]; | 872                 SkGammaCurve curves[3]; | 
| 879                 r = ICCTag::Find(tags.get(), tagCount, kTAG_rTRC); | 873                 r = ICCTag::Find(tags.get(), tagCount, kTAG_rTRC); | 
| 880                 g = ICCTag::Find(tags.get(), tagCount, kTAG_gTRC); | 874                 g = ICCTag::Find(tags.get(), tagCount, kTAG_gTRC); | 
| 881                 b = ICCTag::Find(tags.get(), tagCount, kTAG_bTRC); | 875                 b = ICCTag::Find(tags.get(), tagCount, kTAG_bTRC); | 
| 882                 if (!r || !load_gammas(&curves[0], 1, r->addr((const uint8_t*) b
      ase), r->fLength)) | 876                 if (!r || !load_gammas(&curves[0], 1, r->addr((const uint8_t*) b
      ase), r->fLength)) | 
| 883                 { | 877                 { | 
| 884                     SkColorSpacePrintf("Failed to read R gamma tag.\n"); | 878                     SkColorSpacePrintf("Failed to read R gamma tag.\n"); | 
|  | 879                     curves[0].fNamed = SkColorSpace::kLinear_GammaNamed; | 
| 885                 } | 880                 } | 
| 886                 if (!g || !load_gammas(&curves[1], 1, g->addr((const uint8_t*) b
      ase), g->fLength)) | 881                 if (!g || !load_gammas(&curves[1], 1, g->addr((const uint8_t*) b
      ase), g->fLength)) | 
| 887                 { | 882                 { | 
| 888                     SkColorSpacePrintf("Failed to read G gamma tag.\n"); | 883                     SkColorSpacePrintf("Failed to read G gamma tag.\n"); | 
|  | 884                     curves[1].fNamed = SkColorSpace::kLinear_GammaNamed; | 
| 889                 } | 885                 } | 
| 890                 if (!b || !load_gammas(&curves[2], 1, b->addr((const uint8_t*) b
      ase), b->fLength)) | 886                 if (!b || !load_gammas(&curves[2], 1, b->addr((const uint8_t*) b
      ase), b->fLength)) | 
| 891                 { | 887                 { | 
| 892                     SkColorSpacePrintf("Failed to read B gamma tag.\n"); | 888                     SkColorSpacePrintf("Failed to read B gamma tag.\n"); | 
|  | 889                     curves[2].fNamed = SkColorSpace::kLinear_GammaNamed; | 
| 893                 } | 890                 } | 
| 894 | 891 | 
| 895                 sk_sp<SkGammas> gammas(new SkGammas(std::move(curves[0]), std::m
      ove(curves[1]), | 892                 GammaNamed gammaNamed = SkGammas::Named(curves); | 
| 896                                                     std::move(curves[2]))); | 893                 if (kNonStandard_GammaNamed == gammaNamed) { | 
| 897                 SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor); | 894                     sk_sp<SkGammas> gammas = sk_make_sp<SkGammas>(std::move(curv
      es[0]), | 
| 898                 mat.set3x3ColMajorf(toXYZ); | 895                                                                   std::move(curv
      es[1]), | 
| 899                 if (gammas->isValues()) { | 896                                                                   std::move(curv
      es[2])); | 
| 900                     // When we have values, take advantage of the NewFromRGB ini
      tializer. | 897                     return sk_sp<SkColorSpace>(new SkColorSpace_Base(nullptr, st
      d::move(gammas), | 
| 901                     // This allows us to check for canonical sRGB and Adobe RGB. | 898                                                                      mat, std::m
      ove(data))); | 
| 902                     float gammaVals[3]; |  | 
| 903                     gammaVals[0] = gammas->fRed.fValue; |  | 
| 904                     gammaVals[1] = gammas->fGreen.fValue; |  | 
| 905                     gammaVals[2] = gammas->fBlue.fValue; |  | 
| 906                     return SkColorSpace_Base::NewRGB(gammaVals, mat, std::move(d
      ata)); |  | 
| 907                 } else { | 899                 } else { | 
| 908                     return sk_sp<SkColorSpace>(new SkColorSpace_Base(std::move(g
      ammas), mat, | 900                     return SkColorSpace_Base::NewRGB(gammaNamed, mat, std::move(
      data)); | 
| 909                                                                      kUnknown_Na
      med, |  | 
| 910                                                                      std::move(d
      ata))); |  | 
| 911                 } | 901                 } | 
| 912             } | 902             } | 
| 913 | 903 | 
| 914             // Recognize color profile specified by A2B0 tag. | 904             // Recognize color profile specified by A2B0 tag. | 
| 915             const ICCTag* a2b0 = ICCTag::Find(tags.get(), tagCount, kTAG_A2B0); | 905             const ICCTag* a2b0 = ICCTag::Find(tags.get(), tagCount, kTAG_A2B0); | 
| 916             if (a2b0) { | 906             if (a2b0) { | 
| 917                 SkAutoTDelete<SkColorLookUpTable> colorLUT(new SkColorLookUpTabl
      e()); | 907                 SkAutoTDelete<SkColorLookUpTable> colorLUT(new SkColorLookUpTabl
      e()); | 
| 918                 SkGammaCurve curves[3]; | 908                 SkGammaCurve curves[3]; | 
| 919                 SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor); | 909                 SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor); | 
| 920                 if (!load_a2b0(colorLUT, curves, &toXYZ, a2b0->addr((const uint8
      _t*) base), | 910                 if (!load_a2b0(colorLUT, curves, &toXYZ, a2b0->addr((const uint8
      _t*) base), | 
| 921                                a2b0->fLength)) { | 911                                a2b0->fLength)) { | 
| 922                     return_null("Failed to parse A2B0 tag"); | 912                     return_null("Failed to parse A2B0 tag"); | 
| 923                 } | 913                 } | 
| 924 | 914 | 
| 925                 sk_sp<SkGammas> gammas(new SkGammas(std::move(curves[0]), std::m
      ove(curves[1]), | 915                 GammaNamed gammaNamed = SkGammas::Named(curves); | 
| 926                                                     std::move(curves[2]))); | 916                 if (colorLUT->fTable || kNonStandard_GammaNamed == gammaNamed) { | 
| 927                 if (colorLUT->fTable) { | 917                     sk_sp<SkGammas> gammas = sk_make_sp<SkGammas>(std::move(curv
      es[0]), | 
|  | 918                                                                   std::move(curv
      es[1]), | 
|  | 919                                                                   std::move(curv
      es[2])); | 
|  | 920 | 
| 928                     return sk_sp<SkColorSpace>(new SkColorSpace_Base(colorLUT.re
      lease(), | 921                     return sk_sp<SkColorSpace>(new SkColorSpace_Base(colorLUT.re
      lease(), | 
| 929                                                                      std::move(g
      ammas), toXYZ, | 922                                                                      std::move(g
      ammas), toXYZ, | 
| 930                                                                      std::move(d
      ata))); | 923                                                                      std::move(d
      ata))); | 
| 931                 } else if (gammas->isValues()) { |  | 
| 932                     // When we have values, take advantage of the NewFromRGB ini
      tializer. |  | 
| 933                     // This allows us to check for canonical sRGB and Adobe RGB. |  | 
| 934                     float gammaVals[3]; |  | 
| 935                     gammaVals[0] = gammas->fRed.fValue; |  | 
| 936                     gammaVals[1] = gammas->fGreen.fValue; |  | 
| 937                     gammaVals[2] = gammas->fBlue.fValue; |  | 
| 938                     return SkColorSpace_Base::NewRGB(gammaVals, toXYZ, std::move
      (data)); |  | 
| 939                 } else { | 924                 } else { | 
| 940                     return sk_sp<SkColorSpace>(new SkColorSpace_Base(std::move(g
      ammas), toXYZ, | 925                     return SkColorSpace_Base::NewRGB(gammaNamed, toXYZ, std::mov
      e(data)); | 
| 941                                                                      kUnknown_Na
      med, |  | 
| 942                                                                      std::move(d
      ata))); |  | 
| 943                 } | 926                 } | 
| 944             } | 927             } | 
| 945         } | 928         } | 
| 946         default: | 929         default: | 
| 947             break; | 930             break; | 
| 948     } | 931     } | 
| 949 | 932 | 
| 950     return_null("ICC profile contains unsupported colorspace"); | 933     return_null("ICC profile contains unsupported colorspace"); | 
| 951 } | 934 } | 
| 952 | 935 | 
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1072     ptr[2] = SkEndian_SwapBE32(1); | 1055     ptr[2] = SkEndian_SwapBE32(1); | 
| 1073 | 1056 | 
| 1074     // Convert gamma to 16-bit fixed point. | 1057     // Convert gamma to 16-bit fixed point. | 
| 1075     uint16_t* ptr16 = (uint16_t*) (ptr + 3); | 1058     uint16_t* ptr16 = (uint16_t*) (ptr + 3); | 
| 1076     ptr16[0] = SkEndian_SwapBE16((uint16_t) (value * 256.0f)); | 1059     ptr16[0] = SkEndian_SwapBE16((uint16_t) (value * 256.0f)); | 
| 1077 | 1060 | 
| 1078     // Pad tag with zero. | 1061     // Pad tag with zero. | 
| 1079     ptr16[1] = 0; | 1062     ptr16[1] = 0; | 
| 1080 } | 1063 } | 
| 1081 | 1064 | 
|  | 1065 static float get_gamma_value(const SkGammaCurve* curve) { | 
|  | 1066     switch (curve->fNamed) { | 
|  | 1067         case SkColorSpace::kSRGB_GammaNamed: | 
|  | 1068             // FIXME (msarett): | 
|  | 1069             // kSRGB cannot be represented by a value.  Here we fall through to 
      2.2f, | 
|  | 1070             // which is a close guess.  To be more accurate, we need to represen
      t sRGB | 
|  | 1071             // gamma with a parametric curve. | 
|  | 1072         case SkColorSpace::k2Dot2Curve_GammaNamed: | 
|  | 1073             return 2.2f; | 
|  | 1074         case SkColorSpace::kLinear_GammaNamed: | 
|  | 1075             return 1.0f; | 
|  | 1076         default: | 
|  | 1077             SkASSERT(curve->isValue()); | 
|  | 1078             return curve->fValue; | 
|  | 1079     } | 
|  | 1080 } | 
|  | 1081 | 
| 1082 sk_sp<SkData> SkColorSpace_Base::writeToICC() const { | 1082 sk_sp<SkData> SkColorSpace_Base::writeToICC() const { | 
| 1083     // Return if this object was created from a profile, or if we have already s
      erialized | 1083     // Return if this object was created from a profile, or if we have already s
      erialized | 
| 1084     // the profile. | 1084     // the profile. | 
| 1085     if (fProfileData) { | 1085     if (fProfileData) { | 
| 1086         return fProfileData; | 1086         return fProfileData; | 
| 1087     } | 1087     } | 
| 1088 | 1088 | 
| 1089     // The client may create an SkColorSpace using an SkMatrix44, but currently 
      we only | 1089     // The client may create an SkColorSpace using an SkMatrix44, but currently 
      we only | 
| 1090     // support writing profiles with 3x3 matrices. | 1090     // support writing profiles with 3x3 matrices. | 
| 1091     // TODO (msarett): Fix this! | 1091     // TODO (msarett): Fix this! | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 1113 | 1113 | 
| 1114     // Write XYZ tags | 1114     // Write XYZ tags | 
| 1115     write_xyz_tag((uint32_t*) ptr, fToXYZD50, 0); | 1115     write_xyz_tag((uint32_t*) ptr, fToXYZD50, 0); | 
| 1116     ptr += kTAG_XYZ_Bytes; | 1116     ptr += kTAG_XYZ_Bytes; | 
| 1117     write_xyz_tag((uint32_t*) ptr, fToXYZD50, 1); | 1117     write_xyz_tag((uint32_t*) ptr, fToXYZD50, 1); | 
| 1118     ptr += kTAG_XYZ_Bytes; | 1118     ptr += kTAG_XYZ_Bytes; | 
| 1119     write_xyz_tag((uint32_t*) ptr, fToXYZD50, 2); | 1119     write_xyz_tag((uint32_t*) ptr, fToXYZD50, 2); | 
| 1120     ptr += kTAG_XYZ_Bytes; | 1120     ptr += kTAG_XYZ_Bytes; | 
| 1121 | 1121 | 
| 1122     // Write TRC tags | 1122     // Write TRC tags | 
| 1123     SkASSERT(as_CSB(this)->fGammas->fRed.isValue()); | 1123     GammaNamed gammaNamed = this->gammaNamed(); | 
| 1124     write_trc_tag((uint32_t*) ptr, as_CSB(this)->fGammas->fRed.fValue); | 1124     if (kNonStandard_GammaNamed == gammaNamed) { | 
| 1125     ptr += SkAlign4(kTAG_TRC_Bytes); | 1125         write_trc_tag((uint32_t*) ptr, get_gamma_value(&as_CSB(this)->fGammas->f
      Red)); | 
| 1126     SkASSERT(as_CSB(this)->fGammas->fGreen.isValue()); | 1126         ptr += SkAlign4(kTAG_TRC_Bytes); | 
| 1127     write_trc_tag((uint32_t*) ptr, as_CSB(this)->fGammas->fGreen.fValue); | 1127         write_trc_tag((uint32_t*) ptr, get_gamma_value(&as_CSB(this)->fGammas->f
      Green)); | 
| 1128     ptr += SkAlign4(kTAG_TRC_Bytes); | 1128         ptr += SkAlign4(kTAG_TRC_Bytes); | 
| 1129     SkASSERT(as_CSB(this)->fGammas->fBlue.isValue()); | 1129         write_trc_tag((uint32_t*) ptr, get_gamma_value(&as_CSB(this)->fGammas->f
      Blue)); | 
| 1130     write_trc_tag((uint32_t*) ptr, as_CSB(this)->fGammas->fBlue.fValue); | 1130         ptr += SkAlign4(kTAG_TRC_Bytes); | 
| 1131     ptr += SkAlign4(kTAG_TRC_Bytes); | 1131     } else { | 
|  | 1132         switch (gammaNamed) { | 
|  | 1133             case SkColorSpace::kSRGB_GammaNamed: | 
|  | 1134                 // FIXME (msarett): | 
|  | 1135                 // kSRGB cannot be represented by a value.  Here we fall through
       to 2.2f, | 
|  | 1136                 // which is a close guess.  To be more accurate, we need to repr
      esent sRGB | 
|  | 1137                 // gamma with a parametric curve. | 
|  | 1138             case SkColorSpace::k2Dot2Curve_GammaNamed: | 
|  | 1139                 write_trc_tag((uint32_t*) ptr, 2.2f); | 
|  | 1140                 ptr += SkAlign4(kTAG_TRC_Bytes); | 
|  | 1141                 write_trc_tag((uint32_t*) ptr, 2.2f); | 
|  | 1142                 ptr += SkAlign4(kTAG_TRC_Bytes); | 
|  | 1143                 write_trc_tag((uint32_t*) ptr, 2.2f); | 
|  | 1144                 ptr += SkAlign4(kTAG_TRC_Bytes); | 
|  | 1145                 break; | 
|  | 1146             case SkColorSpace::kLinear_GammaNamed: | 
|  | 1147                 write_trc_tag((uint32_t*) ptr, 1.0f); | 
|  | 1148                 ptr += SkAlign4(kTAG_TRC_Bytes); | 
|  | 1149                 write_trc_tag((uint32_t*) ptr, 1.0f); | 
|  | 1150                 ptr += SkAlign4(kTAG_TRC_Bytes); | 
|  | 1151                 write_trc_tag((uint32_t*) ptr, 1.0f); | 
|  | 1152                 ptr += SkAlign4(kTAG_TRC_Bytes); | 
|  | 1153                 break; | 
|  | 1154             default: | 
|  | 1155                 SkASSERT(false); | 
|  | 1156                 break; | 
|  | 1157         } | 
|  | 1158     } | 
| 1132 | 1159 | 
| 1133     // Write white point tag | 1160     // Write white point tag | 
| 1134     uint32_t* ptr32 = (uint32_t*) ptr; | 1161     uint32_t* ptr32 = (uint32_t*) ptr; | 
| 1135     ptr32[0] = SkEndian_SwapBE32(kXYZ_PCSSpace); | 1162     ptr32[0] = SkEndian_SwapBE32(kXYZ_PCSSpace); | 
| 1136     ptr32[1] = 0; | 1163     ptr32[1] = 0; | 
| 1137     // TODO (msarett): These values correspond to the D65 white point.  This may
       not always be | 1164     // TODO (msarett): These values correspond to the D65 white point.  This may
       not always be | 
| 1138     //                 correct. | 1165     //                 correct. | 
| 1139     ptr32[2] = SkEndian_SwapBE32(0x0000f351); | 1166     ptr32[2] = SkEndian_SwapBE32(0x0000f351); | 
| 1140     ptr32[3] = SkEndian_SwapBE32(0x00010000); | 1167     ptr32[3] = SkEndian_SwapBE32(0x00010000); | 
| 1141     ptr32[4] = SkEndian_SwapBE32(0x000116cc); | 1168     ptr32[4] = SkEndian_SwapBE32(0x000116cc); | 
| 1142     ptr += kTAG_XYZ_Bytes; | 1169     ptr += kTAG_XYZ_Bytes; | 
| 1143 | 1170 | 
| 1144     // Write copyright tag | 1171     // Write copyright tag | 
| 1145     memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); | 1172     memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); | 
| 1146 | 1173 | 
| 1147     // TODO (msarett): Should we try to hold onto the data so we can return imme
      diately if | 1174     // TODO (msarett): Should we try to hold onto the data so we can return imme
      diately if | 
| 1148     //                 the client calls again? | 1175     //                 the client calls again? | 
| 1149     return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); | 1176     return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); | 
| 1150 } | 1177 } | 
| OLD | NEW | 
|---|