~ubuntu-branches/ubuntu/karmic/gears/karmic

« back to all changes in this revision

Viewing changes to third_party/skia/src/core/SkBlitter_4444.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Lesicnik
  • Date: 2009-04-30 19:15:25 UTC
  • Revision ID: james.westby@ubuntu.com-20090430191525-0790sb5wzg8ou0xb
Tags: upstream-0.5.21.0~svn3334+dfsg
ImportĀ upstreamĀ versionĀ 0.5.21.0~svn3334+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* libs/graphics/sgl/SkBlitter_ARGB32.cpp
 
2
 **
 
3
 ** Copyright 2006, The Android Open Source Project
 
4
 **
 
5
 ** Licensed under the Apache License, Version 2.0 (the "License"); 
 
6
 ** you may not use this file except in compliance with the License. 
 
7
 ** You may obtain a copy of the License at 
 
8
 **
 
9
 **     http://www.apache.org/licenses/LICENSE-2.0 
 
10
 **
 
11
 ** Unless required by applicable law or agreed to in writing, software 
 
12
 ** distributed under the License is distributed on an "AS IS" BASIS, 
 
13
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 
14
 ** See the License for the specific language governing permissions and 
 
15
 ** limitations under the License.
 
16
 */
 
17
 
 
18
#include "SkCoreBlitters.h"
 
19
#include "SkColorPriv.h"
 
20
#include "SkDither.h"
 
21
#include "SkShader.h"
 
22
#include "SkTemplatesPriv.h"
 
23
#include "SkUtils.h"
 
24
#include "SkXfermode.h"
 
25
 
 
26
inline SkPMColor SkBlendARGB4444(SkPMColor16 src, SkPMColor16 dst, U8CPU aa)
 
27
{
 
28
    SkASSERT((unsigned)aa <= 255);
 
29
    
 
30
    unsigned src_scale = SkAlpha255To256(aa) >> 4;
 
31
    unsigned dst_scale = SkAlpha15To16(15 - SkAlphaMul4(SkGetPackedA4444(src), src_scale));
 
32
    
 
33
    uint32_t src32 = SkExpand_4444(src) * src_scale;
 
34
    uint32_t dst32 = SkExpand_4444(dst) * dst_scale;
 
35
    return SkCompact_4444((src32 + dst32) >> 4);
 
36
}
 
37
 
 
38
///////////////////////////////////////////////////////////////////////////////
 
39
 
 
40
class SkARGB4444_Blitter : public SkRasterBlitter {
 
41
public:
 
42
    SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& paint);
 
43
    virtual void blitH(int x, int y, int width);
 
44
    virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]);
 
45
    virtual void blitV(int x, int y, int height, SkAlpha alpha);
 
46
    virtual void blitRect(int x, int y, int width, int height);
 
47
    virtual void blitMask(const SkMask&, const SkIRect&);
 
48
    virtual const SkBitmap* justAnOpaqueColor(uint32_t*);
 
49
    
 
50
protected:
 
51
    SkPMColor16 fPMColor16, fPMColor16Other;
 
52
    SkPMColor16 fRawColor16, fRawColor16Other;
 
53
    uint8_t     fScale16;
 
54
    
 
55
private:
 
56
    // illegal
 
57
    SkARGB4444_Blitter& operator=(const SkARGB4444_Blitter&);
 
58
    
 
59
    typedef SkRasterBlitter INHERITED;
 
60
};
 
61
 
 
62
 
 
63
SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& paint)
 
64
    : INHERITED(device)
 
65
{
 
66
    // cache premultiplied versions in 4444
 
67
    SkPMColor c = SkPreMultiplyColor(paint.getColor());
 
68
    fPMColor16 = SkPixel32ToPixel4444(c);
 
69
    if (paint.isDither()) {
 
70
        fPMColor16Other = SkDitherPixel32To4444(c);
 
71
    } else {
 
72
        fPMColor16Other = fPMColor16;
 
73
    }
 
74
 
 
75
    // cache raw versions in 4444
 
76
    fRawColor16 = SkPackARGB4444(0xFF >> 4, SkColorGetR(c) >> 4,
 
77
                                 SkColorGetG(c) >> 4, SkColorGetB(c) >> 4);
 
78
    if (paint.isDither()) {
 
79
        fRawColor16Other = SkDitherARGB32To4444(0xFF, SkColorGetR(c),
 
80
                                                SkColorGetG(c), SkColorGetB(c));
 
81
    } else {
 
82
        fRawColor16Other = fRawColor16;
 
83
    }
 
84
    
 
85
    // our dithered color will be the same or more opaque than the original
 
86
    // so use dithered to compute our scale
 
87
    SkASSERT(SkGetPackedA4444(fPMColor16Other) >= SkGetPackedA4444(fPMColor16));
 
88
 
 
89
    fScale16 = SkAlpha15To16(SkGetPackedA4444(fPMColor16Other));
 
90
    if (16 == fScale16) {
 
91
        // force the original to also be opaque
 
92
        fPMColor16 |= (0xF << SK_A4444_SHIFT);
 
93
    }
 
94
}
 
95
 
 
96
const SkBitmap* SkARGB4444_Blitter::justAnOpaqueColor(uint32_t* value)
 
97
{
 
98
    if (16 == fScale16) {
 
99
        *value = fPMColor16;
 
100
        return &fDevice;
 
101
    }
 
102
    return NULL;
 
103
}
 
104
 
 
105
static void src_over_4444(SkPMColor16 dst[], SkPMColor16 color,
 
106
                          SkPMColor16 other, unsigned invScale, int count)
 
107
{
 
108
    int twice = count >> 1;
 
109
    while (--twice >= 0) {
 
110
        *dst = color + SkAlphaMulQ4(*dst, invScale);
 
111
        dst++;
 
112
        *dst = other + SkAlphaMulQ4(*dst, invScale);
 
113
        dst++;
 
114
    }
 
115
    if (color & 1) {
 
116
        *dst = color + SkAlphaMulQ4(*dst, invScale);
 
117
    }
 
118
}
 
119
 
 
120
static inline uint32_t SkExpand_4444_Replicate(SkPMColor16 c)
 
121
{
 
122
    uint32_t c32 = SkExpand_4444(c);
 
123
    return c32 | (c32 << 4);
 
124
}
 
125
 
 
126
static void src_over_4444x(SkPMColor16 dst[], uint32_t color,
 
127
                           uint32_t other, unsigned invScale, int count)
 
128
{
 
129
    int twice = count >> 1;
 
130
    uint32_t tmp;
 
131
    while (--twice >= 0) {
 
132
        tmp = SkExpand_4444(*dst) * invScale;
 
133
        *dst++ = SkCompact_4444((color + tmp) >> 4);
 
134
        tmp = SkExpand_4444(*dst) * invScale;
 
135
        *dst++ = SkCompact_4444((other + tmp) >> 4);
 
136
    }
 
137
    if (color & 1) {
 
138
        tmp = SkExpand_4444(*dst) * invScale;
 
139
        *dst = SkCompact_4444((color + tmp) >> 4);
 
140
    }
 
141
}
 
142
 
 
143
void SkARGB4444_Blitter::blitH(int x, int y, int width)
 
144
{
 
145
    SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
 
146
    
 
147
    if (0 == fScale16) {
 
148
        return;
 
149
    }
 
150
    
 
151
    SkPMColor16* device = fDevice.getAddr16(x, y);
 
152
    SkPMColor16  color = fPMColor16;
 
153
    SkPMColor16  other = fPMColor16Other;
 
154
    
 
155
    if ((x ^ y) & 1) {
 
156
        SkTSwap<SkPMColor16>(color, other);
 
157
    }
 
158
    
 
159
    if (16 == fScale16) {
 
160
        sk_dither_memset16(device, color, other, width);
 
161
    }
 
162
    else {
 
163
        src_over_4444x(device, SkExpand_4444_Replicate(color),
 
164
                       SkExpand_4444_Replicate(other),
 
165
                       16 - fScale16, width);
 
166
    }
 
167
}
 
168
 
 
169
void SkARGB4444_Blitter::blitV(int x, int y, int height, SkAlpha alpha)
 
170
{
 
171
    if (0 == alpha || 0 == fScale16) {
 
172
        return;
 
173
    }
 
174
    
 
175
    SkPMColor16* device = fDevice.getAddr16(x, y);
 
176
    SkPMColor16  color = fPMColor16;
 
177
    SkPMColor16  other = fPMColor16Other;
 
178
    unsigned     rb = fDevice.rowBytes();
 
179
    
 
180
    if ((x ^ y) & 1) {
 
181
        SkTSwap<SkPMColor16>(color, other);
 
182
    }
 
183
 
 
184
    if (16 == fScale16 && 255 == alpha) {
 
185
        while (--height >= 0) {
 
186
            *device = color;
 
187
            device = (SkPMColor16*)((char*)device + rb);
 
188
            SkTSwap<SkPMColor16>(color, other);
 
189
        }
 
190
    } else {
 
191
        unsigned alphaScale = SkAlpha255To256(alpha);
 
192
        uint32_t c32 = SkExpand_4444(color) * (alphaScale >> 4);
 
193
        // need to normalize the low nibble of each expanded component
 
194
        // so we don't overflow the add with d32
 
195
        c32 = SkCompact_4444(c32 >> 4);
 
196
        unsigned invScale = 16 - SkAlpha15To16(SkGetPackedA4444(c32));
 
197
        // now re-expand and replicate
 
198
        c32 = SkExpand_4444_Replicate(c32);
 
199
 
 
200
        while (--height >= 0) {
 
201
            uint32_t d32 = SkExpand_4444(*device) * invScale;
 
202
            *device = SkCompact_4444((c32 + d32) >> 4);
 
203
            device = (SkPMColor16*)((char*)device + rb);
 
204
        }
 
205
    }
 
206
}
 
207
 
 
208
void SkARGB4444_Blitter::blitRect(int x, int y, int width, int height)
 
209
{
 
210
    SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height());
 
211
    
 
212
    if (0 == fScale16) {
 
213
        return;
 
214
    }
 
215
    
 
216
    SkPMColor16* device = fDevice.getAddr16(x, y);
 
217
    SkPMColor16  color = fPMColor16;
 
218
    SkPMColor16  other = fPMColor16Other;
 
219
    
 
220
    if ((x ^ y) & 1) {
 
221
        SkTSwap<SkPMColor16>(color, other);
 
222
    }
 
223
    
 
224
    if (16 == fScale16) {
 
225
        while (--height >= 0) {
 
226
            sk_dither_memset16(device, color, other, width);
 
227
            device = (SkPMColor16*)((char*)device + fDevice.rowBytes());
 
228
            SkTSwap<SkPMColor16>(color, other);
 
229
        }
 
230
    } else {
 
231
        unsigned invScale = 16 - fScale16;
 
232
 
 
233
        uint32_t c32 = SkExpand_4444_Replicate(color);
 
234
        uint32_t o32 = SkExpand_4444_Replicate(other);
 
235
        while (--height >= 0) {
 
236
            src_over_4444x(device, c32, o32, invScale, width);
 
237
            device = (SkPMColor16*)((char*)device + fDevice.rowBytes());
 
238
            SkTSwap<uint32_t>(c32, o32);
 
239
        }
 
240
    }
 
241
}
 
242
 
 
243
void SkARGB4444_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[])
 
244
{
 
245
    if (0 == fScale16) {
 
246
        return;
 
247
    }
 
248
    
 
249
    SkPMColor16* device = fDevice.getAddr16(x, y);
 
250
    SkPMColor16  color = fPMColor16;
 
251
    SkPMColor16  other = fPMColor16Other;
 
252
    
 
253
    if ((x ^ y) & 1) {
 
254
        SkTSwap<SkPMColor16>(color, other);
 
255
    }
 
256
    
 
257
    for (;;) {
 
258
        int count = runs[0];
 
259
        SkASSERT(count >= 0);
 
260
        if (count <= 0) {
 
261
            return;
 
262
        }
 
263
        
 
264
        unsigned aa = antialias[0];
 
265
        if (aa) {
 
266
            if (0xFF == aa) {
 
267
                if (16 == fScale16) {
 
268
                    sk_dither_memset16(device, color, other, count);
 
269
                } else {
 
270
                    src_over_4444(device, color, other, 16 - fScale16, count);
 
271
                }
 
272
            } else {
 
273
                // todo: respect dithering
 
274
                aa = SkAlpha255To256(aa);   // FIX
 
275
                SkPMColor16 src = SkAlphaMulQ4(color, aa >> 4);
 
276
                unsigned dst_scale = SkAlpha15To16(15 - SkGetPackedA4444(src)); // FIX
 
277
                int n = count;
 
278
                do {
 
279
                    --n;
 
280
                    device[n] = src + SkAlphaMulQ4(device[n], dst_scale);
 
281
                } while (n > 0);
 
282
            }
 
283
        }
 
284
 
 
285
        runs += count;
 
286
        antialias += count;
 
287
        device += count;
 
288
 
 
289
        if (count & 1) {
 
290
            SkTSwap<SkPMColor16>(color, other);
 
291
        }
 
292
    }
 
293
}
 
294
 
 
295
//////////////////////////////////////////////////////////////////////////////////////
 
296
 
 
297
#define solid_8_pixels(mask, dst, color)    \
 
298
do {                                    \
 
299
if (mask & 0x80) dst[0] = color;    \
 
300
if (mask & 0x40) dst[1] = color;    \
 
301
if (mask & 0x20) dst[2] = color;    \
 
302
if (mask & 0x10) dst[3] = color;    \
 
303
if (mask & 0x08) dst[4] = color;    \
 
304
if (mask & 0x04) dst[5] = color;    \
 
305
if (mask & 0x02) dst[6] = color;    \
 
306
if (mask & 0x01) dst[7] = color;    \
 
307
} while (0)
 
308
 
 
309
#define SK_BLITBWMASK_NAME                  SkARGB4444_BlitBW
 
310
#define SK_BLITBWMASK_ARGS                  , SkPMColor16 color
 
311
#define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
 
312
#define SK_BLITBWMASK_GETADDR               getAddr16
 
313
#define SK_BLITBWMASK_DEVTYPE               uint16_t
 
314
#include "SkBlitBWMaskTemplate.h"
 
315
 
 
316
#define blend_8_pixels(mask, dst, sc, dst_scale)                            \
 
317
do {                                                                    \
 
318
if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ4(dst[0], dst_scale); }  \
 
319
if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ4(dst[1], dst_scale); }  \
 
320
if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ4(dst[2], dst_scale); }  \
 
321
if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ4(dst[3], dst_scale); }  \
 
322
if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ4(dst[4], dst_scale); }  \
 
323
if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ4(dst[5], dst_scale); }  \
 
324
if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ4(dst[6], dst_scale); }  \
 
325
if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ4(dst[7], dst_scale); }  \
 
326
} while (0)
 
327
 
 
328
#define SK_BLITBWMASK_NAME                  SkARGB4444_BlendBW
 
329
#define SK_BLITBWMASK_ARGS                  , uint16_t sc, unsigned dst_scale
 
330
#define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, sc, dst_scale)
 
331
#define SK_BLITBWMASK_GETADDR               getAddr16
 
332
#define SK_BLITBWMASK_DEVTYPE               uint16_t
 
333
#include "SkBlitBWMaskTemplate.h"
 
334
 
 
335
void SkARGB4444_Blitter::blitMask(const SkMask& mask, const SkIRect& clip)
 
336
{
 
337
    SkASSERT(mask.fBounds.contains(clip));
 
338
    
 
339
    if (0 == fScale16) {
 
340
        return;
 
341
    }
 
342
    
 
343
    if (mask.fFormat == SkMask::kBW_Format) {
 
344
        if (16 == fScale16) {
 
345
            SkARGB4444_BlitBW(fDevice, mask, clip, fPMColor16);
 
346
        } else {
 
347
            SkARGB4444_BlendBW(fDevice, mask, clip, fPMColor16, 16 - fScale16);
 
348
        }
 
349
        return;
 
350
    }
 
351
    
 
352
    int x = clip.fLeft;
 
353
    int y = clip.fTop;
 
354
    int width = clip.width();
 
355
    int height = clip.height();
 
356
    
 
357
    SkPMColor16*    device = fDevice.getAddr16(x, y);
 
358
    const uint8_t*  alpha = mask.getAddr(x, y);
 
359
    SkPMColor16     srcColor = fPMColor16;
 
360
    unsigned        devRB = fDevice.rowBytes() - (width << 1);
 
361
    unsigned        maskRB = mask.fRowBytes - width;
 
362
    
 
363
    do {
 
364
        int w = width;
 
365
        do {
 
366
            unsigned aa = *alpha++;
 
367
            *device = SkBlendARGB4444(srcColor, *device, aa);
 
368
            device += 1;
 
369
        } while (--w != 0);
 
370
        device = (SkPMColor16*)((char*)device + devRB);
 
371
        alpha += maskRB;
 
372
    } while (--height != 0);
 
373
}
 
374
 
 
375
//////////////////////////////////////////////////////////////////////////////////////////
 
376
 
 
377
class SkARGB4444_Shader_Blitter : public SkShaderBlitter {
 
378
    SkXfermode*     fXfermode;
 
379
    SkBlitRow::Proc fOpaqueProc;
 
380
    SkBlitRow::Proc fAlphaProc;
 
381
    SkPMColor*      fBuffer;
 
382
    uint8_t*        fAAExpand;
 
383
public:
 
384
SkARGB4444_Shader_Blitter(const SkBitmap& device, const SkPaint& paint)
 
385
    : INHERITED(device, paint)
 
386
{
 
387
    const int width = device.width();
 
388
    fBuffer = (SkPMColor*)sk_malloc_throw(width * sizeof(SkPMColor) + width);
 
389
    fAAExpand = (uint8_t*)(fBuffer + width);
 
390
    
 
391
    (fXfermode = paint.getXfermode())->safeRef();
 
392
    
 
393
    unsigned flags = 0;
 
394
    if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
 
395
        flags |= SkBlitRow::kSrcPixelAlpha_Flag;
 
396
    }
 
397
    if (paint.isDither()) {
 
398
        flags |= SkBlitRow::kDither_Flag;
 
399
    }
 
400
    fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kARGB_4444_Config);
 
401
    fAlphaProc = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag,
 
402
                                    SkBitmap::kARGB_4444_Config);
 
403
}
 
404
 
 
405
virtual ~SkARGB4444_Shader_Blitter()
 
406
{
 
407
    fXfermode->safeUnref();
 
408
    sk_free(fBuffer);
 
409
}
 
410
 
 
411
virtual void blitH(int x, int y, int width)
 
412
{
 
413
    SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
 
414
    
 
415
    SkPMColor16* device = fDevice.getAddr16(x, y);    
 
416
    SkPMColor*   span = fBuffer;
 
417
    
 
418
    fShader->shadeSpan(x, y, span, width);
 
419
    if (fXfermode) {
 
420
        fXfermode->xfer4444(device, span, width, NULL);
 
421
    }
 
422
    else {
 
423
        fOpaqueProc(device, span, width, 0xFF, x, y);
 
424
    }
 
425
}
 
426
 
 
427
virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[])
 
428
{
 
429
    SkPMColor* SK_RESTRICT span = fBuffer;
 
430
    uint8_t* SK_RESTRICT aaExpand = fAAExpand;
 
431
    SkPMColor16* device = fDevice.getAddr16(x, y);
 
432
    SkShader*    shader = fShader;
 
433
    SkXfermode*  xfer = fXfermode;
 
434
    
 
435
    if (NULL != xfer) {
 
436
        for (;;) {
 
437
            int count = *runs;
 
438
            if (count <= 0)
 
439
                break;
 
440
            int aa = *antialias;
 
441
            if (aa) {
 
442
                shader->shadeSpan(x, y, span, count);
 
443
                if (255 == aa) {
 
444
                    xfer->xfer4444(device, span, count, NULL);
 
445
                } else {
 
446
                    const uint8_t* aaBuffer = antialias;
 
447
                    if (count > 1) {
 
448
                        memset(aaExpand, aa, count);
 
449
                        aaBuffer = aaExpand;
 
450
                    }
 
451
                    xfer->xfer4444(device, span, count, aaBuffer);
 
452
                }
 
453
            }
 
454
            device += count;
 
455
            runs += count;
 
456
            antialias += count;
 
457
            x += count;
 
458
        } 
 
459
    } else {    // no xfermode
 
460
        for (;;) {
 
461
            int count = *runs;
 
462
            if (count <= 0)
 
463
                break;
 
464
            int aa = *antialias;
 
465
            if (aa) {
 
466
                fShader->shadeSpan(x, y, span, count);
 
467
                if (255 == aa) {
 
468
                    fOpaqueProc(device, span, count, aa, x, y);
 
469
                } else {
 
470
                    fAlphaProc(device, span, count, aa, x, y);
 
471
                }
 
472
            }
 
473
            device += count;
 
474
            runs += count;
 
475
            antialias += count;
 
476
            x += count;
 
477
        } 
 
478
    }
 
479
}
 
480
 
 
481
private:
 
482
    typedef SkShaderBlitter INHERITED;
 
483
};
 
484
 
 
485
///////////////////////////////////////////////////////////////////////////////
 
486
///////////////////////////////////////////////////////////////////////////////
 
487
 
 
488
SkBlitter* SkBlitter_ChooseD4444(const SkBitmap& device,
 
489
                                 const SkPaint& paint,
 
490
                                 void* storage, size_t storageSize)
 
491
{
 
492
    SkBlitter* blitter;
 
493
 
 
494
    if (paint.getShader()) {
 
495
        SK_PLACEMENT_NEW_ARGS(blitter, SkARGB4444_Shader_Blitter, storage, storageSize, (device, paint));
 
496
    } else {
 
497
        SK_PLACEMENT_NEW_ARGS(blitter, SkARGB4444_Blitter, storage, storageSize, (device, paint));
 
498
    }
 
499
    return blitter;
 
500
}
 
501