Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef SkDither_DEFINED
     18 #define SkDither_DEFINED
     19 
     20 #include "SkColorPriv.h"
     21 
     22 #define SK_DitherValueMax4444   15
     23 #define SK_DitherValueMax565    7
     24 
     25 /*  need to use macros for bit-counts for each component, and then
     26     move these into SkColorPriv.h
     27 */
     28 
     29 #define SkDITHER_R32_FOR_565_MACRO(r, d)    (r + d - (r >> 5))
     30 #define SkDITHER_G32_FOR_565_MACRO(g, d)    (g + (d >> 1) - (g >> 6))
     31 #define SkDITHER_B32_FOR_565_MACRO(b, d)    (b + d - (b >> 5))
     32 
     33 #define SkDITHER_A32_FOR_4444_MACRO(a, d)    (a + 15 - (a >> 4))
     34 #define SkDITHER_R32_FOR_4444_MACRO(r, d)    (r + d - (r >> 4))
     35 #define SkDITHER_G32_FOR_4444_MACRO(g, d)    (g + d - (g >> 4))
     36 #define SkDITHER_B32_FOR_4444_MACRO(b, d)    (b + d - (b >> 4))
     37 
     38 #ifdef SK_DEBUG
     39     inline unsigned SkDITHER_R32_FOR_565(unsigned r, unsigned d)
     40     {
     41         SkASSERT(d <= SK_DitherValueMax565);
     42         SkA32Assert(r);
     43         r = SkDITHER_R32_FOR_565_MACRO(r, d);
     44         SkA32Assert(r);
     45         return r;
     46     }
     47     inline unsigned SkDITHER_G32_FOR_565(unsigned g, unsigned d)
     48     {
     49         SkASSERT(d <= SK_DitherValueMax565);
     50         SkG32Assert(g);
     51         g = SkDITHER_G32_FOR_565_MACRO(g, d);
     52         SkG32Assert(g);
     53         return g;
     54     }
     55     inline unsigned SkDITHER_B32_FOR_565(unsigned b, unsigned d)
     56     {
     57         SkASSERT(d <= SK_DitherValueMax565);
     58         SkB32Assert(b);
     59         b = SkDITHER_B32_FOR_565_MACRO(b, d);
     60         SkB32Assert(b);
     61         return b;
     62     }
     63 #else
     64     #define SkDITHER_R32_FOR_565(r, d)  SkDITHER_R32_FOR_565_MACRO(r, d)
     65     #define SkDITHER_G32_FOR_565(g, d)  SkDITHER_G32_FOR_565_MACRO(g, d)
     66     #define SkDITHER_B32_FOR_565(b, d)  SkDITHER_B32_FOR_565_MACRO(b, d)
     67 #endif
     68 
     69 #define SkDITHER_R32To565(r, d)  SkR32ToR16(SkDITHER_R32_FOR_565(r, d))
     70 #define SkDITHER_G32To565(g, d)  SkG32ToG16(SkDITHER_G32_FOR_565(g, d))
     71 #define SkDITHER_B32To565(b, d)  SkB32ToB16(SkDITHER_B32_FOR_565(b, d))
     72 
     73 #define SkDITHER_A32To4444(a, d)  SkA32To4444(SkDITHER_A32_FOR_4444_MACRO(a, d))
     74 #define SkDITHER_R32To4444(r, d)  SkR32To4444(SkDITHER_R32_FOR_4444_MACRO(r, d))
     75 #define SkDITHER_G32To4444(g, d)  SkG32To4444(SkDITHER_G32_FOR_4444_MACRO(g, d))
     76 #define SkDITHER_B32To4444(b, d)  SkB32To4444(SkDITHER_B32_FOR_4444_MACRO(b, d))
     77 
     78 static inline SkPMColor SkDitherARGB32For565(SkPMColor c, unsigned dither)
     79 {
     80     SkASSERT(dither <= SK_DitherValueMax565);
     81 
     82     unsigned sa = SkGetPackedA32(c);
     83     dither = SkAlphaMul(dither, SkAlpha255To256(sa));
     84 
     85     unsigned sr = SkGetPackedR32(c);
     86     unsigned sg = SkGetPackedG32(c);
     87     unsigned sb = SkGetPackedB32(c);
     88     sr = SkDITHER_R32_FOR_565(sr, dither);
     89     sg = SkDITHER_G32_FOR_565(sg, dither);
     90     sb = SkDITHER_B32_FOR_565(sb, dither);
     91 
     92     return SkPackARGB32(sa, sr, sg, sb);
     93 }
     94 
     95 static inline SkPMColor SkDitherRGB32For565(SkPMColor c, unsigned dither)
     96 {
     97     SkASSERT(dither <= SK_DitherValueMax565);
     98 
     99     unsigned sr = SkGetPackedR32(c);
    100     unsigned sg = SkGetPackedG32(c);
    101     unsigned sb = SkGetPackedB32(c);
    102     sr = SkDITHER_R32_FOR_565(sr, dither);
    103     sg = SkDITHER_G32_FOR_565(sg, dither);
    104     sb = SkDITHER_B32_FOR_565(sb, dither);
    105 
    106     return SkPackARGB32(0xFF, sr, sg, sb);
    107 }
    108 
    109 static inline uint16_t SkDitherRGBTo565(U8CPU r, U8CPU g, U8CPU b,
    110                                               unsigned dither)
    111 {
    112     SkASSERT(dither <= SK_DitherValueMax565);
    113     r = SkDITHER_R32To565(r, dither);
    114     g = SkDITHER_G32To565(g, dither);
    115     b = SkDITHER_B32To565(b, dither);
    116     return SkPackRGB16(r, g, b);
    117 }
    118 
    119 static inline uint16_t SkDitherRGB32To565(SkPMColor c, unsigned dither)
    120 {
    121     SkASSERT(dither <= SK_DitherValueMax565);
    122 
    123     unsigned sr = SkGetPackedR32(c);
    124     unsigned sg = SkGetPackedG32(c);
    125     unsigned sb = SkGetPackedB32(c);
    126     sr = SkDITHER_R32To565(sr, dither);
    127     sg = SkDITHER_G32To565(sg, dither);
    128     sb = SkDITHER_B32To565(sb, dither);
    129 
    130     return SkPackRGB16(sr, sg, sb);
    131 }
    132 
    133 static inline uint16_t SkDitherARGB32To565(U8CPU sa, SkPMColor c, unsigned dither)
    134 {
    135     SkASSERT(dither <= SK_DitherValueMax565);
    136     dither = SkAlphaMul(dither, SkAlpha255To256(sa));
    137 
    138     unsigned sr = SkGetPackedR32(c);
    139     unsigned sg = SkGetPackedG32(c);
    140     unsigned sb = SkGetPackedB32(c);
    141     sr = SkDITHER_R32To565(sr, dither);
    142     sg = SkDITHER_G32To565(sg, dither);
    143     sb = SkDITHER_B32To565(sb, dither);
    144 
    145     return SkPackRGB16(sr, sg, sb);
    146 }
    147 
    148 ///////////////////////// 4444
    149 
    150 static inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r, U8CPU g,
    151                                                U8CPU b, unsigned dither)
    152 {
    153     dither = SkAlphaMul(dither, SkAlpha255To256(a));
    154 
    155     a = SkDITHER_A32To4444(a, dither);
    156     r = SkDITHER_R32To4444(r, dither);
    157     g = SkDITHER_G32To4444(g, dither);
    158     b = SkDITHER_B32To4444(b, dither);
    159 
    160     return SkPackARGB4444(a, r, g, b);
    161 }
    162 
    163 static inline SkPMColor16 SkDitherARGB32To4444(SkPMColor c, unsigned dither)
    164 {
    165     unsigned a = SkGetPackedA32(c);
    166     unsigned r = SkGetPackedR32(c);
    167     unsigned g = SkGetPackedG32(c);
    168     unsigned b = SkGetPackedB32(c);
    169 
    170     dither = SkAlphaMul(dither, SkAlpha255To256(a));
    171 
    172     a = SkDITHER_A32To4444(a, dither);
    173     r = SkDITHER_R32To4444(r, dither);
    174     g = SkDITHER_G32To4444(g, dither);
    175     b = SkDITHER_B32To4444(b, dither);
    176 
    177     return SkPackARGB4444(a, r, g, b);
    178 }
    179 
    180 // TODO: need dither routines for 565 -> 4444
    181 
    182 // this toggles between a 4x4 and a 1x4 array
    183 //#define ENABLE_DITHER_MATRIX_4X4
    184 
    185 #ifdef ENABLE_DITHER_MATRIX_4X4
    186     extern const uint8_t gDitherMatrix_4Bit_4X4[4][4];
    187     extern const uint8_t gDitherMatrix_3Bit_4X4[4][4];
    188 
    189     #define DITHER_4444_SCAN(y) const uint8_t* dither_scan = gDitherMatrix_4Bit_4X4[(y) & 3]
    190     #define DITHER_565_SCAN(y)  const uint8_t* dither_scan = gDitherMatrix_3Bit_4X4[(y) & 3]
    191 
    192     #define DITHER_VALUE(x) dither_scan[(x) & 3]
    193 #else
    194     extern const uint16_t gDitherMatrix_4Bit_16[4];
    195     extern const uint16_t gDitherMatrix_3Bit_16[4];
    196 
    197     #define DITHER_4444_SCAN(y) const uint16_t dither_scan = gDitherMatrix_4Bit_16[(y) & 3]
    198     #define DITHER_565_SCAN(y)  const uint16_t dither_scan = gDitherMatrix_3Bit_16[(y) & 3]
    199 
    200     #define DITHER_VALUE(x) ((dither_scan >> (((x) & 3) << 2)) & 0xF)
    201 #endif
    202 
    203 #define DITHER_INC_X(x) ++(x)
    204 
    205 #endif
    206