OLD | NEW |
| (Empty) |
1 #include "SkBitmap.h" | |
2 #include "SkRegion.h" | |
3 | |
4 bool SkBitmap::scrollRect(const SkIRect* subset, int dx, int dy, | |
5 SkRegion* inval) const | |
6 { | |
7 if (NULL != subset) { | |
8 SkBitmap tmp; | |
9 | |
10 return this->extractSubset(&tmp, *subset) && | |
11 // now call again with no rectangle | |
12 tmp.scrollRect(NULL, dx, dy, inval); | |
13 } | |
14 | |
15 int shift; | |
16 | |
17 switch (this->config()) { | |
18 case kIndex8_Config: | |
19 case kA8_Config: | |
20 shift = 0; | |
21 break; | |
22 case kARGB_4444_Config: | |
23 case kRGB_565_Config: | |
24 shift = 1; | |
25 break; | |
26 case kARGB_8888_Config: | |
27 shift = 2; | |
28 break; | |
29 default: | |
30 // can't scroll this config | |
31 return false; | |
32 } | |
33 | |
34 int width = this->width(); | |
35 int height = this->height(); | |
36 | |
37 // check if there's nothing to do | |
38 if ((dx | dy) == 0 || width <= 0 || height <= 0) { | |
39 if (NULL != inval) { | |
40 inval->setEmpty(); | |
41 } | |
42 return true; | |
43 } | |
44 | |
45 // compute the inval region now, before we see if there are any pixels | |
46 if (NULL != inval) { | |
47 SkIRect r; | |
48 | |
49 r.set(0, 0, width, height); | |
50 // initial the region with the entire bounds | |
51 inval->setRect(r); | |
52 // do the "scroll" | |
53 r.offset(dx, dy); | |
54 | |
55 // check if we scrolled completely away | |
56 if (!SkIRect::Intersects(r, inval->getBounds())) { | |
57 // inval has already been updated... | |
58 return true; | |
59 } | |
60 | |
61 // compute the dirty area | |
62 inval->op(r, SkRegion::kDifference_Op); | |
63 } | |
64 | |
65 SkAutoLockPixels alp(*this); | |
66 // if we have no pixels, just return (inval is already updated) | |
67 // don't call readyToDraw(), since we don't require a colortable per se | |
68 if (this->getPixels() == NULL) { | |
69 return true; | |
70 } | |
71 | |
72 // if we get this far, then we need to shift the pixels | |
73 | |
74 char* dst = (char*)this->getPixels(); | |
75 const char* src = dst; | |
76 int rowBytes = this->rowBytes(); // need rowBytes to be signed | |
77 | |
78 if (dy <= 0) { | |
79 src -= dy * rowBytes; | |
80 height += dy; | |
81 } else { | |
82 dst += dy * rowBytes; | |
83 height -= dy; | |
84 // now jump src/dst to the last scanline | |
85 src += (height - 1) * rowBytes; | |
86 dst += (height - 1) * rowBytes; | |
87 // now invert rowbytes so we copy backwards in the loop | |
88 rowBytes = -rowBytes; | |
89 } | |
90 | |
91 if (dx <= 0) { | |
92 src -= dx << shift; | |
93 width += dx; | |
94 } else { | |
95 dst += dx << shift; | |
96 width -= dx; | |
97 } | |
98 | |
99 width <<= shift; // now width is the number of bytes to move per line | |
100 while (--height >= 0) { | |
101 memmove(dst, src, width); | |
102 dst += rowBytes; | |
103 src += rowBytes; | |
104 } | |
105 return true; | |
106 } | |
107 | |
OLD | NEW |