11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/* 31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc. 41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * 51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file. 71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */ 80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBitmap.h" 90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkRegion.h" 100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkBitmap::scrollRect(const SkIRect* subset, int dx, int dy, 120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRegion* inval) const 130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ 140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL != subset) { 150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkBitmap tmp; 160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return this->extractSubset(&tmp, *subset) && 180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // now call again with no rectangle 190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tmp.scrollRect(NULL, dx, dy, inval); 200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int shift; 230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (this->config()) { 250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kIndex8_Config: 260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kA8_Config: 270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project shift = 0; 280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kARGB_4444_Config: 300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kRGB_565_Config: 310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project shift = 1; 320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kARGB_8888_Config: 340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project shift = 2; 350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project default: 370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // can't scroll this config 380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int width = this->width(); 420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int height = this->height(); 430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // check if there's nothing to do 450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if ((dx | dy) == 0 || width <= 0 || height <= 0) { 460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL != inval) { 470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project inval->setEmpty(); 480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // compute the inval region now, before we see if there are any pixels 530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL != inval) { 540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIRect r; 550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.set(0, 0, width, height); 570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // initial the region with the entire bounds 580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project inval->setRect(r); 590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // do the "scroll" 600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.offset(dx, dy); 610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // check if we scrolled completely away 630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!SkIRect::Intersects(r, inval->getBounds())) { 640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // inval has already been updated... 650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // compute the dirty area 690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project inval->op(r, SkRegion::kDifference_Op); 700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoLockPixels alp(*this); 730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // if we have no pixels, just return (inval is already updated) 740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // don't call readyToDraw(), since we don't require a colortable per se 750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (this->getPixels() == NULL) { 760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project char* dst = (char*)this->getPixels(); 800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const char* src = dst; 810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int rowBytes = this->rowBytes(); // need rowBytes to be signed 820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (dy <= 0) { 840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project src -= dy * rowBytes; 850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project height += dy; 860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst += dy * rowBytes; 880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project height -= dy; 890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // now jump src/dst to the last scanline 900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project src += (height - 1) * rowBytes; 910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst += (height - 1) * rowBytes; 920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // now invert rowbytes so we copy backwards in the loop 930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rowBytes = -rowBytes; 940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (dx <= 0) { 970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project src -= dx << shift; 980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project width += dx; 990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst += dx << shift; 1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project width -= dx; 1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // If the X-translation would push it completely beyond the region, 1051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // then there's nothing to draw. 1061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (width <= 0) { 1071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return true; 1081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project width <<= shift; // now width is the number of bytes to move per line 1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while (--height >= 0) { 1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memmove(dst, src, width); 1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst += rowBytes; 1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project src += rowBytes; 1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 118