1 #include "SkBitmap.h" 2 #include "SkRegion.h" 3 4 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