• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "SkBitmap.h"
2 #include "SkRegion.h"
3 
scrollRect(const SkIRect * subset,int dx,int dy,SkRegion * inval) const4 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 
108