OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "gfx/blit.h" | 5 #include "gfx/blit.h" |
6 | 6 |
7 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 7 #include "base/logging.h" |
8 #include <cairo/cairo.h> | 8 #include "build/build_config.h" |
9 #endif | |
10 | |
11 #if defined(OS_MACOSX) | |
12 #include "base/scoped_cftyperef.h" | |
13 #endif | |
14 #include "gfx/point.h" | 9 #include "gfx/point.h" |
15 #include "gfx/rect.h" | 10 #include "gfx/rect.h" |
16 #include "skia/ext/platform_canvas.h" | 11 #include "skia/ext/platform_canvas.h" |
17 #include "skia/ext/platform_device.h" | 12 #include "skia/ext/platform_device.h" |
18 | 13 |
| 14 #if defined(TOOLKIT_GTK) |
| 15 #include <cairo/cairo.h> |
| 16 #endif |
| 17 |
| 18 #if defined(OS_MACOSX) |
| 19 #include "base/mac_util.h" |
| 20 #include "base/scoped_cftyperef.h" |
| 21 #endif |
| 22 |
19 namespace gfx { | 23 namespace gfx { |
20 | 24 |
| 25 namespace { |
| 26 |
| 27 // Returns true if the given canvas has any part of itself clipped out or |
| 28 // any non-identity tranform. |
| 29 bool HasClipOrTransform(const skia::PlatformCanvas& canvas) { |
| 30 if (!canvas.getTotalMatrix().isIdentity()) |
| 31 return true; |
| 32 |
| 33 const SkRegion& clip_region = canvas.getTotalClip(); |
| 34 if (clip_region.isEmpty() || clip_region.isComplex()) |
| 35 return true; |
| 36 |
| 37 // Now we know the clip is a regular rectangle, make sure it covers the |
| 38 // entire canvas. |
| 39 const SkBitmap& bitmap = canvas.getTopPlatformDevice().accessBitmap(false); |
| 40 const SkIRect& clip_bounds = clip_region.getBounds(); |
| 41 if (clip_bounds.fLeft != 0 || clip_bounds.fTop != 0 || |
| 42 clip_bounds.fRight != bitmap.width() || |
| 43 clip_bounds.fBottom != bitmap.height()) |
| 44 return true; |
| 45 |
| 46 return false; |
| 47 } |
| 48 |
| 49 } // namespace |
| 50 |
21 void BlitContextToContext(NativeDrawingContext dst_context, | 51 void BlitContextToContext(NativeDrawingContext dst_context, |
22 const Rect& dst_rect, | 52 const Rect& dst_rect, |
23 NativeDrawingContext src_context, | 53 NativeDrawingContext src_context, |
24 const Point& src_origin) { | 54 const Point& src_origin) { |
25 #if defined(OS_WIN) | 55 #if defined(OS_WIN) |
26 BitBlt(dst_context, dst_rect.x(), dst_rect.y(), | 56 BitBlt(dst_context, dst_rect.x(), dst_rect.y(), |
27 dst_rect.width(), dst_rect.height(), | 57 dst_rect.width(), dst_rect.height(), |
28 src_context, src_origin.x(), src_origin.y(), SRCCOPY); | 58 src_context, src_origin.x(), src_origin.y(), SRCCOPY); |
29 #elif defined(OS_MACOSX) | 59 #elif defined(OS_MACOSX) |
30 // Only translations and/or vertical flips in the source context are | 60 // Only translations and/or vertical flips in the source context are |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 } | 121 } |
92 | 122 |
93 void BlitCanvasToCanvas(skia::PlatformCanvas *dst_canvas, | 123 void BlitCanvasToCanvas(skia::PlatformCanvas *dst_canvas, |
94 const Rect& dst_rect, | 124 const Rect& dst_rect, |
95 skia::PlatformCanvas *src_canvas, | 125 skia::PlatformCanvas *src_canvas, |
96 const Point& src_origin) { | 126 const Point& src_origin) { |
97 BlitContextToContext(GetContextFromCanvas(dst_canvas), dst_rect, | 127 BlitContextToContext(GetContextFromCanvas(dst_canvas), dst_rect, |
98 GetContextFromCanvas(src_canvas), src_origin); | 128 GetContextFromCanvas(src_canvas), src_origin); |
99 } | 129 } |
100 | 130 |
| 131 #if defined(OS_WIN) |
| 132 |
| 133 void ScrollCanvas(skia::PlatformCanvas* canvas, |
| 134 const gfx::Rect& clip, |
| 135 const gfx::Point& amount) { |
| 136 DCHECK(!HasClipOrTransform(*canvas)); // Don't support special stuff. |
| 137 HDC hdc = canvas->beginPlatformPaint(); |
| 138 |
| 139 RECT damaged_rect; |
| 140 RECT r = clip.ToRECT(); |
| 141 ScrollDC(hdc, dx, dy, NULL, &r, NULL, &damaged_rect); |
| 142 |
| 143 canvas->endPlatformPaint(); |
| 144 } |
| 145 |
| 146 #elif defined(OS_POSIX) |
| 147 // Cairo has no nice scroll function so we do our own. On Mac it's possible to |
| 148 // use platform scroll code, but it's complex so we just use the same path |
| 149 // here. Either way it will be software-only, so it shouldn't matter much. |
| 150 |
| 151 void ScrollCanvas(skia::PlatformCanvas* canvas, |
| 152 const gfx::Rect& in_clip, |
| 153 const gfx::Point& amount) { |
| 154 DCHECK(!HasClipOrTransform(*canvas)); // Don't support special stuff. |
| 155 SkBitmap& bitmap = const_cast<SkBitmap&>( |
| 156 canvas->getTopPlatformDevice().accessBitmap(true)); |
| 157 SkAutoLockPixels lock(bitmap); |
| 158 |
| 159 // We expect all coords to be inside the canvas, so clip here. |
| 160 gfx::Rect clip = in_clip.Intersect( |
| 161 gfx::Rect(0, 0, bitmap.width(), bitmap.height())); |
| 162 |
| 163 // Compute the set of pixels we'll actually end up painting. |
| 164 gfx::Rect dest_rect = clip; |
| 165 dest_rect.Offset(amount); |
| 166 dest_rect = dest_rect.Intersect(clip); |
| 167 if (dest_rect.size() == gfx::Size()) |
| 168 return; // Nothing to do. |
| 169 |
| 170 // Compute the source pixels that will map to the dest_rect |
| 171 gfx::Rect src_rect = dest_rect; |
| 172 src_rect.Offset(-amount.x(), -amount.y()); |
| 173 |
| 174 size_t row_bytes = dest_rect.width() * 4; |
| 175 if (amount.y() > 0) { |
| 176 // Data is moving down, copy from the bottom up. |
| 177 for (int y = dest_rect.height() - 1; y >= 0; y--) { |
| 178 memcpy(bitmap.getAddr32(dest_rect.x(), dest_rect.y() + y), |
| 179 bitmap.getAddr32(src_rect.x(), src_rect.y() + y), |
| 180 row_bytes); |
| 181 } |
| 182 } else if (amount.y() < 0) { |
| 183 // Data is moving up, copy from the top down. |
| 184 for (int y = 0; y < dest_rect.height(); y++) { |
| 185 memcpy(bitmap.getAddr32(dest_rect.x(), dest_rect.y() + y), |
| 186 bitmap.getAddr32(src_rect.x(), src_rect.y() + y), |
| 187 row_bytes); |
| 188 } |
| 189 } else if (amount.x() != 0) { |
| 190 // Horizontal-only scroll. We can do it in either top-to-bottom or bottom- |
| 191 // to-top, but have to be careful about the order for copying each row. |
| 192 // Fortunately, memmove already handles this for us. |
| 193 for (int y = 0; y < dest_rect.height(); y++) { |
| 194 memmove(bitmap.getAddr32(dest_rect.x(), dest_rect.y() + y), |
| 195 bitmap.getAddr32(src_rect.x(), src_rect.y() + y), |
| 196 row_bytes); |
| 197 } |
| 198 } |
| 199 } |
| 200 |
| 201 #endif |
| 202 |
101 } // namespace gfx | 203 } // namespace gfx |
OLD | NEW |