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