Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkBitmap_scroll.cpp
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 signed
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 }