Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4583)

Unified Diff: chrome/browser/renderer_host/backing_store_posix.cc

Issue 21050: POSIX: Backing store scrolling. (Closed)
Patch Set: Created 11 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/renderer_host/backing_store_posix.cc
diff --git a/chrome/browser/renderer_host/backing_store_posix.cc b/chrome/browser/renderer_host/backing_store_posix.cc
index a21b235ff6ae5c9c8861e903c905d487de7510a4..7a56cdf9ba2c4eba008763d6311fc8776448c523 100644
--- a/chrome/browser/renderer_host/backing_store_posix.cc
+++ b/chrome/browser/renderer_host/backing_store_posix.cc
@@ -4,6 +4,11 @@
#include "chrome/browser/renderer_host/backing_store.h"
+#include "base/logging.h"
+#include "skia/ext/platform_canvas.h"
+#include "skia/include/SkBitmap.h"
+#include "skia/include/SkCanvas.h"
+
BackingStore::BackingStore(const gfx::Size& size)
: size_(size) {
if (!canvas_.initialize(size.width(), size.height(), true))
@@ -26,12 +31,134 @@ bool BackingStore::PaintRect(base::ProcessHandle process,
return true;
}
+// Return the given value, clipped to 0..max (inclusive)
+static int RangeClip(int value, int max) {
+ return std::min(max, std::max(value, 0));
+}
+
void BackingStore::ScrollRect(base::ProcessHandle process,
brettw 2009/02/04 20:36:06 Can you make some comment that this is a temporary
BitmapWireData bitmap,
const gfx::Rect& bitmap_rect,
int dx, int dy,
const gfx::Rect& clip_rect,
const gfx::Size& view_size) {
- // TODO(port): implement scrolling
- NOTIMPLEMENTED();
+ // On Windows, there's a ScrollDC call which performs horiz and vertical
+ // scrolling
+ //
+ // clip_rect: MSDN says "The only bits that will be painted are the
+ // bits that remain inside this rectangle after the scroll operation has been
+ // completed."
+ //
+ // The Windows code always sets the whole backing store as the source of the
+ // scroll. Thus, we only have to worry about pixels which will end up inside
+ // the clipping rectangle. (Note that the clipping rectangle is not
+ // translated by the scrol.)
+
+ // We only support scrolling in one direction at a time.
+ DCHECK(dx == 0 || dy == 0);
+
+ if (bitmap.width() != bitmap_rect.width() ||
+ bitmap.height() != bitmap_rect.height() ||
+ bitmap.config() != SkBitmap::kARGB_8888_Config) {
+ return;
+ }
+
+ // We assume that |clip_rect| is within the backing store.
+
+ const SkBitmap &backing_bitmap = canvas_.getDevice()->accessBitmap(true);
+ const int stride = backing_bitmap.rowBytes();
+ uint8_t* x = static_cast<uint8_t*>(backing_bitmap.getPixels());
+
+ if (dx) {
+ // horizontal scroll. Positive values of |dx| scroll right.
+
+ // We know that |clip_rect| is the destination rectangle. The source
+ // rectangle, in an infinite world, would be the destination rectangle
+ // translated by -dx. However, we can't pull pixels from beyound the
+ // edge of the backing store. By truncating the source rectangle to the
+ // backing store, we might have made it thinner, thus we find the final
+ // dest rectangle by translating the resulting source rectangle back.
+ const int bs_width = canvas_.getDevice()->width();
+ const int src_rect_left = RangeClip(clip_rect.x() - dx, bs_width);
+ const int src_rect_right = RangeClip(clip_rect.right() - dx, bs_width);
+
+ const int dest_rect_left = RangeClip(src_rect_left + dx, bs_width);
+ const int dest_rect_right = RangeClip(src_rect_right + dx, bs_width);
+
+ DCHECK(dest_rect_right >= dest_rect_left);
+ DCHECK(src_rect_right >= src_rect_left);
+ DCHECK(dest_rect_right - dest_rect_left ==
+ src_rect_right - src_rect_left);
+
+ // This is the number of bytes to move per line at 4 bytes per pixel.
+ const int len = (dest_rect_right - dest_rect_left) * 4;
+
+ // Position the pixel data pointer at the top-left corner of the dest rect
+ x += clip_rect.y() * stride;
+ x += clip_rect.x() * 4;
+
+ // This is the number of bytes to reach left in order to find the source
+ // rectangle. (Will be negative for a left scroll.)
+ const int left_reach = dest_rect_left - src_rect_left;
+
+ for (int y = clip_rect.y(); y < clip_rect.bottom(); ++y) {
+ // Note that overlapping regions requires memmove, not memcpy.
+ memmove(x, x + left_reach, len);
+ x += stride;
+ }
+ } else {
+ // vertical scroll. Positive values of |dy| scroll down.
+
+ // The logic is very similar to the horizontal case, above.
+ const int bs_height = canvas_.getDevice()->height();
+ const int src_rect_top = RangeClip(clip_rect.y() - dy, bs_height);
+ const int src_rect_bottom = RangeClip(clip_rect.bottom() - dy, bs_height);
+
+ const int dest_rect_top = RangeClip(src_rect_top + dy, bs_height);
+ const int dest_rect_bottom = RangeClip(src_rect_bottom + dy, bs_height);
+
+ const int len = clip_rect.width() * 4;
+
+ DCHECK(dest_rect_bottom >= dest_rect_top);
+ DCHECK(src_rect_bottom >= src_rect_top);
+
+ // We need to consider the two directions separately here because the order
+ // of copying rows must vary to avoid writing data which we later need to
+ // read.
+ if (dy > 0) {
+ // scrolling down; dest rect is above src rect.
brettw 2009/02/04 20:36:06 This comment and the next 3 need capital letters a
+
+ // position the pixel data pointer at the top-left corner of the dest
+ // rect.
+ x += dest_rect_top * stride;
+ x += clip_rect.x() * 4;
+
+ DCHECK(dest_rect_top <= src_rect_top);
+ const int down_reach_bytes = stride * (src_rect_top - dest_rect_top);
+
+ for (int y = dest_rect_top; y < dest_rect_bottom; ++y) {
+ memcpy(x, x + down_reach_bytes, len);
+ x += stride;
+ }
+ } else {
+ // scrolling up; dest rect is below src rect.
+
+ // position the pixel data pointer at the bottom-left corner of the dest
+ // rect.
+ x += (dest_rect_bottom - 1) * stride;
+ x += clip_rect.x() * 4;
+
+ DCHECK(src_rect_top <= dest_rect_top);
+ const int up_reach_bytes = stride * (dest_rect_bottom - src_rect_bottom);
+
+ for (int y = dest_rect_bottom - 1; y >= dest_rect_top; --y) {
+ memcpy(x, x - up_reach_bytes, len);
+ x -= stride;
+ }
+ }
+ }
+
+ // Now paint the new bitmap data.
+ canvas_.drawBitmap(bitmap, bitmap_rect.x(), bitmap_rect.y());
+ return;
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698