1 /*
2 * Copyright 2006 The Android Open Source Project
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 // This file does not have include guards because it is not meant to be used on its own.
8
9 #include "include/core/SkPixmap.h"
10 #include "include/core/SkRect.h"
11 #include "include/private/base/SkAssert.h"
12 #include "src/core/SkMask.h"
13
14 #include <cstddef>
15 #include <cstdint>
16
17 #ifndef ClearLow3Bits_DEFINED
18 #define ClearLow3Bits_DEFINED
19 #define ClearLow3Bits(x) ((unsigned)(x) >> 3 << 3)
20 #endif
21
22 /*
23 SK_BLITBWMASK_NAME name of function(const SkPixmap& dstPixmap, const SkMask& mask, const SkIRect& clip, SK_BLITBWMASK_ARGS)
24 SK_BLITBWMASK_ARGS list of additional arguments to SK_BLITBWMASK_NAME, beginning with a comma
25 SK_BLITBWMASK_BLIT8 name of function(U8CPU byteMask, SK_BLITBWMASK_DEVTYPE* dst, int x, int y)
26 SK_BLITBWMASK_GETADDR either writable_addr[8,16,32]
27 SK_BLITBWMASK_DEVTYPE either U32 or U16 or U8
28 */
29
SK_BLITBWMASK_NAME(const SkPixmap & dstPixmap,const SkMask & srcMask,const SkIRect & clip SK_BLITBWMASK_ARGS)30 static void SK_BLITBWMASK_NAME(const SkPixmap& dstPixmap, const SkMask& srcMask,
31 const SkIRect& clip SK_BLITBWMASK_ARGS) {
32 SkASSERT(clip.fRight <= srcMask.fBounds.fRight);
33
34 int cx = clip.fLeft;
35 int cy = clip.fTop;
36 int maskLeft = srcMask.fBounds.fLeft;
37 unsigned mask_rowBytes = srcMask.fRowBytes;
38 size_t bitmap_rowBytes = dstPixmap.rowBytes();
39 unsigned height = clip.height();
40
41 SkASSERT(mask_rowBytes != 0);
42 SkASSERT(bitmap_rowBytes != 0);
43 SkASSERT(height != 0);
44
45 const uint8_t* bits = srcMask.getAddr1(cx, cy);
46 SK_BLITBWMASK_DEVTYPE* device = dstPixmap.SK_BLITBWMASK_GETADDR(cx, cy);
47
48 if (cx == maskLeft && clip.fRight == srcMask.fBounds.fRight)
49 {
50 do {
51 SK_BLITBWMASK_DEVTYPE* dst = device;
52 unsigned rb = mask_rowBytes;
53 do {
54 U8CPU mask = *bits++;
55 SK_BLITBWMASK_BLIT8(mask, dst);
56 dst += 8;
57 } while (--rb != 0);
58 device = (SK_BLITBWMASK_DEVTYPE*)((char*)device + bitmap_rowBytes);
59 } while (--height != 0);
60 }
61 else
62 {
63 int left_edge = cx - maskLeft;
64 SkASSERT(left_edge >= 0);
65 int rite_edge = clip.fRight - maskLeft;
66 SkASSERT(rite_edge > left_edge);
67
68 int left_mask = 0xFF >> (left_edge & 7);
69 int rite_mask = 0xFF << (8 - (rite_edge & 7));
70 rite_mask &= 0xFF; // only want low-8 bits of mask
71 int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3);
72
73 // check for empty right mask, so we don't read off the end (or go slower than we need to)
74 if (rite_mask == 0)
75 {
76 SkASSERT(full_runs >= 0);
77 full_runs -= 1;
78 rite_mask = 0xFF;
79 }
80 if (left_mask == 0xFF)
81 full_runs -= 1;
82
83 // back up manually so we can keep in sync with our byte-aligned src
84 // and not trigger an assert from the getAddr## function
85 device -= left_edge & 7;
86
87 if (full_runs < 0)
88 {
89 left_mask &= rite_mask;
90 SkASSERT(left_mask != 0);
91 do {
92 U8CPU mask = *bits & left_mask;
93 SK_BLITBWMASK_BLIT8(mask, device);
94 bits += mask_rowBytes;
95 device = (SK_BLITBWMASK_DEVTYPE*)((char*)device + bitmap_rowBytes);
96 } while (--height != 0);
97 }
98 else
99 {
100 do {
101 int runs = full_runs;
102 SK_BLITBWMASK_DEVTYPE* dst = device;
103 const uint8_t* b = bits;
104 U8CPU mask;
105
106 mask = *b++ & left_mask;
107 SK_BLITBWMASK_BLIT8(mask, dst);
108 dst += 8;
109
110 while (--runs >= 0)
111 {
112 mask = *b++;
113 SK_BLITBWMASK_BLIT8(mask, dst);
114 dst += 8;
115 }
116
117 mask = *b & rite_mask;
118 SK_BLITBWMASK_BLIT8(mask, dst);
119
120 bits += mask_rowBytes;
121 device = (SK_BLITBWMASK_DEVTYPE*)((char*)device + bitmap_rowBytes);
122 } while (--height != 0);
123 }
124 }
125 }
126
127 #undef SK_BLITBWMASK_NAME
128 #undef SK_BLITBWMASK_ARGS
129 #undef SK_BLITBWMASK_BLIT8
130 #undef SK_BLITBWMASK_GETADDR
131 #undef SK_BLITBWMASK_DEVTYPE
132 #undef SK_BLITBWMASK_DOROWSETUP
133