| OLD | NEW | 
|    1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |    1 // Copyright (c) 2010 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 "webkit/glue/plugins/pepper_device_context_2d.h" |    5 #include "webkit/glue/plugins/pepper_device_context_2d.h" | 
|    6  |    6  | 
|    7 #include "base/logging.h" |    7 #include "base/logging.h" | 
|    8 #include "gfx/point.h" |    8 #include "gfx/point.h" | 
|    9 #include "gfx/rect.h" |    9 #include "gfx/rect.h" | 
|   10 #include "skia/ext/platform_canvas.h" |   10 #include "skia/ext/platform_canvas.h" | 
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   63   if (!module) |   63   if (!module) | 
|   64     return NULL; |   64     return NULL; | 
|   65  |   65  | 
|   66   scoped_refptr<DeviceContext2D> context(new DeviceContext2D(module)); |   66   scoped_refptr<DeviceContext2D> context(new DeviceContext2D(module)); | 
|   67   if (!context->Init(width, height, is_always_opaque)) |   67   if (!context->Init(width, height, is_always_opaque)) | 
|   68     return NULL; |   68     return NULL; | 
|   69   context->AddRef();  // AddRef for the caller. |   69   context->AddRef();  // AddRef for the caller. | 
|   70   return context->GetResource(); |   70   return context->GetResource(); | 
|   71 } |   71 } | 
|   72  |   72  | 
 |   73 bool Describe(PP_Resource device_context, | 
 |   74               int32_t* width, int32_t* height, bool* is_always_opaque) { | 
 |   75   scoped_refptr<DeviceContext2D> context( | 
 |   76       ResourceTracker::Get()->GetAsDeviceContext2D(device_context)); | 
 |   77   if (!context.get()) | 
 |   78     return false; | 
 |   79   return context->Describe(width, height, is_always_opaque); | 
 |   80 } | 
 |   81  | 
|   73 bool PaintImageData(PP_Resource device_context, |   82 bool PaintImageData(PP_Resource device_context, | 
|   74                     PP_Resource image, |   83                     PP_Resource image, | 
|   75                     int32_t x, int32_t y, |   84                     int32_t x, int32_t y, | 
|   76                     const PP_Rect* src_rect) { |   85                     const PP_Rect* src_rect) { | 
|   77   scoped_refptr<DeviceContext2D> context( |   86   scoped_refptr<DeviceContext2D> context( | 
|   78       ResourceTracker::Get()->GetAsDeviceContext2D(device_context)); |   87       ResourceTracker::Get()->GetAsDeviceContext2D(device_context)); | 
|   79   if (!context.get()) |   88   if (!context.get()) | 
|   80     return false; |   89     return false; | 
|   81   return context->PaintImageData(image, x, y, src_rect); |   90   return context->PaintImageData(image, x, y, src_rect); | 
|   82 } |   91 } | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
|  102 bool Flush(PP_Resource device_context, |  111 bool Flush(PP_Resource device_context, | 
|  103            PPB_DeviceContext2D_FlushCallback callback, |  112            PPB_DeviceContext2D_FlushCallback callback, | 
|  104            void* callback_data) { |  113            void* callback_data) { | 
|  105   scoped_refptr<DeviceContext2D> context( |  114   scoped_refptr<DeviceContext2D> context( | 
|  106       ResourceTracker::Get()->GetAsDeviceContext2D(device_context)); |  115       ResourceTracker::Get()->GetAsDeviceContext2D(device_context)); | 
|  107   if (!context.get()) |  116   if (!context.get()) | 
|  108     return false; |  117     return false; | 
|  109   return context->Flush(callback, callback_data); |  118   return context->Flush(callback, callback_data); | 
|  110 } |  119 } | 
|  111  |  120  | 
 |  121 bool ReadImageData(PP_Resource device_context, | 
 |  122                    PP_Resource image, | 
 |  123                    int32_t x, int32_t y) { | 
 |  124   scoped_refptr<DeviceContext2D> context( | 
 |  125       ResourceTracker::Get()->GetAsDeviceContext2D(device_context)); | 
 |  126   if (!context.get()) | 
 |  127     return false; | 
 |  128   return context->ReadImageData(image, x, y); | 
 |  129 } | 
 |  130  | 
|  112 const PPB_DeviceContext2D ppb_devicecontext2d = { |  131 const PPB_DeviceContext2D ppb_devicecontext2d = { | 
|  113   &Create, |  132   &Create, | 
 |  133   &Describe, | 
|  114   &PaintImageData, |  134   &PaintImageData, | 
|  115   &Scroll, |  135   &Scroll, | 
|  116   &ReplaceContents, |  136   &ReplaceContents, | 
|  117   &Flush |  137   &Flush, | 
 |  138   &ReadImageData | 
|  118 }; |  139 }; | 
|  119  |  140  | 
|  120 }  // namespace |  141 }  // namespace | 
|  121  |  142  | 
|  122 struct DeviceContext2D::QueuedOperation { |  143 struct DeviceContext2D::QueuedOperation { | 
|  123   enum Type { |  144   enum Type { | 
|  124     PAINT, |  145     PAINT, | 
|  125     SCROLL, |  146     SCROLL, | 
|  126     REPLACE |  147     REPLACE | 
|  127   }; |  148   }; | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
|  154  |  175  | 
|  155 DeviceContext2D::~DeviceContext2D() { |  176 DeviceContext2D::~DeviceContext2D() { | 
|  156 } |  177 } | 
|  157  |  178  | 
|  158 // static |  179 // static | 
|  159 const PPB_DeviceContext2D* DeviceContext2D::GetInterface() { |  180 const PPB_DeviceContext2D* DeviceContext2D::GetInterface() { | 
|  160   return &ppb_devicecontext2d; |  181   return &ppb_devicecontext2d; | 
|  161 } |  182 } | 
|  162  |  183  | 
|  163 bool DeviceContext2D::Init(int width, int height, bool is_always_opaque) { |  184 bool DeviceContext2D::Init(int width, int height, bool is_always_opaque) { | 
 |  185   // The underlying ImageData will validate the dimensions. | 
|  164   image_data_ = new ImageData(module()); |  186   image_data_ = new ImageData(module()); | 
|  165   if (!image_data_->Init(PP_IMAGEDATAFORMAT_BGRA_PREMUL, width, height, true) || |  187   if (!image_data_->Init(PP_IMAGEDATAFORMAT_BGRA_PREMUL, width, height, true) || | 
|  166       !image_data_->Map()) { |  188       !image_data_->Map()) { | 
|  167     image_data_ = NULL; |  189     image_data_ = NULL; | 
|  168     return false; |  190     return false; | 
|  169   } |  191   } | 
|  170  |  192  | 
|  171   return true; |  193   return true; | 
|  172 } |  194 } | 
|  173  |  195  | 
 |  196 bool DeviceContext2D::Describe(int32_t* width, int32_t* height, | 
 |  197                                bool* is_always_opaque) { | 
 |  198   *width = image_data_->width(); | 
 |  199   *height = image_data_->height(); | 
 |  200   *is_always_opaque = false;  // TODO(brettw) implement this. | 
 |  201   return true; | 
 |  202 } | 
 |  203  | 
|  174 bool DeviceContext2D::PaintImageData(PP_Resource image, |  204 bool DeviceContext2D::PaintImageData(PP_Resource image, | 
|  175                                      int32_t x, int32_t y, |  205                                      int32_t x, int32_t y, | 
|  176                                      const PP_Rect* src_rect) { |  206                                      const PP_Rect* src_rect) { | 
|  177   scoped_refptr<ImageData> image_resource( |  207   scoped_refptr<ImageData> image_resource( | 
|  178       ResourceTracker::Get()->GetAsImageData(image)); |  208       ResourceTracker::Get()->GetAsImageData(image)); | 
|  179   if (!image_resource.get() || !image_resource->is_valid()) |  209   if (!image_resource.get()) | 
|  180     return false; |  210     return false; | 
|  181  |  211  | 
|  182   const SkBitmap& new_image_bitmap = image_resource->GetMappedBitmap(); |  | 
|  183  |  | 
|  184   QueuedOperation operation(QueuedOperation::PAINT); |  212   QueuedOperation operation(QueuedOperation::PAINT); | 
|  185   operation.paint_image = image_resource; |  213   operation.paint_image = image_resource; | 
|  186   if (!ValidateAndConvertRect(src_rect, new_image_bitmap.width(), |  214   if (!ValidateAndConvertRect(src_rect, image_resource->width(), | 
|  187                               new_image_bitmap.height(), |  215                               image_resource->height(), | 
|  188                               &operation.paint_src_rect)) |  216                               &operation.paint_src_rect)) | 
|  189     return false; |  217     return false; | 
|  190  |  218  | 
|  191   // Validate the bitmap position using the previously-validated rect. |  219   // Validate the bitmap position using the previously-validated rect, there | 
|  192   if (x < 0 || |  220   // should be no painted area outside of the image. | 
|  193       static_cast<int64>(x) + |  221   int64 x64 = static_cast<int64>(x), y64 = static_cast<int64>(y); | 
|  194       static_cast<int64>(operation.paint_src_rect.right()) > |  222   if (x64 + static_cast<int64>(operation.paint_src_rect.x()) < 0 || | 
 |  223       x64 + static_cast<int64>(operation.paint_src_rect.right()) > | 
|  195       image_data_->width()) |  224       image_data_->width()) | 
|  196     return false; |  225     return false; | 
|  197   if (y < 0 || |  226   if (y64 + static_cast<int64>(operation.paint_src_rect.y()) < 0 || | 
|  198       static_cast<int64>(y) + |  227       y64 + static_cast<int64>(operation.paint_src_rect.bottom()) > | 
|  199       static_cast<int64>(operation.paint_src_rect.bottom()) > |  | 
|  200       image_data_->height()) |  228       image_data_->height()) | 
|  201     return false; |  229     return false; | 
|  202   operation.paint_x = x; |  230   operation.paint_x = x; | 
|  203   operation.paint_y = y; |  231   operation.paint_y = y; | 
|  204  |  232  | 
|  205   queued_operations_.push_back(operation); |  233   queued_operations_.push_back(operation); | 
|  206   return true; |  234   return true; | 
|  207 } |  235 } | 
|  208  |  236  | 
|  209 bool DeviceContext2D::Scroll(const PP_Rect* clip_rect, |  237 bool DeviceContext2D::Scroll(const PP_Rect* clip_rect, | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
|  224   operation.scroll_dx = dx; |  252   operation.scroll_dx = dx; | 
|  225   operation.scroll_dy = dy; |  253   operation.scroll_dy = dy; | 
|  226  |  254  | 
|  227   queued_operations_.push_back(operation); |  255   queued_operations_.push_back(operation); | 
|  228   return false; |  256   return false; | 
|  229 } |  257 } | 
|  230  |  258  | 
|  231 bool DeviceContext2D::ReplaceContents(PP_Resource image) { |  259 bool DeviceContext2D::ReplaceContents(PP_Resource image) { | 
|  232   scoped_refptr<ImageData> image_resource( |  260   scoped_refptr<ImageData> image_resource( | 
|  233       ResourceTracker::Get()->GetAsImageData(image)); |  261       ResourceTracker::Get()->GetAsImageData(image)); | 
|  234   if (!image_resource.get() || !image_resource->is_valid()) |  262   if (!image_resource.get()) | 
 |  263     return false; | 
 |  264   if (image_resource->format() != PP_IMAGEDATAFORMAT_BGRA_PREMUL) | 
|  235     return false; |  265     return false; | 
|  236  |  266  | 
|  237   if (image_resource->width() != image_data_->width() || |  267   if (image_resource->width() != image_data_->width() || | 
|  238       image_resource->height() != image_data_->height()) |  268       image_resource->height() != image_data_->height()) | 
|  239     return false; |  269     return false; | 
|  240  |  270  | 
|  241   QueuedOperation operation(QueuedOperation::REPLACE); |  271   QueuedOperation operation(QueuedOperation::REPLACE); | 
|  242   operation.replace_image = new ImageData(image_resource->module()); |  272   operation.replace_image = image_resource; | 
|  243   queued_operations_.push_back(operation); |  273   queued_operations_.push_back(operation); | 
|  244  |  274  | 
|  245   // Swap the input image data with the new one we just made in the |  275   return true; | 
|  246   // QueuedOperation. This way the plugin still gets to manage the reference |  | 
|  247   // count of the old object without having memory released out from under it. |  | 
|  248   // But it ensures that after this, if the plugin does try to use the image |  | 
|  249   // it gave us, those operations will fail. |  | 
|  250   operation.replace_image->Swap(image_resource.get()); |  | 
|  251  |  | 
|  252   return false; |  | 
|  253 } |  276 } | 
|  254  |  277  | 
|  255 bool DeviceContext2D::Flush(PPB_DeviceContext2D_FlushCallback callback, |  278 bool DeviceContext2D::Flush(PPB_DeviceContext2D_FlushCallback callback, | 
|  256                             void* callback_data) { |  279                             void* callback_data) { | 
|  257   for (size_t i = 0; i < queued_operations_.size(); i++) { |  280   for (size_t i = 0; i < queued_operations_.size(); i++) { | 
|  258     QueuedOperation& operation = queued_operations_[i]; |  281     QueuedOperation& operation = queued_operations_[i]; | 
|  259     switch (operation.type) { |  282     switch (operation.type) { | 
|  260       case QueuedOperation::PAINT: |  283       case QueuedOperation::PAINT: | 
|  261         ExecutePaintImageData(operation.paint_image.get(), |  284         ExecutePaintImageData(operation.paint_image.get(), | 
|  262                               operation.paint_x, operation.paint_y, |  285                               operation.paint_x, operation.paint_y, | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
|  286   // Save the callback to execute later. See |unpainted_flush_callbacks_| in |  309   // Save the callback to execute later. See |unpainted_flush_callbacks_| in | 
|  287   // the header file. |  310   // the header file. | 
|  288   if (callback) { |  311   if (callback) { | 
|  289     unpainted_flush_callbacks_.push_back( |  312     unpainted_flush_callbacks_.push_back( | 
|  290         FlushCallbackData(callback, id, context, user_data)); |  313         FlushCallbackData(callback, id, context, user_data)); | 
|  291   } |  314   } | 
|  292 */ |  315 */ | 
|  293   return true; |  316   return true; | 
|  294 } |  317 } | 
|  295  |  318  | 
 |  319 bool DeviceContext2D::ReadImageData(PP_Resource image, int32_t x, int32_t y) { | 
 |  320   // Get and validate the image object to paint into. | 
 |  321   scoped_refptr<ImageData> image_resource( | 
 |  322       ResourceTracker::Get()->GetAsImageData(image)); | 
 |  323   if (!image_resource.get()) | 
 |  324     return false; | 
 |  325   if (image_resource->format() != PP_IMAGEDATAFORMAT_BGRA_PREMUL) | 
 |  326     return false;  // Must be in the right format. | 
 |  327  | 
 |  328   // Validate the bitmap position. | 
 |  329   if (x < 0 || | 
 |  330       static_cast<int64>(x) + static_cast<int64>(image_resource->width()) > | 
 |  331       image_data_->width()) | 
 |  332     return false; | 
 |  333   if (y < 0 || | 
 |  334       static_cast<int64>(y) + static_cast<int64>(image_resource->height()) > | 
 |  335       image_data_->height()) | 
 |  336     return false; | 
 |  337  | 
 |  338   ImageDataAutoMapper auto_mapper(image_resource.get()); | 
 |  339   if (!auto_mapper.is_valid()) | 
 |  340     return false; | 
 |  341   skia::PlatformCanvas* dest_canvas = image_resource->mapped_canvas(); | 
 |  342  | 
 |  343   SkIRect src_irect = { x, y, | 
 |  344                         x + image_resource->width(), | 
 |  345                         y + image_resource->height() }; | 
 |  346   SkRect dest_rect = { SkIntToScalar(0), | 
 |  347                        SkIntToScalar(0), | 
 |  348                        SkIntToScalar(image_resource->width()), | 
 |  349                        SkIntToScalar(image_resource->height()) }; | 
 |  350  | 
 |  351   // We want to replace the contents of the bitmap rather than blend. | 
 |  352   SkPaint paint; | 
 |  353   paint.setXfermodeMode(SkXfermode::kSrc_Mode); | 
 |  354   dest_canvas->drawBitmapRect(*image_data_->GetMappedBitmap(), | 
 |  355                               &src_irect, dest_rect, &paint); | 
 |  356   return true; | 
 |  357 } | 
 |  358  | 
|  296 void DeviceContext2D::Paint(WebKit::WebCanvas* canvas, |  359 void DeviceContext2D::Paint(WebKit::WebCanvas* canvas, | 
|  297                             const gfx::Rect& plugin_rect, |  360                             const gfx::Rect& plugin_rect, | 
|  298                             const gfx::Rect& paint_rect) { |  361                             const gfx::Rect& paint_rect) { | 
|  299   // We're guaranteed to have a mapped canvas since we mapped it in Init(). |  362   // We're guaranteed to have a mapped canvas since we mapped it in Init(). | 
|  300   const SkBitmap& backing_bitmap = image_data_->GetMappedBitmap(); |  363   const SkBitmap& backing_bitmap = *image_data_->GetMappedBitmap(); | 
|  301  |  364  | 
|  302 #if defined(OS_MACOSX) |  365 #if defined(OS_MACOSX) | 
|  303   SkAutoLockPixels lock(backing_bitmap); |  366   SkAutoLockPixels lock(backing_bitmap); | 
|  304  |  367  | 
|  305   scoped_cftyperef<CGDataProviderRef> data_provider( |  368   scoped_cftyperef<CGDataProviderRef> data_provider( | 
|  306       CGDataProviderCreateWithData( |  369       CGDataProviderCreateWithData( | 
|  307           NULL, backing_bitmap.getAddr32(0, 0), |  370           NULL, backing_bitmap.getAddr32(0, 0), | 
|  308           backing_bitmap.rowBytes() * backing_bitmap.height(), NULL)); |  371           backing_bitmap.rowBytes() * backing_bitmap.height(), NULL)); | 
|  309   scoped_cftyperef<CGImageRef> image( |  372   scoped_cftyperef<CGImageRef> image( | 
|  310       CGImageCreate( |  373       CGImageCreate( | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
|  330   CGContextDrawImage(canvas, bounds, image); |  393   CGContextDrawImage(canvas, bounds, image); | 
|  331   CGContextRestoreGState(canvas); |  394   CGContextRestoreGState(canvas); | 
|  332 #else |  395 #else | 
|  333   gfx::Point origin(plugin_rect.origin().x(), plugin_rect.origin().y()); |  396   gfx::Point origin(plugin_rect.origin().x(), plugin_rect.origin().y()); | 
|  334   canvas->drawBitmap(backing_bitmap, |  397   canvas->drawBitmap(backing_bitmap, | 
|  335                      SkIntToScalar(plugin_rect.origin().x()), |  398                      SkIntToScalar(plugin_rect.origin().x()), | 
|  336                      SkIntToScalar(plugin_rect.origin().y())); |  399                      SkIntToScalar(plugin_rect.origin().y())); | 
|  337 #endif |  400 #endif | 
|  338 } |  401 } | 
|  339  |  402  | 
|  340  |  403 void DeviceContext2D::ExecutePaintImageData(ImageData* image, | 
|  341 void DeviceContext2D::ExecutePaintImageData(const ImageData* image, |  | 
|  342                                             int x, int y, |  404                                             int x, int y, | 
|  343                                             const gfx::Rect& src_rect) { |  405                                             const gfx::Rect& src_rect) { | 
|  344   // Portion within the source image to cut out. |  406   // Portion within the source image to cut out. | 
|  345   SkIRect src_irect = { src_rect.x(), src_rect.y(), |  407   SkIRect src_irect = { src_rect.x(), src_rect.y(), | 
|  346                         src_rect.right(), src_rect.bottom() }; |  408                         src_rect.right(), src_rect.bottom() }; | 
|  347  |  409  | 
|  348   // Location within the backing store to copy to. |  410   // Location within the backing store to copy to. | 
|  349   SkRect dest_rect = { SkIntToScalar(x + src_rect.x()), |  411   SkRect dest_rect = { SkIntToScalar(x + src_rect.x()), | 
|  350                        SkIntToScalar(y + src_rect.y()), |  412                        SkIntToScalar(y + src_rect.y()), | 
|  351                        SkIntToScalar(x + src_rect.right()), |  413                        SkIntToScalar(x + src_rect.right()), | 
|  352                        SkIntToScalar(y + src_rect.bottom()) }; |  414                        SkIntToScalar(y + src_rect.bottom()) }; | 
|  353  |  415  | 
|  354   // We're guaranteed to have a mapped canvas since we mapped it in Init(). |  416   // We're guaranteed to have a mapped canvas since we mapped it in Init(). | 
|  355   skia::PlatformCanvas* backing_canvas = image_data_->mapped_canvas(); |  417   skia::PlatformCanvas* backing_canvas = image_data_->mapped_canvas(); | 
|  356  |  418  | 
 |  419   // Ensure the source image is mapped to read from it. | 
 |  420   ImageDataAutoMapper auto_mapper(image); | 
 |  421   if (!auto_mapper.is_valid()) | 
 |  422     return; | 
 |  423  | 
|  357   // We want to replace the contents of the bitmap rather than blend. |  424   // We want to replace the contents of the bitmap rather than blend. | 
|  358   SkPaint paint; |  425   SkPaint paint; | 
|  359   paint.setXfermodeMode(SkXfermode::kSrc_Mode); |  426   paint.setXfermodeMode(SkXfermode::kSrc_Mode); | 
|  360   backing_canvas->drawBitmapRect(image->GetMappedBitmap(), |  427   backing_canvas->drawBitmapRect(*image->GetMappedBitmap(), | 
|  361                                  &src_irect, dest_rect, &paint); |  428                                  &src_irect, dest_rect, &paint); | 
|  362 } |  429 } | 
|  363  |  430  | 
|  364 void DeviceContext2D::ExecuteScroll(const gfx::Rect& clip, int dx, int dy) { |  431 void DeviceContext2D::ExecuteScroll(const gfx::Rect& clip, int dx, int dy) { | 
|  365   // FIXME(brettw) |  432   // FIXME(brettw) | 
|  366 } |  433 } | 
|  367  |  434  | 
|  368 void DeviceContext2D::ExecuteReplaceContents(ImageData* image) { |  435 void DeviceContext2D::ExecuteReplaceContents(ImageData* image) { | 
|  369   image_data_->Swap(image); |  436   image_data_->Swap(image); | 
|  370 } |  437 } | 
|  371  |  438  | 
|  372 }  // namespace pepper |  439 }  // namespace pepper | 
| OLD | NEW |