OLD | NEW |
---|---|
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/renderer_host/backing_store.h" | 5 #include "chrome/browser/renderer_host/backing_store.h" |
6 | 6 |
7 #include "base/logging.h" | |
8 #include "skia/ext/platform_canvas.h" | |
9 #include "skia/include/SkBitmap.h" | |
10 #include "skia/include/SkCanvas.h" | |
11 | |
7 BackingStore::BackingStore(const gfx::Size& size) | 12 BackingStore::BackingStore(const gfx::Size& size) |
8 : size_(size) { | 13 : size_(size) { |
9 if (!canvas_.initialize(size.width(), size.height(), true)) | 14 if (!canvas_.initialize(size.width(), size.height(), true)) |
10 SK_CRASH(); | 15 SK_CRASH(); |
11 } | 16 } |
12 | 17 |
13 BackingStore::~BackingStore() { | 18 BackingStore::~BackingStore() { |
14 } | 19 } |
15 | 20 |
16 bool BackingStore::PaintRect(base::ProcessHandle process, | 21 bool BackingStore::PaintRect(base::ProcessHandle process, |
17 BitmapWireData bitmap, | 22 BitmapWireData bitmap, |
18 const gfx::Rect& bitmap_rect) { | 23 const gfx::Rect& bitmap_rect) { |
19 if (bitmap.width() != bitmap_rect.width() || | 24 if (bitmap.width() != bitmap_rect.width() || |
20 bitmap.height() != bitmap_rect.height() || | 25 bitmap.height() != bitmap_rect.height() || |
21 bitmap.config() != SkBitmap::kARGB_8888_Config) { | 26 bitmap.config() != SkBitmap::kARGB_8888_Config) { |
22 return false; | 27 return false; |
23 } | 28 } |
24 | 29 |
25 canvas_.drawBitmap(bitmap, bitmap_rect.x(), bitmap_rect.y()); | 30 canvas_.drawBitmap(bitmap, bitmap_rect.x(), bitmap_rect.y()); |
26 return true; | 31 return true; |
27 } | 32 } |
28 | 33 |
34 // Return the given value, clipped to 0..max (inclusive) | |
35 static int RangeClip(int value, int max) { | |
36 return std::min(max, std::max(value, 0)); | |
37 } | |
38 | |
29 void BackingStore::ScrollRect(base::ProcessHandle process, | 39 void BackingStore::ScrollRect(base::ProcessHandle process, |
brettw
2009/02/04 20:36:06
Can you make some comment that this is a temporary
| |
30 BitmapWireData bitmap, | 40 BitmapWireData bitmap, |
31 const gfx::Rect& bitmap_rect, | 41 const gfx::Rect& bitmap_rect, |
32 int dx, int dy, | 42 int dx, int dy, |
33 const gfx::Rect& clip_rect, | 43 const gfx::Rect& clip_rect, |
34 const gfx::Size& view_size) { | 44 const gfx::Size& view_size) { |
35 // TODO(port): implement scrolling | 45 // On Windows, there's a ScrollDC call which performs horiz and vertical |
36 NOTIMPLEMENTED(); | 46 // scrolling |
47 // | |
48 // clip_rect: MSDN says "The only bits that will be painted are the | |
49 // bits that remain inside this rectangle after the scroll operation has been | |
50 // completed." | |
51 // | |
52 // The Windows code always sets the whole backing store as the source of the | |
53 // scroll. Thus, we only have to worry about pixels which will end up inside | |
54 // the clipping rectangle. (Note that the clipping rectangle is not | |
55 // translated by the scrol.) | |
56 | |
57 // We only support scrolling in one direction at a time. | |
58 DCHECK(dx == 0 || dy == 0); | |
59 | |
60 if (bitmap.width() != bitmap_rect.width() || | |
61 bitmap.height() != bitmap_rect.height() || | |
62 bitmap.config() != SkBitmap::kARGB_8888_Config) { | |
63 return; | |
64 } | |
65 | |
66 // We assume that |clip_rect| is within the backing store. | |
67 | |
68 const SkBitmap &backing_bitmap = canvas_.getDevice()->accessBitmap(true); | |
69 const int stride = backing_bitmap.rowBytes(); | |
70 uint8_t* x = static_cast<uint8_t*>(backing_bitmap.getPixels()); | |
71 | |
72 if (dx) { | |
73 // horizontal scroll. Positive values of |dx| scroll right. | |
74 | |
75 // We know that |clip_rect| is the destination rectangle. The source | |
76 // rectangle, in an infinite world, would be the destination rectangle | |
77 // translated by -dx. However, we can't pull pixels from beyound the | |
78 // edge of the backing store. By truncating the source rectangle to the | |
79 // backing store, we might have made it thinner, thus we find the final | |
80 // dest rectangle by translating the resulting source rectangle back. | |
81 const int bs_width = canvas_.getDevice()->width(); | |
82 const int src_rect_left = RangeClip(clip_rect.x() - dx, bs_width); | |
83 const int src_rect_right = RangeClip(clip_rect.right() - dx, bs_width); | |
84 | |
85 const int dest_rect_left = RangeClip(src_rect_left + dx, bs_width); | |
86 const int dest_rect_right = RangeClip(src_rect_right + dx, bs_width); | |
87 | |
88 DCHECK(dest_rect_right >= dest_rect_left); | |
89 DCHECK(src_rect_right >= src_rect_left); | |
90 DCHECK(dest_rect_right - dest_rect_left == | |
91 src_rect_right - src_rect_left); | |
92 | |
93 // This is the number of bytes to move per line at 4 bytes per pixel. | |
94 const int len = (dest_rect_right - dest_rect_left) * 4; | |
95 | |
96 // Position the pixel data pointer at the top-left corner of the dest rect | |
97 x += clip_rect.y() * stride; | |
98 x += clip_rect.x() * 4; | |
99 | |
100 // This is the number of bytes to reach left in order to find the source | |
101 // rectangle. (Will be negative for a left scroll.) | |
102 const int left_reach = dest_rect_left - src_rect_left; | |
103 | |
104 for (int y = clip_rect.y(); y < clip_rect.bottom(); ++y) { | |
105 // Note that overlapping regions requires memmove, not memcpy. | |
106 memmove(x, x + left_reach, len); | |
107 x += stride; | |
108 } | |
109 } else { | |
110 // vertical scroll. Positive values of |dy| scroll down. | |
111 | |
112 // The logic is very similar to the horizontal case, above. | |
113 const int bs_height = canvas_.getDevice()->height(); | |
114 const int src_rect_top = RangeClip(clip_rect.y() - dy, bs_height); | |
115 const int src_rect_bottom = RangeClip(clip_rect.bottom() - dy, bs_height); | |
116 | |
117 const int dest_rect_top = RangeClip(src_rect_top + dy, bs_height); | |
118 const int dest_rect_bottom = RangeClip(src_rect_bottom + dy, bs_height); | |
119 | |
120 const int len = clip_rect.width() * 4; | |
121 | |
122 DCHECK(dest_rect_bottom >= dest_rect_top); | |
123 DCHECK(src_rect_bottom >= src_rect_top); | |
124 | |
125 // We need to consider the two directions separately here because the order | |
126 // of copying rows must vary to avoid writing data which we later need to | |
127 // read. | |
128 if (dy > 0) { | |
129 // 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
| |
130 | |
131 // position the pixel data pointer at the top-left corner of the dest | |
132 // rect. | |
133 x += dest_rect_top * stride; | |
134 x += clip_rect.x() * 4; | |
135 | |
136 DCHECK(dest_rect_top <= src_rect_top); | |
137 const int down_reach_bytes = stride * (src_rect_top - dest_rect_top); | |
138 | |
139 for (int y = dest_rect_top; y < dest_rect_bottom; ++y) { | |
140 memcpy(x, x + down_reach_bytes, len); | |
141 x += stride; | |
142 } | |
143 } else { | |
144 // scrolling up; dest rect is below src rect. | |
145 | |
146 // position the pixel data pointer at the bottom-left corner of the dest | |
147 // rect. | |
148 x += (dest_rect_bottom - 1) * stride; | |
149 x += clip_rect.x() * 4; | |
150 | |
151 DCHECK(src_rect_top <= dest_rect_top); | |
152 const int up_reach_bytes = stride * (dest_rect_bottom - src_rect_bottom); | |
153 | |
154 for (int y = dest_rect_bottom - 1; y >= dest_rect_top; --y) { | |
155 memcpy(x, x - up_reach_bytes, len); | |
156 x -= stride; | |
157 } | |
158 } | |
159 } | |
160 | |
161 // Now paint the new bitmap data. | |
162 canvas_.drawBitmap(bitmap, bitmap_rect.x(), bitmap_rect.y()); | |
163 return; | |
37 } | 164 } |
OLD | NEW |