LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkPM4fPriv.h (source / functions) Hit Total Coverage
Test: output.info Lines: 16 70 22.9 %
Date: 2017-07-14 16:53:18 Functions: 4 11 36.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2016 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #ifndef SkPM4fPriv_DEFINED
       9             : #define SkPM4fPriv_DEFINED
      10             : 
      11             : #include "SkColorPriv.h"
      12             : #include "SkColorSpace.h"
      13             : #include "SkColorSpace_Base.h"
      14             : #include "SkArenaAlloc.h"
      15             : #include "SkPM4f.h"
      16             : #include "SkRasterPipeline.h"
      17             : #include "SkSRGB.h"
      18             : 
      19             : static inline Sk4f set_alpha(const Sk4f& px, float alpha) {
      20             :     return { px[0], px[1], px[2], alpha };
      21             : }
      22             : 
      23           0 : static inline float get_alpha(const Sk4f& px) {
      24           0 :     return px[3];
      25             : }
      26             : 
      27             : 
      28           0 : static inline Sk4f Sk4f_fromL32(uint32_t px) {
      29           0 :     return SkNx_cast<float>(Sk4b::Load(&px)) * (1/255.0f);
      30             : }
      31             : 
      32          81 : static inline Sk4f Sk4f_fromS32(uint32_t px) {
      33          81 :     return { sk_linear_from_srgb[(px >>  0) & 0xff],
      34          81 :              sk_linear_from_srgb[(px >>  8) & 0xff],
      35          81 :              sk_linear_from_srgb[(px >> 16) & 0xff],
      36         162 :                     (1/255.0f) * (px >> 24)          };
      37             : }
      38             : 
      39           0 : static inline uint32_t Sk4f_toL32(const Sk4f& px) {
      40             :     uint32_t l32;
      41           0 :     SkNx_cast<uint8_t>(Sk4f_round(px * 255.0f)).store(&l32);
      42           0 :     return l32;
      43             : }
      44             : 
      45          81 : static inline uint32_t Sk4f_toS32(const Sk4f& px) {
      46          81 :     Sk4i  rgb = sk_linear_to_srgb(px),
      47         324 :          srgb = { rgb[0], rgb[1], rgb[2], (int)(255.0f * px[3] + 0.5f) };
      48             : 
      49             :     uint32_t s32;
      50         162 :     SkNx_cast<uint8_t>(srgb).store(&s32);
      51          81 :     return s32;
      52             : }
      53             : 
      54             : 
      55             : // SkColor handling:
      56             : //   SkColor has an ordering of (b, g, r, a) if cast to an Sk4f, so the code swizzles r and b to
      57             : // produce the needed (r, g, b, a) ordering.
      58             : static inline Sk4f Sk4f_from_SkColor(SkColor color) {
      59             :     return swizzle_rb(Sk4f_fromS32(color));
      60             : }
      61             : 
      62             : static inline void assert_unit(float x) {
      63             :     SkASSERT(0 <= x && x <= 1);
      64             : }
      65             : 
      66             : static inline float exact_srgb_to_linear(float srgb) {
      67             :     assert_unit(srgb);
      68             :     float linear;
      69             :     if (srgb <= 0.04045) {
      70             :         linear = srgb / 12.92f;
      71             :     } else {
      72             :         linear = powf((srgb + 0.055f) / 1.055f, 2.4f);
      73             :     }
      74             :     assert_unit(linear);
      75             :     return linear;
      76             : }
      77             : 
      78           0 : static inline void analyze_3x4_matrix(const float matrix[12],
      79             :                                       bool* can_underflow, bool* can_overflow) {
      80             :     // | 0 3 6  9 |   |r|   |x|
      81             :     // | 1 4 7 10 | x |g| = |y|
      82             :     // | 2 5 8 11 |   |b|   |z|
      83             :     //                |1|
      84             :     // We'll find min/max bounds on each of x,y,z assuming r,g,b are all in [0,1].
      85             :     // If any can be <0, we'll set can_underflow; if any can be >1, can_overflow.
      86           0 :     bool underflow = false,
      87           0 :           overflow = false;
      88           0 :     for (int i = 0; i < 3; i++) {
      89           0 :         SkScalar min = matrix[i+9],
      90           0 :                  max = matrix[i+9];
      91           0 :         (matrix[i+0] < 0 ? min : max) += matrix[i+0];
      92           0 :         (matrix[i+3] < 0 ? min : max) += matrix[i+3];
      93           0 :         (matrix[i+6] < 0 ? min : max) += matrix[i+6];
      94           0 :         underflow = underflow || min < 0;
      95           0 :         overflow  =  overflow || max > 1;
      96             :     }
      97           0 :     *can_underflow = underflow;
      98           0 :     *can_overflow  =  overflow;
      99           0 : }
     100             : 
     101             : 
     102             : // N.B. scratch_matrix_3x4 must live at least as long as p.
     103           0 : static inline bool append_gamut_transform(SkRasterPipeline* p, float scratch_matrix_3x4[12],
     104             :                                           SkColorSpace* src, SkColorSpace* dst) {
     105           0 :     if (src == dst) { return true; }
     106           0 :     if (!dst)       { return true; }   // Legacy modes intentionally ignore color gamut.
     107           0 :     if (!src)       { return true; }   // A null src color space means linear gamma, dst gamut.
     108             : 
     109           0 :     auto toXYZ = as_CSB(src)->  toXYZD50(),
     110           0 :        fromXYZ = as_CSB(dst)->fromXYZD50();
     111           0 :     if (!toXYZ || !fromXYZ) { return false; }  // Unsupported color space type.
     112             : 
     113           0 :     if (as_CSB(src)->toXYZD50Hash() == as_CSB(dst)->toXYZD50Hash()) { return true; }
     114             : 
     115           0 :     SkMatrix44 m44(*fromXYZ, *toXYZ);
     116             : 
     117             :     // Convert from 4x4 to (column-major) 3x4.
     118           0 :     auto ptr = scratch_matrix_3x4;
     119           0 :     *ptr++ = m44.get(0,0); *ptr++ = m44.get(1,0); *ptr++ = m44.get(2,0);
     120           0 :     *ptr++ = m44.get(0,1); *ptr++ = m44.get(1,1); *ptr++ = m44.get(2,1);
     121           0 :     *ptr++ = m44.get(0,2); *ptr++ = m44.get(1,2); *ptr++ = m44.get(2,2);
     122           0 :     *ptr++ = m44.get(0,3); *ptr++ = m44.get(1,3); *ptr++ = m44.get(2,3);
     123             : 
     124             :     bool needs_clamp_0, needs_clamp_a;
     125           0 :     analyze_3x4_matrix(scratch_matrix_3x4, &needs_clamp_0, &needs_clamp_a);
     126             : 
     127           0 :     p->append(SkRasterPipeline::matrix_3x4, scratch_matrix_3x4);
     128           0 :     if (needs_clamp_0) { p->append(SkRasterPipeline::clamp_0); }
     129           0 :     if (needs_clamp_a) { p->append(SkRasterPipeline::clamp_a); }
     130           0 :     return true;
     131             : }
     132             : 
     133           0 : static inline bool append_gamut_transform(SkRasterPipeline* p, SkArenaAlloc* scratch,
     134             :                                           SkColorSpace* src, SkColorSpace* dst) {
     135           0 :     return append_gamut_transform(p, scratch->makeArrayDefault<float>(12), src, dst);
     136             : }
     137             : 
     138           0 : static inline SkColor4f to_colorspace(const SkColor4f& c, SkColorSpace* src, SkColorSpace* dst) {
     139           0 :     SkColor4f color4f = c;
     140           0 :     if (src && dst) {
     141           0 :         void* color4f_ptr = &color4f;
     142             : 
     143             :         float scratch_matrix_3x4[12];
     144             : 
     145           0 :         SkRasterPipeline p;
     146           0 :         p.append(SkRasterPipeline::constant_color, color4f_ptr);
     147           0 :         append_gamut_transform(&p, scratch_matrix_3x4, src, dst);
     148           0 :         p.append(SkRasterPipeline::store_f32, &color4f_ptr);
     149             : 
     150           0 :         p.run(0,1);
     151             :     }
     152           0 :     return color4f;
     153             : }
     154             : 
     155         312 : static inline SkColor4f SkColor4f_from_SkColor(SkColor color, SkColorSpace* dst) {
     156             :     SkColor4f color4f;
     157         312 :     if (dst) {
     158             :         // sRGB gamma, sRGB gamut.
     159           0 :         color4f = to_colorspace(SkColor4f::FromColor(color),
     160           0 :                                 SkColorSpace::MakeSRGB().get(), dst);
     161             :     } else {
     162             :         // Linear gamma, dst gamut.
     163        1248 :         swizzle_rb(SkNx_cast<float>(Sk4b::Load(&color)) * (1/255.0f)).store(&color4f);
     164             :     }
     165         312 :     return color4f;
     166             : }
     167             : 
     168         312 : static inline SkPM4f SkPM4f_from_SkColor(SkColor color, SkColorSpace* dst) {
     169         312 :     return SkColor4f_from_SkColor(color, dst).premul();
     170             : }
     171             : 
     172             : #endif

Generated by: LCOV version 1.13