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

Side by Side Diff: gfx/blit.cc

Issue 6246027: Move src/gfx/ to src/ui/gfx... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 10 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « gfx/blit.h ('k') | gfx/blit_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "gfx/blit.h"
6
7 #include "base/logging.h"
8 #include "build/build_config.h"
9 #include "gfx/point.h"
10 #include "gfx/rect.h"
11 #include "skia/ext/platform_canvas.h"
12 #include "skia/ext/platform_device.h"
13
14 #if defined(OS_POSIX) && !defined(OS_MACOSX)
15 #include <cairo/cairo.h>
16 #endif
17
18 #if defined(OS_MACOSX)
19 #include "base/mac/scoped_cftyperef.h"
20 #endif
21
22 namespace gfx {
23
24 namespace {
25
26 // Returns true if the given canvas has any part of itself clipped out or
27 // any non-identity tranform.
28 bool HasClipOrTransform(const skia::PlatformCanvas& canvas) {
29 if (!canvas.getTotalMatrix().isIdentity())
30 return true;
31
32 const SkRegion& clip_region = canvas.getTotalClip();
33 if (clip_region.isEmpty() || clip_region.isComplex())
34 return true;
35
36 // Now we know the clip is a regular rectangle, make sure it covers the
37 // entire canvas.
38 const SkBitmap& bitmap = canvas.getTopPlatformDevice().accessBitmap(false);
39 const SkIRect& clip_bounds = clip_region.getBounds();
40 if (clip_bounds.fLeft != 0 || clip_bounds.fTop != 0 ||
41 clip_bounds.fRight != bitmap.width() ||
42 clip_bounds.fBottom != bitmap.height())
43 return true;
44
45 return false;
46 }
47
48 } // namespace
49
50 void BlitContextToContext(NativeDrawingContext dst_context,
51 const Rect& dst_rect,
52 NativeDrawingContext src_context,
53 const Point& src_origin) {
54 #if defined(OS_WIN)
55 BitBlt(dst_context, dst_rect.x(), dst_rect.y(),
56 dst_rect.width(), dst_rect.height(),
57 src_context, src_origin.x(), src_origin.y(), SRCCOPY);
58 #elif defined(OS_MACOSX)
59 // Only translations and/or vertical flips in the source context are
60 // supported; more complex source context transforms will be ignored.
61
62 // If there is a translation on the source context, we need to account for
63 // it ourselves since CGBitmapContextCreateImage will bypass it.
64 Rect src_rect(src_origin, dst_rect.size());
65 CGAffineTransform transform = CGContextGetCTM(src_context);
66 bool flipped = fabs(transform.d + 1) < 0.0001;
67 CGFloat delta_y = flipped ? CGBitmapContextGetHeight(src_context) -
68 transform.ty
69 : transform.ty;
70 src_rect.Offset(transform.tx, delta_y);
71
72 base::mac::ScopedCFTypeRef<CGImageRef>
73 src_image(CGBitmapContextCreateImage(src_context));
74 base::mac::ScopedCFTypeRef<CGImageRef> src_sub_image(
75 CGImageCreateWithImageInRect(src_image, src_rect.ToCGRect()));
76 CGContextDrawImage(dst_context, dst_rect.ToCGRect(), src_sub_image);
77 #else // Linux, BSD, others
78 // Only translations in the source context are supported; more complex
79 // source context transforms will be ignored.
80 cairo_save(dst_context);
81 double surface_x = src_origin.x();
82 double surface_y = src_origin.y();
83 cairo_user_to_device(src_context, &surface_x, &surface_y);
84 cairo_set_source_surface(dst_context, cairo_get_target(src_context),
85 dst_rect.x()-surface_x, dst_rect.y()-surface_y);
86 cairo_rectangle(dst_context, dst_rect.x(), dst_rect.y(),
87 dst_rect.width(), dst_rect.height());
88 cairo_clip(dst_context);
89 cairo_paint(dst_context);
90 cairo_restore(dst_context);
91 #endif
92 }
93
94 static NativeDrawingContext GetContextFromCanvas(
95 skia::PlatformCanvas *canvas) {
96 skia::PlatformDevice& device = canvas->getTopPlatformDevice();
97 #if defined(OS_WIN)
98 return device.getBitmapDC();
99 #elif defined(OS_MACOSX)
100 return device.GetBitmapContext();
101 #else // Linux, BSD, others
102 return device.beginPlatformPaint();
103 #endif
104 }
105
106 void BlitContextToCanvas(skia::PlatformCanvas *dst_canvas,
107 const Rect& dst_rect,
108 NativeDrawingContext src_context,
109 const Point& src_origin) {
110 BlitContextToContext(GetContextFromCanvas(dst_canvas), dst_rect,
111 src_context, src_origin);
112 }
113
114 void BlitCanvasToContext(NativeDrawingContext dst_context,
115 const Rect& dst_rect,
116 skia::PlatformCanvas *src_canvas,
117 const Point& src_origin) {
118 BlitContextToContext(dst_context, dst_rect,
119 GetContextFromCanvas(src_canvas), src_origin);
120 }
121
122 void BlitCanvasToCanvas(skia::PlatformCanvas *dst_canvas,
123 const Rect& dst_rect,
124 skia::PlatformCanvas *src_canvas,
125 const Point& src_origin) {
126 BlitContextToContext(GetContextFromCanvas(dst_canvas), dst_rect,
127 GetContextFromCanvas(src_canvas), src_origin);
128 }
129
130 #if defined(OS_WIN)
131
132 void ScrollCanvas(skia::PlatformCanvas* canvas,
133 const gfx::Rect& clip,
134 const gfx::Point& amount) {
135 DCHECK(!HasClipOrTransform(*canvas)); // Don't support special stuff.
136 HDC hdc = canvas->beginPlatformPaint();
137
138 RECT damaged_rect;
139 RECT r = clip.ToRECT();
140 ScrollDC(hdc, amount.x(), amount.y(), NULL, &r, NULL, &damaged_rect);
141
142 canvas->endPlatformPaint();
143 }
144
145 #elif defined(OS_POSIX)
146 // Cairo has no nice scroll function so we do our own. On Mac it's possible to
147 // use platform scroll code, but it's complex so we just use the same path
148 // here. Either way it will be software-only, so it shouldn't matter much.
149
150 void ScrollCanvas(skia::PlatformCanvas* canvas,
151 const gfx::Rect& in_clip,
152 const gfx::Point& amount) {
153 DCHECK(!HasClipOrTransform(*canvas)); // Don't support special stuff.
154 SkBitmap& bitmap = const_cast<SkBitmap&>(
155 canvas->getTopPlatformDevice().accessBitmap(true));
156 SkAutoLockPixels lock(bitmap);
157
158 // We expect all coords to be inside the canvas, so clip here.
159 gfx::Rect clip = in_clip.Intersect(
160 gfx::Rect(0, 0, bitmap.width(), bitmap.height()));
161
162 // Compute the set of pixels we'll actually end up painting.
163 gfx::Rect dest_rect = clip;
164 dest_rect.Offset(amount);
165 dest_rect = dest_rect.Intersect(clip);
166 if (dest_rect.size() == gfx::Size())
167 return; // Nothing to do.
168
169 // Compute the source pixels that will map to the dest_rect
170 gfx::Rect src_rect = dest_rect;
171 src_rect.Offset(-amount.x(), -amount.y());
172
173 size_t row_bytes = dest_rect.width() * 4;
174 if (amount.y() > 0) {
175 // Data is moving down, copy from the bottom up.
176 for (int y = dest_rect.height() - 1; y >= 0; y--) {
177 memcpy(bitmap.getAddr32(dest_rect.x(), dest_rect.y() + y),
178 bitmap.getAddr32(src_rect.x(), src_rect.y() + y),
179 row_bytes);
180 }
181 } else if (amount.y() < 0) {
182 // Data is moving up, copy from the top down.
183 for (int y = 0; y < dest_rect.height(); y++) {
184 memcpy(bitmap.getAddr32(dest_rect.x(), dest_rect.y() + y),
185 bitmap.getAddr32(src_rect.x(), src_rect.y() + y),
186 row_bytes);
187 }
188 } else if (amount.x() != 0) {
189 // Horizontal-only scroll. We can do it in either top-to-bottom or bottom-
190 // to-top, but have to be careful about the order for copying each row.
191 // Fortunately, memmove already handles this for us.
192 for (int y = 0; y < dest_rect.height(); y++) {
193 memmove(bitmap.getAddr32(dest_rect.x(), dest_rect.y() + y),
194 bitmap.getAddr32(src_rect.x(), src_rect.y() + y),
195 row_bytes);
196 }
197 }
198 }
199
200 #endif
201
202 } // namespace gfx
OLDNEW
« no previous file with comments | « gfx/blit.h ('k') | gfx/blit_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698