Index: content/renderer/render_widget.cc |
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc |
index bbc4eccc3adcab50a70ab255b7c9d83ab21e32e5..99b3731082e9003987ed98ecaff36bf65388ec56 100644 |
--- a/content/renderer/render_widget.cc |
+++ b/content/renderer/render_widget.cc |
@@ -24,6 +24,7 @@ |
#include "ipc/ipc_sync_message.h" |
#include "skia/ext/platform_canvas.h" |
#include "third_party/skia/include/core/SkShader.h" |
+#include "third_party/skia/include/effects/SkTableColorFilter.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPoint.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupMenu.h" |
@@ -98,7 +99,8 @@ RenderWidget::RenderWidget(WebKit::WebPopupType popup_type) |
is_accelerated_compositing_active_(false), |
animation_update_pending_(false), |
animation_task_posted_(false), |
- invalidation_task_posted_(false) { |
+ invalidation_task_posted_(false), |
+ invert_(false) { |
RenderProcess::current()->AddRefProcess(); |
DCHECK(RenderThread::Get()); |
has_disable_gpu_vsync_switch_ = CommandLine::ForCurrentProcess()->HasSwitch( |
@@ -217,6 +219,7 @@ bool RenderWidget::OnMessageReceived(const IPC::Message& message) { |
IPC_MESSAGE_HANDLER(ViewMsg_Repaint, OnMsgRepaint) |
IPC_MESSAGE_HANDLER(ViewMsg_SetTextDirection, OnSetTextDirection) |
IPC_MESSAGE_HANDLER(ViewMsg_Move_ACK, OnRequestMoveAck) |
+ IPC_MESSAGE_HANDLER(ViewMsg_InvertWebContent, OnInvertWebContent) |
IPC_MESSAGE_UNHANDLED(handled = false) |
IPC_END_MESSAGE_MAP() |
return handled; |
@@ -587,6 +590,16 @@ void RenderWidget::PaintRect(const gfx::Rect& rect, |
canvas->translate(static_cast<SkScalar>(-canvas_origin.x()), |
static_cast<SkScalar>(-canvas_origin.y())); |
+ if (invert_) { |
+ // Draw everything to a temporary bitmap and then apply an |
+ // inverting color map to the result. This is balanced by an extra |
+ // call to canvas->restore(), below. |
+ DCHECK(invert_paint_.get()); |
+ SkRect bounds; |
+ bounds.set(rect.x(), rect.y(), rect.right(), rect.bottom()); |
+ canvas->saveLayer(&bounds, invert_paint_.get()); |
+ } |
+ |
// If there is a custom background, tile it. |
if (!background_.empty()) { |
SkPaint paint; |
@@ -647,6 +660,9 @@ void RenderWidget::PaintRect(const gfx::Rect& rect, |
skia::GetTopDevice(*canvas)->accessBitmap(false); |
} |
+ if (invert_) |
+ canvas->restore(); |
+ |
PaintDebugBorder(rect, canvas); |
canvas->restore(); |
} |
@@ -1389,6 +1405,37 @@ void RenderWidget::OnSetTextDirection(WebTextDirection direction) { |
webwidget_->setTextDirection(direction); |
} |
+void RenderWidget::OnInvertWebContent(bool invert) { |
+ if (invert_ == invert) |
+ return; |
+ |
+ invert_ = invert; |
+ |
+ if (invert_ && !invert_paint_.get()) { |
+ // Gamma-aware color inversion: each source pixel value x is normally |
+ // displayed on a computer monitor with a gamma correction x^gamma, |
+ // where gamma is typically in the range 1.8...2.2. By approximating |
+ // gamma as exactly 2, the formula to invert one value is sqrt(1 - x^2). |
+ uint8_t table[256]; |
+ for (unsigned int i = 0; i < 256; i++) { |
+ double value = i / 255.0; |
+ value = sqrt(1 - (value * value)); |
+ table[i] = static_cast<uint8_t>(255 * value); |
+ } |
+ |
+ // Create a Skia Paint with this inverting color map. |
+ invert_paint_.reset(new SkPaint()); |
+ invert_paint_->setStyle(SkPaint::kFill_Style); |
+ invert_paint_->setColor(SK_ColorBLACK); |
+ SkColorFilter* filter = SkTableColorFilter::CreateARGB( |
+ NULL, table, table, table); |
+ invert_paint_->setColorFilter(filter); |
+ filter->unref(); |
+ } |
+ |
+ OnMsgRepaint(size_); |
+} |
+ |
webkit::ppapi::PluginInstance* RenderWidget::GetBitmapForOptimizedPluginPaint( |
const gfx::Rect& paint_bounds, |
TransportDIB** dib, |