diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/src/core/SkBitmap_scroll.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/src/core/SkBitmap_scroll.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,105 @@ + +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "SkBitmap.h" +#include "SkRegion.h" + +bool SkBitmap::scrollRect(const SkIRect* subset, int dx, int dy, + SkRegion* inval) const +{ + if (this->isImmutable() || kUnknown_SkColorType == this->colorType()) { + return false; + } + + if (NULL != subset) { + SkBitmap tmp; + + return this->extractSubset(&tmp, *subset) && + // now call again with no rectangle + tmp.scrollRect(NULL, dx, dy, inval); + } + + int shift = this->bytesPerPixel() >> 1; + int width = this->width(); + int height = this->height(); + + // check if there's nothing to do + if ((dx | dy) == 0 || width <= 0 || height <= 0) { + if (NULL != inval) { + inval->setEmpty(); + } + return true; + } + + // compute the inval region now, before we see if there are any pixels + if (NULL != inval) { + SkIRect r; + + r.set(0, 0, width, height); + // initial the region with the entire bounds + inval->setRect(r); + // do the "scroll" + r.offset(dx, dy); + + // check if we scrolled completely away + if (!SkIRect::Intersects(r, inval->getBounds())) { + // inval has already been updated... + return true; + } + + // compute the dirty area + inval->op(r, SkRegion::kDifference_Op); + } + + SkAutoLockPixels alp(*this); + // if we have no pixels, just return (inval is already updated) + // don't call readyToDraw(), since we don't require a colortable per se + if (this->getPixels() == NULL) { + return true; + } + + char* dst = (char*)this->getPixels(); + const char* src = dst; + int rowBytes = (int)this->rowBytes(); // need rowBytes to be signed + + if (dy <= 0) { + src -= dy * rowBytes; + height += dy; + } else { + dst += dy * rowBytes; + height -= dy; + // now jump src/dst to the last scanline + src += (height - 1) * rowBytes; + dst += (height - 1) * rowBytes; + // now invert rowbytes so we copy backwards in the loop + rowBytes = -rowBytes; + } + + if (dx <= 0) { + src -= dx << shift; + width += dx; + } else { + dst += dx << shift; + width -= dx; + } + + // If the X-translation would push it completely beyond the region, + // then there's nothing to draw. + if (width <= 0) { + return true; + } + + width <<= shift; // now width is the number of bytes to move per line + while (--height >= 0) { + memmove(dst, src, width); + dst += rowBytes; + src += rowBytes; + } + + this->notifyPixelsChanged(); + return true; +}