Index: content/renderer/webplugin_delegate_proxy.cc |
=================================================================== |
--- content/renderer/webplugin_delegate_proxy.cc (revision 166499) |
+++ content/renderer/webplugin_delegate_proxy.cc (working copy) |
@@ -48,6 +48,7 @@ |
#include "ui/gfx/canvas.h" |
#include "ui/gfx/native_widget_types.h" |
#include "ui/gfx/size.h" |
+#include "ui/gfx/skia_util.h" |
#include "webkit/glue/webkit_glue.h" |
#include "webkit/plugins/npapi/webplugin.h" |
#include "webkit/plugins/plugin_constants.h" |
@@ -211,7 +212,6 @@ |
npobject_(NULL), |
sad_plugin_(NULL), |
invalidate_pending_(false), |
- transparent_(false), |
front_buffer_index_(0), |
page_url_(render_view_->webview()->mainFrame()->document().url()) { |
} |
@@ -279,33 +279,6 @@ |
MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
} |
-// Returns true if the given Silverlight 'background' value corresponds to |
-// one that should make the plugin transparent. See: |
-// http://msdn.microsoft.com/en-us/library/cc838148(VS.95).aspx |
-// for possible values. |
-static bool SilverlightColorIsTransparent(const std::string& color) { |
- if (StartsWithASCII(color, "#", false)) { |
- // If it's #ARGB or #AARRGGBB check the alpha; if not it's an RGB form and |
- // it's not transparent. |
- if ((color.length() == 5 && !StartsWithASCII(color, "#F", false)) || |
- (color.length() == 9 && !StartsWithASCII(color, "#FF", false))) |
- return true; |
- } else if (StartsWithASCII(color, "sc#", false)) { |
- // It's either sc#A,R,G,B or sc#R,G,B; if the former, check the alpha. |
- if (color.length() < 4) |
- return false; |
- std::string value_string = color.substr(3, std::string::npos); |
- std::vector<std::string> components; |
- base::SplitString(value_string, ',', &components); |
- if (components.size() == 4 && !StartsWithASCII(components[0], "1", false)) |
- return true; |
- } else if (LowerCaseEqualsASCII(color, "transparent")) { |
- return true; |
- } |
- // Anything else is a named, opaque color or an RGB form with no alpha. |
- return false; |
-} |
- |
bool WebPluginDelegateProxy::Initialize( |
const GURL& url, |
const std::vector<std::string>& arg_names, |
@@ -392,25 +365,12 @@ |
params.arg_names = arg_names; |
params.arg_values = arg_values; |
params.host_render_view_routing_id = render_view_->routing_id(); |
- |
- bool flash = LowerCaseEqualsASCII(mime_type_, kFlashPluginSwfMimeType); |
- bool silverlight = |
- StartsWithASCII(mime_type_, "application/x-silverlight", false); |
- for (size_t i = 0; i < arg_names.size(); ++i) { |
- if ((flash && LowerCaseEqualsASCII(arg_names[i], "wmode") && |
- LowerCaseEqualsASCII(arg_values[i], "transparent")) || |
- (silverlight && LowerCaseEqualsASCII(arg_names[i], "background") && |
- SilverlightColorIsTransparent(arg_values[i]))) { |
- transparent_ = true; |
- } |
- } |
params.load_manually = load_manually; |
plugin_ = plugin; |
result = false; |
- IPC::Message* msg = new PluginMsg_Init(instance_id_, params, &result); |
- Send(msg); |
+ Send(new PluginMsg_Init(instance_id_, params, &result)); |
if (!result) |
LOG(ERROR) << "PluginMsg_Init returned false"; |
@@ -580,8 +540,6 @@ |
param.windowless_buffer0 = TransportDIB::DefaultHandleValue(); |
param.windowless_buffer1 = TransportDIB::DefaultHandleValue(); |
param.windowless_buffer_index = back_buffer_index(); |
- param.background_buffer = TransportDIB::DefaultHandleValue(); |
- param.transparent = transparent_; |
#if defined(OS_POSIX) |
// If we're using POSIX mmap'd TransportDIBs, sending the handle across |
@@ -599,11 +557,6 @@ |
CopyTransportDIBHandleForMessage(transport_stores_[1].dib->handle(), |
¶m.windowless_buffer1, |
channel_host_->peer_pid()); |
- |
- if (background_store_.dib.get()) |
- CopyTransportDIBHandleForMessage(background_store_.dib->handle(), |
- ¶m.background_buffer, |
- channel_host_->peer_pid()); |
} |
IPC::Message* msg; |
@@ -645,14 +598,6 @@ |
{ |
bitmaps_changed = true; |
- bool needs_background_store = transparent_; |
-#if defined(OS_MACOSX) |
- // We don't support transparency under QuickDraw, and CoreGraphics |
- // preserves transparency information (and does the compositing itself) |
- // so plugins don't need access to the page background. |
- needs_background_store = false; |
-#endif |
- |
// Create a shared memory section that the plugin paints into |
// asynchronously. |
ResetWindowlessBitmaps(); |
@@ -660,10 +605,7 @@ |
if (!CreateSharedBitmap(&transport_stores_[0].dib, |
&transport_stores_[0].canvas) || |
!CreateSharedBitmap(&transport_stores_[1].dib, |
- &transport_stores_[1].canvas) || |
- (needs_background_store && |
- !CreateSharedBitmap(&background_store_.dib, |
- &background_store_.canvas))) { |
+ &transport_stores_[1].canvas)) { |
DCHECK(false); |
ResetWindowlessBitmaps(); |
return; |
@@ -678,11 +620,9 @@ |
void WebPluginDelegateProxy::ResetWindowlessBitmaps() { |
transport_stores_[0].dib.reset(); |
transport_stores_[1].dib.reset(); |
- background_store_.dib.reset(); |
transport_stores_[0].canvas.reset(); |
transport_stores_[1].canvas.reset(); |
- background_store_.canvas.reset(); |
transport_store_painted_ = gfx::Rect(); |
front_buffer_diff_ = gfx::Rect(); |
} |
@@ -762,40 +702,13 @@ |
if (!front_buffer_canvas()) |
return; |
- // We're using the native OS APIs from here on out. |
- if (!skia::SupportsPlatformPaint(canvas)) { |
- // TODO(alokp): Implement this path. |
- // This block will only get hit with --enable-accelerated-drawing flag. |
- // With accelerated canvas, we do not have a bitmap that can be provided |
- // to the plugin for compositing. We may have to implement a solution |
- // described in crbug.com/12586. |
- DLOG(WARNING) << "Could not paint plugin"; |
- return; |
- } |
- skia::ScopedPlatformPaint scoped_platform_paint(canvas); |
- gfx::NativeDrawingContext context = |
- scoped_platform_paint.GetPlatformSurface(); |
- |
gfx::Rect offset_rect = rect; |
offset_rect.Offset(-plugin_rect_.x(), -plugin_rect_.y()); |
- gfx::Rect canvas_rect = offset_rect; |
-#if defined(OS_MACOSX) |
- // The canvases are flipped relative to the context, so flip the rect too. |
- FlipRectVerticallyWithHeight(&canvas_rect, plugin_rect_.height()); |
-#endif |
- bool background_changed = false; |
- if (background_store_.canvas.get() && BackgroundChanged(context, rect)) { |
- background_changed = true; |
- BlitContextToCanvas(background_store_.canvas.get(), canvas_rect, |
- context, rect.origin()); |
- } |
- |
// transport_store_painted_ is really a bounding box, so in principle this |
// check could falsely indicate that we don't need to paint offset_rect, but |
// in practice it works fine. |
- if (background_changed || |
- !transport_store_painted_.Contains(offset_rect)) { |
+ if (!transport_store_painted_.Contains(offset_rect)) { |
Send(new PluginMsg_Paint(instance_id_, offset_rect)); |
// Since the plugin is not blocked on the renderer in this context, there is |
// a chance that it will begin repainting the back-buffer before we complete |
@@ -805,20 +718,15 @@ |
UpdateFrontBuffer(offset_rect, false); |
} |
-#if defined(OS_MACOSX) |
- // The canvases are flipped relative to the context, so flip the context's |
- // coordinate space so that the blit unflips the content. |
- CGContextSaveGState(context); |
- CGContextScaleCTM(context, 1, -1); |
- rect.set_y(-rect.bottom()); |
-#endif |
- BlitCanvasToContext(context, |
- rect, |
- front_buffer_canvas(), |
- offset_rect.origin()); |
-#if defined(OS_MACOSX) |
- CGContextRestoreGState(context); |
-#endif |
+ const SkBitmap& bitmap = |
+ front_buffer_canvas()->getDevice()->accessBitmap(false); |
+ SkPaint paint; |
+ paint.setXfermodeMode(SkXfermode::kSrcATop_Mode); |
+ SkIRect src_rect = gfx::RectToSkIRect(offset_rect); |
+ canvas->drawBitmapRect(bitmap, |
+ &src_rect, |
+ gfx::RectToSkRect(rect), |
+ &paint); |
if (invalidate_pending_) { |
// Only send the PaintAck message if this paint is in response to an |
@@ -829,157 +737,6 @@ |
} |
} |
-bool WebPluginDelegateProxy::BackgroundChanged( |
- gfx::NativeDrawingContext context, |
- const gfx::Rect& rect) { |
-#if defined(OS_ANDROID) |
- NOTIMPLEMENTED(); |
-#else |
-#if defined(OS_WIN) |
- HBITMAP hbitmap = static_cast<HBITMAP>(GetCurrentObject(context, OBJ_BITMAP)); |
- if (hbitmap == NULL) { |
- NOTREACHED(); |
- return true; |
- } |
- |
- BITMAP bitmap = { 0 }; |
- int result = GetObject(hbitmap, sizeof(bitmap), &bitmap); |
- if (!result) { |
- NOTREACHED(); |
- return true; |
- } |
- |
- XFORM xf; |
- if (!GetWorldTransform(context, &xf)) { |
- NOTREACHED(); |
- return true; |
- } |
- |
- // The damaged rect that we're given can be larger than the bitmap, so |
- // intersect their rects first. |
- gfx::Rect bitmap_rect(static_cast<int>(-xf.eDx), static_cast<int>(-xf.eDy), |
- bitmap.bmWidth, bitmap.bmHeight); |
- gfx::Rect check_rect = gfx::IntersectRects(rect, bitmap_rect); |
- int row_byte_size = check_rect.width() * (bitmap.bmBitsPixel / 8); |
- for (int y = check_rect.y(); y < check_rect.bottom(); y++) { |
- char* hdc_row_start = static_cast<char*>(bitmap.bmBits) + |
- (y + static_cast<int>(xf.eDy)) * bitmap.bmWidthBytes + |
- (check_rect.x() + static_cast<int>(xf.eDx)) * (bitmap.bmBitsPixel / 8); |
- |
- // getAddr32 doesn't use the translation units, so we have to subtract |
- // the plugin origin from the coordinates. |
- uint32_t* canvas_row_start = |
- background_store_.canvas->getDevice()->accessBitmap(true).getAddr32( |
- check_rect.x() - plugin_rect_.x(), y - plugin_rect_.y()); |
- if (memcmp(hdc_row_start, canvas_row_start, row_byte_size) != 0) |
- return true; |
- } |
-#else |
-#if defined(OS_MACOSX) |
- // If there is a translation on the content area context, we need to account |
- // for it; the context may be a subset of the full content area with a |
- // transform that makes the coordinates work out. |
- CGAffineTransform transform = CGContextGetCTM(context); |
- bool flipped = fabs(transform.d + 1) < 0.0001; |
- CGFloat context_offset_x = -transform.tx; |
- CGFloat context_offset_y = flipped ? transform.ty - |
- CGBitmapContextGetHeight(context) |
- : -transform.ty; |
- gfx::Rect full_content_rect(context_offset_x, context_offset_y, |
- CGBitmapContextGetWidth(context), |
- CGBitmapContextGetHeight(context)); |
-#else |
- cairo_surface_t* page_surface = cairo_get_target(context); |
- DCHECK_EQ(cairo_surface_get_type(page_surface), CAIRO_SURFACE_TYPE_IMAGE); |
- DCHECK_EQ(cairo_image_surface_get_format(page_surface), CAIRO_FORMAT_ARGB32); |
- |
- // Transform context coordinates into surface coordinates. |
- double page_x_double = 0; |
- double page_y_double = 0; |
- cairo_device_to_user(context, &page_x_double, &page_y_double); |
- gfx::Rect full_content_rect(static_cast<int>(page_x_double), |
- static_cast<int>(page_y_double), |
- cairo_image_surface_get_width(page_surface), |
- cairo_image_surface_get_height(page_surface)); |
-#endif |
- // According to comments in the Windows code, the damage rect that we're given |
- // may project outside the image, so intersect their rects. |
- gfx::Rect content_rect = gfx::IntersectRects(rect, full_content_rect); |
- |
-#if defined(OS_MACOSX) |
- const unsigned char* page_bytes = static_cast<const unsigned char*>( |
- CGBitmapContextGetData(context)); |
- int page_stride = CGBitmapContextGetBytesPerRow(context); |
- int page_start_x = content_rect.x() - context_offset_x; |
- int page_start_y = content_rect.y() - context_offset_y; |
- |
- skia::ScopedPlatformPaint scoped_platform_paint( |
- background_store_.canvas.get()); |
- CGContextRef bg_context = scoped_platform_paint.GetPlatformSurface(); |
- |
- DCHECK_EQ(CGBitmapContextGetBitsPerPixel(context), |
- CGBitmapContextGetBitsPerPixel(bg_context)); |
- const unsigned char* bg_bytes = static_cast<const unsigned char*>( |
- CGBitmapContextGetData(bg_context)); |
- int full_bg_width = CGBitmapContextGetWidth(bg_context); |
- int full_bg_height = CGBitmapContextGetHeight(bg_context); |
- int bg_stride = CGBitmapContextGetBytesPerRow(bg_context); |
- int bg_last_row = CGBitmapContextGetHeight(bg_context) - 1; |
- |
- int bytes_per_pixel = CGBitmapContextGetBitsPerPixel(context) / 8; |
-#else |
- cairo_surface_flush(page_surface); |
- const unsigned char* page_bytes = cairo_image_surface_get_data(page_surface); |
- int page_stride = cairo_image_surface_get_stride(page_surface); |
- int page_start_x = content_rect.x() - static_cast<int>(page_x_double); |
- int page_start_y = content_rect.y() - static_cast<int>(page_y_double); |
- |
- skia::ScopedPlatformPaint scoped_platform_paint( |
- background_store_.canvas.get()); |
- cairo_surface_t* bg_surface =cairo_get_target( |
- scoped_platform_paint.GetPlatformSurface()); |
- DCHECK_EQ(cairo_surface_get_type(bg_surface), CAIRO_SURFACE_TYPE_IMAGE); |
- DCHECK_EQ(cairo_image_surface_get_format(bg_surface), CAIRO_FORMAT_ARGB32); |
- cairo_surface_flush(bg_surface); |
- const unsigned char* bg_bytes = cairo_image_surface_get_data(bg_surface); |
- int full_bg_width = cairo_image_surface_get_width(bg_surface); |
- int full_bg_height = cairo_image_surface_get_height(bg_surface); |
- int bg_stride = cairo_image_surface_get_stride(bg_surface); |
- |
- int bytes_per_pixel = 4; // ARGB32 = 4 bytes per pixel. |
-#endif |
- |
- int damage_width = content_rect.width(); |
- int damage_height = content_rect.height(); |
- |
- int bg_start_x = rect.x() - plugin_rect_.x(); |
- int bg_start_y = rect.y() - plugin_rect_.y(); |
- // The damage rect is supposed to have been intersected with the plugin rect; |
- // double-check, since if it hasn't we'll walk off the end of the buffer. |
- DCHECK_LE(bg_start_x + damage_width, full_bg_width); |
- DCHECK_LE(bg_start_y + damage_height, full_bg_height); |
- |
- int bg_x_byte_offset = bg_start_x * bytes_per_pixel; |
- int page_x_byte_offset = page_start_x * bytes_per_pixel; |
- for (int row = 0; row < damage_height; ++row) { |
- int page_offset = page_stride * (page_start_y + row) + page_x_byte_offset; |
- int bg_y = bg_start_y + row; |
-#if defined(OS_MACOSX) |
- // The background buffer is upside down relative to the content. |
- bg_y = bg_last_row - bg_y; |
-#endif |
- int bg_offset = bg_stride * bg_y + bg_x_byte_offset; |
- if (memcmp(page_bytes + page_offset, |
- bg_bytes + bg_offset, |
- damage_width * bytes_per_pixel) != 0) |
- return true; |
- } |
-#endif |
-#endif // OS_ANDROID |
- |
- return false; |
-} |
- |
NPObject* WebPluginDelegateProxy::GetPluginScriptableObject() { |
if (npobject_) |
return WebBindings::retainObject(npobject_); |