1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkBitmap_scroll.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,105 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2011 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 +#include "SkBitmap.h" 1.12 +#include "SkRegion.h" 1.13 + 1.14 +bool SkBitmap::scrollRect(const SkIRect* subset, int dx, int dy, 1.15 + SkRegion* inval) const 1.16 +{ 1.17 + if (this->isImmutable() || kUnknown_SkColorType == this->colorType()) { 1.18 + return false; 1.19 + } 1.20 + 1.21 + if (NULL != subset) { 1.22 + SkBitmap tmp; 1.23 + 1.24 + return this->extractSubset(&tmp, *subset) && 1.25 + // now call again with no rectangle 1.26 + tmp.scrollRect(NULL, dx, dy, inval); 1.27 + } 1.28 + 1.29 + int shift = this->bytesPerPixel() >> 1; 1.30 + int width = this->width(); 1.31 + int height = this->height(); 1.32 + 1.33 + // check if there's nothing to do 1.34 + if ((dx | dy) == 0 || width <= 0 || height <= 0) { 1.35 + if (NULL != inval) { 1.36 + inval->setEmpty(); 1.37 + } 1.38 + return true; 1.39 + } 1.40 + 1.41 + // compute the inval region now, before we see if there are any pixels 1.42 + if (NULL != inval) { 1.43 + SkIRect r; 1.44 + 1.45 + r.set(0, 0, width, height); 1.46 + // initial the region with the entire bounds 1.47 + inval->setRect(r); 1.48 + // do the "scroll" 1.49 + r.offset(dx, dy); 1.50 + 1.51 + // check if we scrolled completely away 1.52 + if (!SkIRect::Intersects(r, inval->getBounds())) { 1.53 + // inval has already been updated... 1.54 + return true; 1.55 + } 1.56 + 1.57 + // compute the dirty area 1.58 + inval->op(r, SkRegion::kDifference_Op); 1.59 + } 1.60 + 1.61 + SkAutoLockPixels alp(*this); 1.62 + // if we have no pixels, just return (inval is already updated) 1.63 + // don't call readyToDraw(), since we don't require a colortable per se 1.64 + if (this->getPixels() == NULL) { 1.65 + return true; 1.66 + } 1.67 + 1.68 + char* dst = (char*)this->getPixels(); 1.69 + const char* src = dst; 1.70 + int rowBytes = (int)this->rowBytes(); // need rowBytes to be signed 1.71 + 1.72 + if (dy <= 0) { 1.73 + src -= dy * rowBytes; 1.74 + height += dy; 1.75 + } else { 1.76 + dst += dy * rowBytes; 1.77 + height -= dy; 1.78 + // now jump src/dst to the last scanline 1.79 + src += (height - 1) * rowBytes; 1.80 + dst += (height - 1) * rowBytes; 1.81 + // now invert rowbytes so we copy backwards in the loop 1.82 + rowBytes = -rowBytes; 1.83 + } 1.84 + 1.85 + if (dx <= 0) { 1.86 + src -= dx << shift; 1.87 + width += dx; 1.88 + } else { 1.89 + dst += dx << shift; 1.90 + width -= dx; 1.91 + } 1.92 + 1.93 + // If the X-translation would push it completely beyond the region, 1.94 + // then there's nothing to draw. 1.95 + if (width <= 0) { 1.96 + return true; 1.97 + } 1.98 + 1.99 + width <<= shift; // now width is the number of bytes to move per line 1.100 + while (--height >= 0) { 1.101 + memmove(dst, src, width); 1.102 + dst += rowBytes; 1.103 + src += rowBytes; 1.104 + } 1.105 + 1.106 + this->notifyPixelsChanged(); 1.107 + return true; 1.108 +}