| Index: webkit/glue/plugins/pepper_device_context_2d.cc
|
| ===================================================================
|
| --- webkit/glue/plugins/pepper_device_context_2d.cc (revision 48097)
|
| +++ webkit/glue/plugins/pepper_device_context_2d.cc (working copy)
|
| @@ -70,6 +70,15 @@
|
| return context->GetResource();
|
| }
|
|
|
| +bool Describe(PP_Resource device_context,
|
| + int32_t* width, int32_t* height, bool* is_always_opaque) {
|
| + scoped_refptr<DeviceContext2D> context(
|
| + ResourceTracker::Get()->GetAsDeviceContext2D(device_context));
|
| + if (!context.get())
|
| + return false;
|
| + return context->Describe(width, height, is_always_opaque);
|
| +}
|
| +
|
| bool PaintImageData(PP_Resource device_context,
|
| PP_Resource image,
|
| int32_t x, int32_t y,
|
| @@ -109,12 +118,24 @@
|
| return context->Flush(callback, callback_data);
|
| }
|
|
|
| +bool ReadImageData(PP_Resource device_context,
|
| + PP_Resource image,
|
| + int32_t x, int32_t y) {
|
| + scoped_refptr<DeviceContext2D> context(
|
| + ResourceTracker::Get()->GetAsDeviceContext2D(device_context));
|
| + if (!context.get())
|
| + return false;
|
| + return context->ReadImageData(image, x, y);
|
| +}
|
| +
|
| const PPB_DeviceContext2D ppb_devicecontext2d = {
|
| &Create,
|
| + &Describe,
|
| &PaintImageData,
|
| &Scroll,
|
| &ReplaceContents,
|
| - &Flush
|
| + &Flush,
|
| + &ReadImageData
|
| };
|
|
|
| } // namespace
|
| @@ -161,6 +182,7 @@
|
| }
|
|
|
| bool DeviceContext2D::Init(int width, int height, bool is_always_opaque) {
|
| + // The underlying ImageData will validate the dimensions.
|
| image_data_ = new ImageData(module());
|
| if (!image_data_->Init(PP_IMAGEDATAFORMAT_BGRA_PREMUL, width, height, true) ||
|
| !image_data_->Map()) {
|
| @@ -171,32 +193,38 @@
|
| return true;
|
| }
|
|
|
| +bool DeviceContext2D::Describe(int32_t* width, int32_t* height,
|
| + bool* is_always_opaque) {
|
| + *width = image_data_->width();
|
| + *height = image_data_->height();
|
| + *is_always_opaque = false; // TODO(brettw) implement this.
|
| + return true;
|
| +}
|
| +
|
| bool DeviceContext2D::PaintImageData(PP_Resource image,
|
| int32_t x, int32_t y,
|
| const PP_Rect* src_rect) {
|
| scoped_refptr<ImageData> image_resource(
|
| ResourceTracker::Get()->GetAsImageData(image));
|
| - if (!image_resource.get() || !image_resource->is_valid())
|
| + if (!image_resource.get())
|
| return false;
|
|
|
| - const SkBitmap& new_image_bitmap = image_resource->GetMappedBitmap();
|
| -
|
| QueuedOperation operation(QueuedOperation::PAINT);
|
| operation.paint_image = image_resource;
|
| - if (!ValidateAndConvertRect(src_rect, new_image_bitmap.width(),
|
| - new_image_bitmap.height(),
|
| + if (!ValidateAndConvertRect(src_rect, image_resource->width(),
|
| + image_resource->height(),
|
| &operation.paint_src_rect))
|
| return false;
|
|
|
| - // Validate the bitmap position using the previously-validated rect.
|
| - if (x < 0 ||
|
| - static_cast<int64>(x) +
|
| - static_cast<int64>(operation.paint_src_rect.right()) >
|
| + // Validate the bitmap position using the previously-validated rect, there
|
| + // should be no painted area outside of the image.
|
| + int64 x64 = static_cast<int64>(x), y64 = static_cast<int64>(y);
|
| + if (x64 + static_cast<int64>(operation.paint_src_rect.x()) < 0 ||
|
| + x64 + static_cast<int64>(operation.paint_src_rect.right()) >
|
| image_data_->width())
|
| return false;
|
| - if (y < 0 ||
|
| - static_cast<int64>(y) +
|
| - static_cast<int64>(operation.paint_src_rect.bottom()) >
|
| + if (y64 + static_cast<int64>(operation.paint_src_rect.y()) < 0 ||
|
| + y64 + static_cast<int64>(operation.paint_src_rect.bottom()) >
|
| image_data_->height())
|
| return false;
|
| operation.paint_x = x;
|
| @@ -231,25 +259,20 @@
|
| bool DeviceContext2D::ReplaceContents(PP_Resource image) {
|
| scoped_refptr<ImageData> image_resource(
|
| ResourceTracker::Get()->GetAsImageData(image));
|
| - if (!image_resource.get() || !image_resource->is_valid())
|
| + if (!image_resource.get())
|
| return false;
|
| + if (image_resource->format() != PP_IMAGEDATAFORMAT_BGRA_PREMUL)
|
| + return false;
|
|
|
| if (image_resource->width() != image_data_->width() ||
|
| image_resource->height() != image_data_->height())
|
| return false;
|
|
|
| QueuedOperation operation(QueuedOperation::REPLACE);
|
| - operation.replace_image = new ImageData(image_resource->module());
|
| + operation.replace_image = image_resource;
|
| queued_operations_.push_back(operation);
|
|
|
| - // Swap the input image data with the new one we just made in the
|
| - // QueuedOperation. This way the plugin still gets to manage the reference
|
| - // count of the old object without having memory released out from under it.
|
| - // But it ensures that after this, if the plugin does try to use the image
|
| - // it gave us, those operations will fail.
|
| - operation.replace_image->Swap(image_resource.get());
|
| -
|
| - return false;
|
| + return true;
|
| }
|
|
|
| bool DeviceContext2D::Flush(PPB_DeviceContext2D_FlushCallback callback,
|
| @@ -293,11 +316,51 @@
|
| return true;
|
| }
|
|
|
| +bool DeviceContext2D::ReadImageData(PP_Resource image, int32_t x, int32_t y) {
|
| + // Get and validate the image object to paint into.
|
| + scoped_refptr<ImageData> image_resource(
|
| + ResourceTracker::Get()->GetAsImageData(image));
|
| + if (!image_resource.get())
|
| + return false;
|
| + if (image_resource->format() != PP_IMAGEDATAFORMAT_BGRA_PREMUL)
|
| + return false; // Must be in the right format.
|
| +
|
| + // Validate the bitmap position.
|
| + if (x < 0 ||
|
| + static_cast<int64>(x) + static_cast<int64>(image_resource->width()) >
|
| + image_data_->width())
|
| + return false;
|
| + if (y < 0 ||
|
| + static_cast<int64>(y) + static_cast<int64>(image_resource->height()) >
|
| + image_data_->height())
|
| + return false;
|
| +
|
| + ImageDataAutoMapper auto_mapper(image_resource.get());
|
| + if (!auto_mapper.is_valid())
|
| + return false;
|
| + skia::PlatformCanvas* dest_canvas = image_resource->mapped_canvas();
|
| +
|
| + SkIRect src_irect = { x, y,
|
| + x + image_resource->width(),
|
| + y + image_resource->height() };
|
| + SkRect dest_rect = { SkIntToScalar(0),
|
| + SkIntToScalar(0),
|
| + SkIntToScalar(image_resource->width()),
|
| + SkIntToScalar(image_resource->height()) };
|
| +
|
| + // We want to replace the contents of the bitmap rather than blend.
|
| + SkPaint paint;
|
| + paint.setXfermodeMode(SkXfermode::kSrc_Mode);
|
| + dest_canvas->drawBitmapRect(*image_data_->GetMappedBitmap(),
|
| + &src_irect, dest_rect, &paint);
|
| + return true;
|
| +}
|
| +
|
| void DeviceContext2D::Paint(WebKit::WebCanvas* canvas,
|
| const gfx::Rect& plugin_rect,
|
| const gfx::Rect& paint_rect) {
|
| // We're guaranteed to have a mapped canvas since we mapped it in Init().
|
| - const SkBitmap& backing_bitmap = image_data_->GetMappedBitmap();
|
| + const SkBitmap& backing_bitmap = *image_data_->GetMappedBitmap();
|
|
|
| #if defined(OS_MACOSX)
|
| SkAutoLockPixels lock(backing_bitmap);
|
| @@ -337,8 +400,7 @@
|
| #endif
|
| }
|
|
|
| -
|
| -void DeviceContext2D::ExecutePaintImageData(const ImageData* image,
|
| +void DeviceContext2D::ExecutePaintImageData(ImageData* image,
|
| int x, int y,
|
| const gfx::Rect& src_rect) {
|
| // Portion within the source image to cut out.
|
| @@ -354,10 +416,15 @@
|
| // We're guaranteed to have a mapped canvas since we mapped it in Init().
|
| skia::PlatformCanvas* backing_canvas = image_data_->mapped_canvas();
|
|
|
| + // Ensure the source image is mapped to read from it.
|
| + ImageDataAutoMapper auto_mapper(image);
|
| + if (!auto_mapper.is_valid())
|
| + return;
|
| +
|
| // We want to replace the contents of the bitmap rather than blend.
|
| SkPaint paint;
|
| paint.setXfermodeMode(SkXfermode::kSrc_Mode);
|
| - backing_canvas->drawBitmapRect(image->GetMappedBitmap(),
|
| + backing_canvas->drawBitmapRect(*image->GetMappedBitmap(),
|
| &src_irect, dest_rect, &paint);
|
| }
|
|
|
|
|