Mike Reed -- can you have a look at the Skia stuff, specifically the
ARGB / ABGR discussion in these two files? I am not a graphics ninja,
and might have mistaken my terminology.
gears/canvas/canvas_rendering_element_ie.cc (the Draw method), and
third_party/skia/include/core/SkUserConfig.h

Noel, can you have a look at everything else?



Hello noel, reed,

I'd like you to do a code review.  Please execute
        g4 diff -c 10562599

or point your web browser to
        http://mondrian/10562599

to review the following code:

Change 10562599 by nigel...@nigeltao-srcwingears2 on 2009/03/21 15:09:02 
*pending*

        First cut of on-screen canvas rendering.
        
        The model is that a GearsCanvas remains an off-screen object, but it
        now can have a DOM element peer (provided that the GearsCanvas isn't
        in a worker thread) that can participate in the DOM tree, and knows
        how to render the GearsCanvas' contents (i.e. the backing SkBitmap).
        
        On IE, this uses an IHTMLPainter behavior and GDI+ to blit the
        SkBitmap directly. Compared to the 'indirect' method of rendering a
        GearsCanvas (i.e. calling encode() to create a PNG Blob to capture
        (via LocalServer) to point an <img>'s src to), this actually renders
        transparency properly on IE6.
        
        On Firefox, I am not aware of an equivalent mechanism to IHTMLPainter,
        and so the rendering peer is a (Firefox's native) <canvas> element,
        and the data is transferred from the GearsCanvas gc to the native
        canvas nc via nc.putImageData(gc.getImageData()). This is undoubtedly
        inefficient, but it is correct, and we can do something faster (but
        more complicated) later. Besides, Firefox already has a native canvas,
        and so the Gears canvas' on-screen rendering performance on FF is not
        as high a priority as the speed on IE (which has no native canvas).
        
        I've punted on measuring rendering performance, since a call to
        invalidateRenderingElement doesn't actually paint the pixels, it
        schedules a paint to happen some time in the future, and therefore
        measuring the clock time elapsed before and after an
        invalidateRenderingElement call won't capture the total time to
        draw the off-screen bitmap on-screen.
        
        In order to avoid a conversion from SkBitmap's packing order and
        GDI+'s packing order, Skia's packing was configured to be ARGB
        (instead of Skia's default ABGR) on Win32 Gears builds.
        
        This is very much pre-alpha quality (and has only been tested on
        IE/Win32, Firefox/Win32, and very briefly on Firefox/Linux). The
        API is also up for debate (e.g. should invalidation be automatic
        or explicit). Nonetheless, it works, so I'm putting this out as a
        first cut.
        
        R=noel,reed
        [email protected]
        DELTA=608  (570 added, 22 deleted, 16 changed)
        OCL=10562599

Affected files ...

... //depot/googleclient/gears/opensource/gears/Makefile#241 edit
... //depot/googleclient/gears/opensource/gears/base/common/js_runner.h#21 edit
... //depot/googleclient/gears/opensource/gears/base/common/js_runner_ff.cc#33 
edit
... //depot/googleclient/gears/opensource/gears/base/common/js_types.cc#53 edit
... //depot/googleclient/gears/opensource/gears/base/common/leak_counter.cc#16 
edit
... //depot/googleclient/gears/opensource/gears/base/common/leak_counter.h#15 
edit
... //depot/googleclient/gears/opensource/gears/canvas/canvas.cc#26 edit
... //depot/googleclient/gears/opensource/gears/canvas/canvas.h#21 edit
... 
//depot/googleclient/gears/opensource/gears/canvas/canvas_rendering_context_2d.cc#21
 edit
... 
//depot/googleclient/gears/opensource/gears/canvas/canvas_rendering_element_ie.cc#1
 add
... 
//depot/googleclient/gears/opensource/gears/canvas/canvas_rendering_element_ie.h#1
 add
... //depot/googleclient/gears/opensource/gears/test/manual/canvas.html#5 edit
... //depot/googleclient/gears/opensource/gears/tools/config.mk#105 edit
... //depot/googleclient/gears/opensource/third_party/skia/README.google#6 edit
... 
//depot/googleclient/gears/opensource/third_party/skia/include/core/SkUserConfig.h#2
 edit

608 delta lines: 570 added, 22 deleted, 16 changed

Also consider running:
        g4 lint -c 10562599

which verifies that the changelist doesn't introduce new style violations.

If you can't do the review, please let me know as soon as possible.  During
your review, please ensure that all new code has corresponding unit tests and
that existing unit tests are updated appropriately.  Visit
http://www/eng/code_review.html for more information.

This is a semiautomated message from "g4 mail".  Complaints or suggestions?
Mail [email protected].
Change 10562599 by nigel...@nigeltao-srcwingears2 on 2009/03/21 15:09:02 
*pending*

        First cut of on-screen canvas rendering.
        
        The model is that a GearsCanvas remains an off-screen object, but it
        now can have a DOM element peer (provided that the GearsCanvas isn't
        in a worker thread) that can participate in the DOM tree, and knows
        how to render the GearsCanvas' contents (i.e. the backing SkBitmap).
        
        On IE, this uses an IHTMLPainter behavior and GDI+ to blit the
        SkBitmap directly. Compared to the 'indirect' method of rendering a
        GearsCanvas (i.e. calling encode() to create a PNG Blob to capture
        (via LocalServer) to point an <img>'s src to), this actually renders
        transparency properly on IE6.
        
        On Firefox, I am not aware of an equivalent mechanism to IHTMLPainter,
        and so the rendering peer is a (Firefox's native) <canvas> element,
        and the data is transferred from the GearsCanvas gc to the native
        canvas nc via nc.putImageData(gc.getImageData()). This is undoubtedly
        inefficient, but it is correct, and we can do something faster (but
        more complicated) later. Besides, Firefox already has a native canvas,
        and so the Gears canvas' on-screen rendering performance on FF is not
        as high a priority as the speed on IE (which has no native canvas).
        
        I've punted on measuring rendering performance, since a call to
        invalidateRenderingElement doesn't actually paint the pixels, it
        schedules a paint to happen some time in the future, and therefore
        measuring the clock time elapsed before and after an
        invalidateRenderingElement call won't capture the total time to
        draw the off-screen bitmap on-screen.
        
        In order to avoid a conversion from SkBitmap's packing order and
        GDI+'s packing order, Skia's packing was configured to be ARGB
        (instead of Skia's default ABGR) on Win32 Gears builds.
        
        This is very much pre-alpha quality (and has only been tested on
        IE/Win32, Firefox/Win32, and very briefly on Firefox/Linux). The
        API is also up for debate (e.g. should invalidation be automatic
        or explicit). Nonetheless, it works, so I'm putting this out as a
        first cut.
        
        OCL=10562599

Affected files ...

... //depot/googleclient/gears/opensource/gears/Makefile#241 edit
... //depot/googleclient/gears/opensource/gears/base/common/js_runner.h#21 edit
... //depot/googleclient/gears/opensource/gears/base/common/js_runner_ff.cc#33 
edit
... //depot/googleclient/gears/opensource/gears/base/common/js_types.cc#53 edit
... //depot/googleclient/gears/opensource/gears/base/common/leak_counter.cc#16 
edit
... //depot/googleclient/gears/opensource/gears/base/common/leak_counter.h#15 
edit
... //depot/googleclient/gears/opensource/gears/canvas/canvas.cc#26 edit
... //depot/googleclient/gears/opensource/gears/canvas/canvas.h#21 edit
... 
//depot/googleclient/gears/opensource/gears/canvas/canvas_rendering_context_2d.cc#21
 edit
... 
//depot/googleclient/gears/opensource/gears/canvas/canvas_rendering_element_ie.cc#1
 add
... 
//depot/googleclient/gears/opensource/gears/canvas/canvas_rendering_element_ie.h#1
 add
... //depot/googleclient/gears/opensource/gears/test/manual/canvas.html#5 edit
... //depot/googleclient/gears/opensource/gears/tools/config.mk#105 edit
... //depot/googleclient/gears/opensource/third_party/skia/README.google#6 edit
... 
//depot/googleclient/gears/opensource/third_party/skia/include/core/SkUserConfig.h#2
 edit

==== //depot/googleclient/gears/opensource/gears/Makefile#241 - 
c:\devel\srcwingears2/googleclient/gears/opensource/gears/Makefile ====
# action=edit type=text
--- googleclient/gears/opensource/gears/Makefile        2009-03-17 
23:38:31.000000000 +1100
+++ googleclient/gears/opensource/gears/Makefile        2009-03-17 
11:44:06.000000000 +1100
@@ -1332,6 +1332,10 @@
                canvas_rendering_context_2d.cc \
                $(NULL)
 
+IE_CPPSRCS += \
+               canvas_rendering_element_ie.cc \
+               $(NULL)
+
 endif  # not android
 endif  # not wince
 endif  # OFFICIAL_BUILD
==== //depot/googleclient/gears/opensource/gears/base/common/js_runner.h#21 - 
c:\devel\srcwingears2/googleclient/gears/opensource/gears/base/common/js_runner.h
 ====
# action=edit type=text
--- googleclient/gears/opensource/gears/base/common/js_runner.h 2009-03-16 
14:52:30.000000000 +1100
+++ googleclient/gears/opensource/gears/base/common/js_runner.h 2009-03-16 
14:52:38.000000000 +1100
@@ -100,6 +100,13 @@
   virtual JsContextPtr GetContext() = 0;
   virtual bool Eval(const std::string16 &script) = 0;
   virtual void SetErrorHandler(JsErrorHandlerInterface *error_handler) = 0;
+
+#if BROWSER_FF
+  virtual bool EvalFuncWithModuleArg(
+      const std::string16 &script,
+      ModuleImplBaseClass *module,
+      jsval *return_value) = 0;
+#endif
 
   // Creates a new object in the JavaScript engine. The caller takes ownership
   // of the returned value.
==== //depot/googleclient/gears/opensource/gears/base/common/js_runner_ff.cc#33 
- 
c:\devel\srcwingears2/googleclient/gears/opensource/gears/base/common/js_runner_ff.cc
 ====
# action=edit type=text
--- googleclient/gears/opensource/gears/base/common/js_runner_ff.cc     
2009-03-16 14:52:30.000000000 +1100
+++ googleclient/gears/opensource/gears/base/common/js_runner_ff.cc     
2009-03-16 14:47:53.000000000 +1100
@@ -484,6 +484,10 @@
   bool Start(const std::string16 &full_script);
   bool Stop();
   virtual bool Eval(const std::string16 &full_script, jsval *return_value);
+  virtual bool EvalFuncWithModuleArg(
+      const std::string16 &script,
+      ModuleImplBaseClass *module,
+      jsval *return_value);
   void SetErrorHandler(JsErrorHandlerInterface *handler) {
     error_handler_ = handler;
   }
@@ -726,6 +730,15 @@
   return true;
 }
 
+bool JsRunner::EvalFuncWithModuleArg(
+    const std::string16 &script,
+    ModuleImplBaseClass *module,
+    jsval *return_value) {
+  // This method is unimplemented simply because it is unused.
+  assert(false);
+  return false;
+}
+
 bool JsRunner::InvokeCallbackSpecialized(
                    const JsRootedCallback *callback, int argc, jsval *argv,
                    JsRootedToken **optional_alloc_retval) {
@@ -799,6 +812,11 @@
     return false;
   }
   virtual bool Eval(const std::string16 &full_script, jsval *return_value);
+  virtual bool EvalFuncWithModuleArg(
+      const std::string16 &script,
+      ModuleImplBaseClass *module,
+      jsval *return_value);
+
   bool InvokeCallbackSpecialized(const JsRootedCallback *callback,
                                  int argc, jsval *argv,
                                  JsRootedToken **optional_alloc_retval);
@@ -900,6 +918,27 @@
   if (!js_ok) { return false; }
   return true;
 }
+
+
+bool DocumentJsRunner::EvalFuncWithModuleArg(
+    const std::string16 &script,
+    ModuleImplBaseClass *module,
+    jsval *return_value) {
+  JSObject *object = JS_GetGlobalObject(js_engine_context_);
+  if (!object) { return false; }
+
+  // First eval the script to get the function...
+  jsval f_as_jsval;
+  if (!Eval(script, &f_as_jsval)) { return false; }
+
+  // ...and then call the function with the module as the argument.
+  scoped_array<jsval> argv(new jsval[1]);
+  argv[0] = module->GetWrapperToken();
+  return JS_CallFunction(js_engine_context_, object,
+                         JS_ValueToFunction(js_engine_context_, f_as_jsval),
+                         1, argv.get(), return_value);
+}
+
 
 bool DocumentJsRunner::ListenForUnloadEvent() {
   unload_monitor_.reset(new HtmlEventMonitor(kEventUnload,
==== //depot/googleclient/gears/opensource/gears/base/common/js_types.cc#53 - 
c:\devel\srcwingears2/googleclient/gears/opensource/gears/base/common/js_types.cc
 ====
# action=edit type=text
--- googleclient/gears/opensource/gears/base/common/js_types.cc 2009-03-16 
14:52:31.000000000 +1100
+++ googleclient/gears/opensource/gears/base/common/js_types.cc 2009-03-17 
18:12:52.000000000 +1100
@@ -2086,6 +2086,9 @@
     case JSPARAM_UNDEFINED:
       *token = JSVAL_VOID;
       break;
+    case JSPARAM_TOKEN:
+      *token = *(static_cast<const JsToken*>(param.value_ptr));
+      break;
     default:
       assert(false);
   }
@@ -2209,6 +2212,10 @@
       // Setting *token = VT_EMPTY doesn't seem to work.
       token->Clear();
       break;
+    case JSPARAM_TOKEN: {
+      *token = *static_cast<const VARIANT *>(param.value_ptr);
+      break;
+    }
     default:
       assert(false);
   }
==== //depot/googleclient/gears/opensource/gears/base/common/leak_counter.cc#16 
- 
c:\devel\srcwingears2/googleclient/gears/opensource/gears/base/common/leak_counter.cc
 ====
# action=edit type=text
--- googleclient/gears/opensource/gears/base/common/leak_counter.cc     
2009-03-02 17:13:47.000000000 +1100
+++ googleclient/gears/opensource/gears/base/common/leak_counter.cc     
2009-03-17 21:12:28.000000000 +1100
@@ -40,6 +40,7 @@
 static AtomicWord leak_counter_counters[MAX_LEAK_COUNTER_TYPE];
 
 static const char16 *leak_counter_names[] = {
+  STRING16(L"CanvasRenderingElementIE"),
   STRING16(L"DocumentJsRunner"),
   STRING16(L"DropTarget"),
   STRING16(L"DropTargetInterceptor"),
==== //depot/googleclient/gears/opensource/gears/base/common/leak_counter.h#15 
- 
c:\devel\srcwingears2/googleclient/gears/opensource/gears/base/common/leak_counter.h
 ====
# action=edit type=text
--- googleclient/gears/opensource/gears/base/common/leak_counter.h      
2009-03-02 17:13:47.000000000 +1100
+++ googleclient/gears/opensource/gears/base/common/leak_counter.h      
2009-03-17 21:12:22.000000000 +1100
@@ -40,6 +40,7 @@
 // When adding new LeakCounterTypes, please keep them in alphabetical order,
 // and also update the leak_counter_names array in leak_counter.cc.
 enum LeakCounterType {
+  LEAK_COUNTER_TYPE_CanvasRenderingElementIE,
   LEAK_COUNTER_TYPE_DocumentJsRunner,
   LEAK_COUNTER_TYPE_DropTarget,
   LEAK_COUNTER_TYPE_DropTargetInterceptor,
==== //depot/googleclient/gears/opensource/gears/canvas/canvas.cc#26 - 
c:\devel\srcwingears2/googleclient/gears/opensource/gears/canvas/canvas.cc ====
# action=edit type=text
--- googleclient/gears/opensource/gears/canvas/canvas.cc        2009-03-21 
14:41:20.000000000 +1100
+++ googleclient/gears/opensource/gears/canvas/canvas.cc        2009-03-21 
14:12:44.000000000 +1100
@@ -36,6 +36,10 @@
 #include "third_party/skia/include/images/SkImageDecoder.h"
 #include "third_party/skia/include/images/SkImageEncoder.h"
 
+#if BROWSER_IE
+#include "gears/canvas/canvas_rendering_element_ie.h"
+#endif
+
 namespace canvas {
 const SkBitmap::Config skia_config = SkBitmap::kARGB_8888_Config;
 }
@@ -47,7 +51,10 @@
 
 GearsCanvas::GearsCanvas()
     : ModuleImplBaseClass(kModuleName),
-    rendering_context_(NULL) {
+      rendering_context_(NULL) {
+#if BROWSER_IE
+  rendering_element_ = NULL;
+#endif
   // Initial dimensions as per the HTML5 canvas spec.
   ResetCanvas(300, 150);
 }
@@ -56,6 +63,14 @@
   // The rendering context is destroyed first, since it has a scoped_refptr to
   // this object. See comment near bottom of canvas.h.
   assert(rendering_context_ == NULL);
+#if BROWSER_IE
+  if (rendering_element_ != NULL) {
+    rendering_element_->OnGearsCanvasDestroyed();
+    // This Release is balanced by an AddRef in GetRenderingElement.
+    rendering_element_->Release();
+    rendering_element_ = NULL;
+  }
+#endif
 }
 
 void GearsCanvas::ClearRenderingContextReference() {
@@ -71,6 +86,18 @@
   RegisterMethod("resize", &GearsCanvas::Resize);
   RegisterProperty("height", &GearsCanvas::GetHeight, &GearsCanvas::SetHeight);
   RegisterProperty("width", &GearsCanvas::GetWidth, &GearsCanvas::SetWidth);
+  // TODO(nigeltao): We need to decide which one of the (off-screen)
+  // GearsCanvas and the (on-screen) rendering DOM element is the definitive
+  // one, in terms of width and height. Does modifying the WxH of one
+  // necessitate keeping the other one in sync?
+  RegisterMethod("getRenderingElement", &GearsCanvas::GetRenderingElement);
+  // TODO(nigeltao): Should we even have this method? Should invalidation
+  // instead be automatic (like the Gecko and WebKit canvas implementations,
+  // which are invalidated after every drawing operation) rather than explicit?
+  // The answer probably depends on whether we can make rendering sufficiently
+  // fast on all Browser x OS combinations.
+  RegisterMethod("invalidateRenderingElement",
+      &GearsCanvas::InvalidateRenderingElement);
 }
 
 void GearsCanvas::EnsureBitmapPixelsAreAllocated() {
@@ -328,6 +355,106 @@
   context->SetReturnValue(JSPARAM_MODULE, rendering_context_);
 }
 
+void GearsCanvas::GetRenderingElement(JsCallContext *context) {
+  if (EnvIsWorker()) {
+    context->SetException(
+        STRING16(L"getRenderingElement is not supported in workers."));
+    return;
+  }
+
+#if BROWSER_FF
+  JsToken retval = JSVAL_NULL;
+  // In the script below, g is the Gears canvas.
+  module_environment_->js_runner_->EvalFuncWithModuleArg(
+      STRING16(L"function(g){"
+          L"if(!g.renderingElement)"
+            L"g.renderingElement=document.createElement('canvas');"
+          L"return g.renderingElement;}"),
+      this,
+      &retval);
+  if (retval == JSVAL_NULL) {
+    context->SetException(STRING16(L"Error in getRenderingElement."));
+    return;
+  }
+  context->SetReturnValue(JSPARAM_TOKEN, &retval);
+#elif BROWSER_IE
+  if (!rendering_element_) {
+    CComObject<CanvasRenderingElementIE> *rendering_element;
+    if (FAILED(CComObject<CanvasRenderingElementIE>::CreateInstance(
+            &rendering_element))) {
+      context->SetException(GET_INTERNAL_ERROR_MESSAGE());
+      return;
+    }
+    rendering_element_ = rendering_element;
+    if (!rendering_element_) {
+      context->SetException(GET_INTERNAL_ERROR_MESSAGE());
+      return;
+    }
+    // This AddRef is balanced by a Release in the GearsCanvas destructor.
+    rendering_element_->AddRef();
+    rendering_element_->SetGearsCanvas(this);
+  }
+  IHTMLElement *element = rendering_element_->GetHtmlElement();
+  if (!element) {
+    context->SetException(GET_INTERNAL_ERROR_MESSAGE());
+    return;
+  }
+  CComVariant result(element);
+  context->SetReturnValue(JSPARAM_TOKEN, &result);
+#else
+  context->SetException(STRING16(L"Unimplemented"));
+#endif
+}
+
+void GearsCanvas::InvalidateRenderingElement(JsCallContext *context) {
+  if (EnvIsWorker()) {
+    context->SetException(
+        STRING16(L"invalidateRenderingElement is not supported in workers."));
+    return;
+  }
+  // Currently, this method takes no args, although it could conceivably take
+  // an (optional) x,y,w,h rectangle to invalidate.
+
+#if BROWSER_FF
+  JsToken retval = JSVAL_NULL;
+  module_environment_->js_runner_->EvalFuncWithModuleArg(
+      // In the script below, g is the Gears canvas, gc is the Gears canvas'
+      // 2d-context, and nc is the native canvas' 2d-context. The 256 is
+      // just a number that is not more than the getImageData upper bound,
+      // GearsCanvasRenderingContext2D::kMaxImageDataSize.
+      // This script uses getImageData/putImageData to move the pixels from
+      // the off-screen Gears canvas to the on-screen native canvas, in sets
+      // of 256 x 256 slices. This probably isn't the fastest way to paint a
+      // Gears canvas onto the screen (as opposed to some low-level XPCOM
+      // incantations), and we're not even caching the eval'ed function, but
+      // it is simple and it works, and we can optimize the implementation
+      // later, if necessary.
+      STRING16(L"function(g){"
+          L"if(!g.renderingElement)"
+            L"return;"
+          L"var gc=g.getContext('gears-2d');"
+          L"var nc=g.renderingElement.getContext('2d');"
+          L"for(var y=0;y<g.height;y+=256){"
+            L"for(var x=0;x<g.width;x+=256){"
+              L"var w=Math.min(256,g.width-x);"
+              L"var h=Math.min(256,g.height-y);"
+              L"nc.putImageData(gc.getImageData(x,y,w,h),x,y);"
+          L"}}}"),
+      this,
+      &retval);
+  if (retval == JSVAL_NULL) {
+    context->SetException(STRING16(L"Error in invalidateRenderingElement."));
+    return;
+  }
+#elif BROWSER_IE
+  if (rendering_element_) {
+    rendering_element_->InvalidateRenderingElement();
+  }
+#else
+  context->SetException(STRING16(L"Unimplemented"));
+#endif
+}
+
 int GearsCanvas::GetWidth() const {
   return skia_bitmap_->width();
 }
==== //depot/googleclient/gears/opensource/gears/canvas/canvas.h#21 - 
c:\devel\srcwingears2/googleclient/gears/opensource/gears/canvas/canvas.h ====
# action=edit type=text
--- googleclient/gears/opensource/gears/canvas/canvas.h 2009-03-21 
14:41:21.000000000 +1100
+++ googleclient/gears/opensource/gears/canvas/canvas.h 2009-03-21 
14:09:31.000000000 +1100
@@ -38,6 +38,9 @@
 class SkCanvas;
 struct SkIRect;
 
+#if BROWSER_IE
+class CanvasRenderingElementIE;
+#endif
 class GearsCanvasRenderingContext2D;
 
 // Extension of a subset of HTML5 canvas for photo manipulation.
@@ -89,6 +92,16 @@
   // IN: String contextId
   // OUT: CanvasRenderingContext2D
   void GetContext(JsCallContext *context);
+
+  // Returns a DOM element peer that renders this Gears canvas onto the screen.
+  // IN: -
+  // OUT: DomElement
+  void GetRenderingElement(JsCallContext *context);
+
+  // Invalidates the DOM element peer, and therefore repaints the Gears canvas.
+  // IN: -
+  // OUT: -
+  void InvalidateRenderingElement(JsCallContext *context);
 
 
   // The following are not exported to Javascript.
@@ -144,6 +157,13 @@
   double alpha_;
   std::string16 composite_operation_;
 
+#if BROWSER_IE
+  // Ideally, this should be a CComPtr<CanvasRenderingElementIE>, but doing
+  // that causes inscrutable C++ template errors. Instead, we manually AddRef
+  // and Release this COM object.
+  CanvasRenderingElementIE *rendering_element_;
+#endif
+
   DISALLOW_EVIL_CONSTRUCTORS(GearsCanvas);
 };
 
==== 
//depot/googleclient/gears/opensource/gears/canvas/canvas_rendering_context_2d.cc#21
 - 
c:\devel\srcwingears2/googleclient/gears/opensource/gears/canvas/canvas_rendering_context_2d.cc
 ====
# action=edit type=text
--- googleclient/gears/opensource/gears/canvas/canvas_rendering_context_2d.cc   
2009-03-19 22:02:56.000000000 +1100
+++ googleclient/gears/opensource/gears/canvas/canvas_rendering_context_2d.cc   
2009-03-21 14:44:43.000000000 +1100
@@ -673,25 +673,6 @@
   // TODO(nigeltao): Are the colors premultiplied? If so, unpremultiply them.
 }
 
-static U8CPU InvScaleByte(U8CPU component, uint32_t scale)
-{
-  assert(component == static_cast<uint8_t>(component));
-  return (component * scale + 0x8000) >> 16;
-}
-
-// TODO(nigeltao): Submit Unpremultiply (and InvScaleByte) into upstream Skia.
-static SkColor Unpremultiply(SkPMColor pm) {
-  if (pm == 0) {
-    return 0;
-  }
-  uint32_t a = SkGetPackedA32(pm);
-  uint32_t scale = (255 << 16) / a;
-  return SkColorSetARGB(a,
-                        InvScaleByte(SkGetPackedR32(pm), scale),
-                        InvScaleByte(SkGetPackedG32(pm), scale),
-                        InvScaleByte(SkGetPackedB32(pm), scale));
-}
-
 void GearsCanvasRenderingContext2D::CreateImageData(JsCallContext *context) {
   double sw, sh;
   JsArgument args[] = {
@@ -772,13 +753,40 @@
 
   int data_index = 0;
   for (int j = 0; j < h; j++) {
-    uint32_t* source = bitmap.getAddr32(x, y + j);
+    uint8 *source = reinterpret_cast<uint8*>(bitmap.getAddr32(x, y + j));
     for (int i = 0; i < w; i++) {
-      SkColor color = Unpremultiply(source[i]);
-      data->SetElementInt(data_index++, SkColorGetR(color));
-      data->SetElementInt(data_index++, SkColorGetG(color));
-      data->SetElementInt(data_index++, SkColorGetB(color));
-      data->SetElementInt(data_index++, SkColorGetA(color));
+      uint8 r, g, b, a;
+      // This unpacking code presumes that we are little-endian.
+      if (SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16) {
+        r = *source++;
+        g = *source++;
+        b = *source++;
+        a = *source++;
+      } else if (SK_R32_SHIFT == 16 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 0) 
{
+        b = *source++;
+        g = *source++;
+        r = *source++;
+        a = *source++;
+      } else {
+        assert(false);
+        context->SetException(GET_INTERNAL_ERROR_MESSAGE());
+        return;
+      }
+
+      // Unpremultiply.
+      if (a == 0) {
+        r = g = b = 0;
+      } else {
+        uint32 scale = (255 << 16) / a;
+        r = (static_cast<uint32>(r) * scale + (1 << 15)) >> 16;
+        g = (static_cast<uint32>(g) * scale + (1 << 15)) >> 16;
+        b = (static_cast<uint32>(b) * scale + (1 << 15)) >> 16;
+      }
+
+      data->SetElementInt(data_index++, r);
+      data->SetElementInt(data_index++, g);
+      data->SetElementInt(data_index++, b);
+      data->SetElementInt(data_index++, a);
     }
   }
 
@@ -862,6 +870,10 @@
       pixel_g = std::max(0, std::min(255, pixel_g));
       pixel_b = std::max(0, std::min(255, pixel_b));
       pixel_a = std::max(0, std::min(255, pixel_a));
+      // SkPreMultiplyARGB calls SkPackARGB32, which picks up the SK_R32_SHIFT
+      // macros defined in SkUserConfig.h, and hence this code below works
+      // either way, if we pack BGRA (as on Win32, same as GDI+) or RGBA
+      // (Skia's default, which we use on non-Win32 platforms).
       source[i] = SkPreMultiplyARGB(
           static_cast<U8CPU>(pixel_a),
           static_cast<U8CPU>(pixel_r),
==== 
//depot/googleclient/gears/opensource/gears/canvas/canvas_rendering_element_ie.cc#1
 - 
c:\devel\srcwingears2/googleclient/gears/opensource/gears/canvas/canvas_rendering_element_ie.cc
 ====
# action=add type=text
--- /dev/null   1970-01-01 11:00:00.000000000 +1100
+++ googleclient/gears/opensource/gears/canvas/canvas_rendering_element_ie.cc   
2009-03-23 13:51:40.000000000 +1100
@@ -0,0 +1,214 @@
+// Copyright 2009, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//  1. Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//  2. Redistributions in binary form must reproduce the above copyright 
notice,
+//     this list of conditions and the following disclaimer in the 
documentation
+//     and/or other materials provided with the distribution.
+//  3. Neither the name of Google Inc. nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#undef NOMINMAX
+#include <mshtmdid.h>
+#include <windows.h>
+#include <gdiplus.h>
+
+#include "gears/canvas/canvas_rendering_element_ie.h"
+
+#include "gears/base/common/base_class.h"
+#include "gears/base/common/leak_counter.h"
+#include "gears/base/common/scoped_refptr.h"
+#include "gears/base/ie/activex_utils.h"
+#include "gears/canvas/canvas.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColorPriv.h"
+
+
+CanvasRenderingElementIE::CanvasRenderingElementIE()
+    : canvas_(NULL) {
+  LEAK_COUNTER_INCREMENT(CanvasRenderingElementIE);
+}
+
+
+CanvasRenderingElementIE::~CanvasRenderingElementIE() {
+  LEAK_COUNTER_DECREMENT(CanvasRenderingElementIE);
+}
+
+
+HRESULT CanvasRenderingElementIE::Detach(void) {
+  return S_OK;
+}
+
+
+HRESULT CanvasRenderingElementIE::Init(
+    IElementBehaviorSite *pElementBehaviorSite) {
+  paint_site_ = pElementBehaviorSite;
+  return S_OK;
+}
+
+
+HRESULT CanvasRenderingElementIE::Notify(LONG lEvent, VARIANT *pVar) {
+  return S_OK;
+}
+
+  
+HRESULT CanvasRenderingElementIE::FindBehavior(
+    BSTR name, BSTR url, IElementBehaviorSite *site, IElementBehavior **out) {
+  if (!name || (_wcsicmp(name, L"CanvasRendering") != 0)) {
+    return E_FAIL;
+  }
+  return QueryInterface(IID_IElementBehavior, reinterpret_cast<void**>(out));
+}
+
+
+HRESULT CanvasRenderingElementIE::Draw(
+      RECT rcBounds, RECT rcUpdate, LONG lDrawFlags, HDC hdc,
+      LPVOID pvDrawObject) {
+  if (!canvas_) {
+    return S_OK;
+  }
+  const SkBitmap &skia_bitmap = canvas_->GetSkBitmap();
+  assert(skia_bitmap.config() == SkBitmap::kARGB_8888_Config);
+  const int w = skia_bitmap.width();
+  const int h = skia_bitmap.height();
+  if (w <= 0 || h <= 0) {
+    return S_OK;
+  }
+  SkAutoLockPixels skia_bitmap_lock(skia_bitmap);
+
+#if 0
+  // If debugging InvalidateRect, enable this code to make the rendering
+  // element's background color change on every call to Draw.
+  static int count = 0;
+  HBRUSH hBrush = CreateSolidBrush(RGB(
+      count == 0 ? 255 : 200,
+      count == 1 ? 255 : 200,
+      count == 2 ? 255 : 200));
+  HGDIOBJ hOldBrush = SelectObject(hdc, hBrush);
+  HGDIOBJ hOldPen = SelectObject(hdc, (HPEN)GetStockObject(NULL_PEN));
+  Rectangle(hdc, rcBounds.left, rcBounds.top,
+      1 + rcBounds.right, 1 + rcBounds.bottom);
+  SelectObject(hdc, hOldBrush);
+  SelectObject(hdc, hOldPen);
+  DeleteObject(hBrush);
+  count = (count + 1) % 3;
+#endif
+
+  // The GdiplusStartup Function docs at
+  // http://msdn.microsoft.com/en-us/library/ms534077(VS.85).aspx say,
+  // "If you want to create a DLL that uses GDI+, ... Call GdiplusStartup and
+  // GdiplusShutdown in each of your functions that make GDI+ calls."
+  Gdiplus::GdiplusStartupInput gdiplusStartupInput;
+  ULONG_PTR gdiplusToken;
+  if (Gdiplus::Ok != Gdiplus::GdiplusStartup(
+          &gdiplusToken, &gdiplusStartupInput, NULL)) {
+    return E_FAIL;
+  }
+
+  // Scoped by { ... } so that we delete our Gdiplus::Bitmap object *before* we
+  // call GdiplusShutdown.
+  {
+    Gdiplus::Graphics graphics(hdc);
+    // As configured by SkUserConfig.h, Skia and GDI+ have the same byte order
+    // in interpreting "ARGB", so we can re-use the SkBitmap's buffer for our
+    // GDI+ Bitmap. The "P" in PixelFormat32bppPARGB stands for pre-multiplied
+    // (which what SkBitmap does).
+    Gdiplus::Bitmap gdiplus_bitmap(
+        w, h, skia_bitmap.rowBytes(), PixelFormat32bppPARGB,
+        reinterpret_cast<uint8*>(skia_bitmap.getAddr32(0, 0)));
+    graphics.DrawImage(&gdiplus_bitmap, rcBounds.left, rcBounds.top);
+  }
+
+  Gdiplus::GdiplusShutdown(gdiplusToken);
+  return S_OK;
+}
+
+
+HRESULT CanvasRenderingElementIE::GetPainterInfo(HTML_PAINTER_INFO *pInfo) {
+  // In the future, we should also implement HTMLPAINTER_SUPPORTS_XFORM, to
+  // support full page zoom, for example.
+  pInfo->lFlags = HTMLPAINTER_TRANSPARENT;
+  pInfo->lZOrder = HTMLPAINT_ZORDER_REPLACE_CONTENT;
+  return S_OK;
+}
+
+
+HRESULT CanvasRenderingElementIE::HitTestPoint(
+    POINT pt, BOOL *pbHit, LONG *plPartID) {
+  return S_OK;
+}
+
+
+HRESULT CanvasRenderingElementIE::OnResize(SIZE pt) {
+  return S_OK;
+}
+
+  
+void CanvasRenderingElementIE::SetGearsCanvas(GearsCanvas *canvas) {
+  assert(canvas_ == NULL);
+  canvas_ = canvas;
+}
+
+
+void CanvasRenderingElementIE::OnGearsCanvasDestroyed() {
+  assert(canvas_ != NULL);
+  canvas_ = NULL;
+}
+
+
+IHTMLElement *CanvasRenderingElementIE::GetHtmlElement() {
+  if (!canvas_) {
+    return NULL;
+  }
+  if (html_element_) {
+    return html_element_;
+  }
+  scoped_refptr<ModuleEnvironment> module_environment;
+  canvas_->GetModuleEnvironment(&module_environment);
+  CComPtr<IHTMLDocument2> document;
+  if (FAILED(ActiveXUtils::GetHtmlDocument2(
+          module_environment->iunknown_site_, &document))) {
+    return NULL;
+  }
+  IHTMLElement *result = NULL;
+  document->createElement(CComBSTR(STRING16(L"gearsCanvasRenderer")), &result);
+  CComQIPtr<IHTMLElement2> html_element2(result);
+  if (!html_element2) {
+    return NULL;
+  }
+  CComBSTR behavior_url(L"#" PRODUCT_SHORT_NAME L"#CanvasRendering");
+  CComQIPtr<IElementBehaviorFactory> factory(this);
+  if (!factory) {
+    return NULL;
+  }
+  CComVariant factory_as_variant(static_cast<IUnknown *>(factory));
+  LONG cookie = 0;
+  if (FAILED(html_element2->addBehavior(
+          behavior_url, &factory_as_variant, &cookie))) {
+    return NULL;
+  }
+  html_element_ = result;
+  return result;
+}
+
+
+void CanvasRenderingElementIE::InvalidateRenderingElement() {
+  if (paint_site_) {
+    paint_site_->InvalidateRect(NULL);
+  }
+}
==== 
//depot/googleclient/gears/opensource/gears/canvas/canvas_rendering_element_ie.h#1
 - 
c:\devel\srcwingears2/googleclient/gears/opensource/gears/canvas/canvas_rendering_element_ie.h
 ====
# action=add type=text
--- /dev/null   1970-01-01 11:00:00.000000000 +1100
+++ googleclient/gears/opensource/gears/canvas/canvas_rendering_element_ie.h    
2009-03-21 11:13:03.000000000 +1100
@@ -0,0 +1,86 @@
+// Copyright 2009, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//  1. Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//  2. Redistributions in binary form must reproduce the above copyright 
notice,
+//     this list of conditions and the following disclaimer in the 
documentation
+//     and/or other materials provided with the distribution.
+//  3. Neither the name of Google Inc. nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GEARS_CANVAS_CANVAS_RENDERING_ELEMENT_IE_H__
+#define GEARS_CANVAS_CANVAS_RENDERING_ELEMENT_IE_H__
+
+#if !defined(OFFICIAL_BUILD)
+
+#include "gears/base/common/common.h"
+
+class GearsCanvas;
+struct IHTMLElement;
+
+class ATL_NO_VTABLE CanvasRenderingElementIE
+    : public CComObjectRootEx<CComMultiThreadModel>,
+      public CComCoClass<CanvasRenderingElementIE>,
+      public IElementBehavior,
+      public IElementBehaviorFactory,
+      public IHTMLPainter {
+ public:
+  DECLARE_NOT_AGGREGATABLE(CanvasRenderingElementIE)
+  DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+  BEGIN_COM_MAP(CanvasRenderingElementIE)
+    COM_INTERFACE_ENTRY(IElementBehavior)
+    COM_INTERFACE_ENTRY(IElementBehaviorFactory)
+    COM_INTERFACE_ENTRY(IHTMLPainter)
+  END_COM_MAP()
+
+  // IElementBehavior methods
+  STDMETHOD(Detach)(void);
+  STDMETHOD(Init)(IElementBehaviorSite *pElementBehaviorSite);
+  STDMETHOD(Notify)(LONG lEvent, VARIANT *pVar);
+
+  // IElementBehaviorFactory methods
+  STDMETHOD(FindBehavior)(
+      BSTR name, BSTR url, IElementBehaviorSite *site, IElementBehavior **out);
+
+  // IHTMLPainter methods
+  STDMETHOD(Draw)(
+      RECT rcBounds, RECT rcUpdate, LONG lDrawFlags, HDC hdc,
+      LPVOID pvDrawObject);
+  STDMETHOD(GetPainterInfo)(HTML_PAINTER_INFO *pInfo);
+  STDMETHOD(HitTestPoint)(POINT pt, BOOL *pbHit, LONG *plPartID);
+  STDMETHOD(OnResize)(SIZE pt);
+
+  CanvasRenderingElementIE();
+  virtual ~CanvasRenderingElementIE();
+
+  IHTMLElement *GetHtmlElement();
+  void InvalidateRenderingElement();
+  void OnGearsCanvasDestroyed();
+  void SetGearsCanvas(GearsCanvas *canvas);
+
+ private:
+  GearsCanvas *canvas_;
+  CComQIPtr<IHTMLElement> html_element_;
+  CComQIPtr<IHTMLPaintSite> paint_site_;
+
+  DISALLOW_EVIL_CONSTRUCTORS(CanvasRenderingElementIE);
+};
+
+#endif  // !defined(OFFICIAL_BUILD)
+#endif  // GEARS_CANVAS_CANVAS_RENDERING_ELEMENT_IE_H__
==== //depot/googleclient/gears/opensource/gears/test/manual/canvas.html#5 - 
c:\devel\srcwingears2/googleclient/gears/opensource/gears/test/manual/canvas.html
 ====
# action=edit type=text
--- googleclient/gears/opensource/gears/test/manual/canvas.html 2009-03-20 
16:21:22.000000000 +1100
+++ googleclient/gears/opensource/gears/test/manual/canvas.html 2009-03-21 
14:45:48.000000000 +1100
@@ -1,7 +1,7 @@
 <html><head><title>Gears Canvas</title></head>
 <body style="background-color:#FFFFCF">
 <p>Gears' canvas:</p>
-<img id="gc" width="100px" height="80px" style="border:1px solid black">
+<div id="gc"></div>
 <hr>
 <p>Browser's native canvas:</p>
 <canvas id="bnc" width="100px" height="80px" style="border:1px solid black">
@@ -11,6 +11,9 @@
 <img id="dc" width="100px" height="80px" style="border:1px solid black">
 <script type="text/javascript" src="../../sdk/gears_init.js"></script>
 <script type="text/javascript">
+
+
+var isIE = google.gears.factory.getBuildInfo().indexOf(';ie') > -1;
 
 
 function draw(c) {
@@ -42,9 +45,6 @@
 }
 
 
-var store = null;
-
-
 var gearsCanvas = null;
 try {
   gearsCanvas = google.gears.factory.create('beta.canvas');
@@ -58,12 +58,28 @@
 
   draw(gearsCanvas.getContext('gears-2d'));
 
-  var localServer = google.gears.factory.create('beta.localserver');
-  localServer.removeStore("test_manual_canvas");
-  store = localServer.createStore("test_manual_canvas");
-  var capturedUrl = 'g' + parseInt(Math.random() * 1000) + '.png';
-  store.captureBlob(gearsCanvas.encode(), capturedUrl, 'image/png');
-  document.getElementById('gc').src = capturedUrl;
+  try {
+    var renderingElement = gearsCanvas.getRenderingElement();
+    renderingElement.style.borderWidth = '1px';
+    renderingElement.style.borderStyle = 'solid';
+    renderingElement.style.borderColor = 'black';
+
+    if (isIE) {
+      // The +2 is because IE's CSS engine appears to treat the 1px border
+      // differently from Gecko and WebKit.
+      renderingElement.style.width = gearsCanvas.width + 2;
+      renderingElement.style.height = gearsCanvas.height + 2;
+    } else {
+      renderingElement.width = gearsCanvas.width;
+      renderingElement.height = gearsCanvas.height;
+    }
+
+    document.getElementById('gc').appendChild(renderingElement);
+    gearsCanvas.invalidateRenderingElement();
+  } catch (e) {
+    // Silently ignore any exceptions -- getRenderingElement isn't implemented
+    // on all platforms yet.
+  }
 }
 
 
@@ -121,6 +137,9 @@
 
   diffContext.putImageData(diffImageData, 0, 0);
 
+  var localServer = google.gears.factory.create('beta.localserver');
+  localServer.removeStore("test_manual_canvas");
+  var store = localServer.createStore("test_manual_canvas");
   var capturedUrl = 'd' + parseInt(Math.random() * 1000) + '.png';
   store.captureBlob(diffCanvas.encode(), capturedUrl, 'image/png');
   document.getElementById('dc').src = capturedUrl;
==== //depot/googleclient/gears/opensource/gears/tools/config.mk#105 - 
c:\devel\srcwingears2/googleclient/gears/opensource/gears/tools/config.mk ====
# action=edit type=text
--- googleclient/gears/opensource/gears/tools/config.mk 2009-03-19 
22:02:57.000000000 +1100
+++ googleclient/gears/opensource/gears/tools/config.mk 2009-03-18 
23:34:28.000000000 +1100
@@ -922,7 +922,7 @@
 FF2_LIBS = $(GECKO_LIB)/xpcom.lib $(GECKO_LIB)/xpcomglue_s.lib 
$(GECKO_LIB)/nspr4.lib $(GECKO_LIB)/js3250.lib ole32.lib shell32.lib 
shlwapi.lib advapi32.lib wininet.lib comdlg32.lib user32.lib gdi32.lib
 FF3_LIBS = $(GECKO_LIB)/xpcom.lib $(GECKO_LIB)/xpcomglue_s.lib 
$(GECKO_LIB)/nspr4.lib $(GECKO_LIB)/js3250.lib ole32.lib shell32.lib 
shlwapi.lib advapi32.lib wininet.lib comdlg32.lib user32.lib gdi32.lib
 ifeq ($(OS),win32)
-IE_LIBS = kernel32.lib user32.lib gdi32.lib uuid.lib sensapi.lib shlwapi.lib 
shell32.lib advapi32.lib wininet.lib comdlg32.lib user32.lib
+IE_LIBS = kernel32.lib user32.lib gdi32.lib gdiplus.lib uuid.lib sensapi.lib 
shlwapi.lib shell32.lib advapi32.lib wininet.lib comdlg32.lib user32.lib
 else # wince
 IE_LIBS = $(WINCE_LIBS) coredll.lib ole32.lib oleaut32.lib uuid.lib 
commctrl.lib atlosapis.lib piedocvw.lib htmlview.lib imaging.lib aygshell.lib
 endif
==== //depot/googleclient/gears/opensource/third_party/skia/README.google#6 - 
c:\devel\srcwingears2/googleclient/gears/opensource/third_party/skia/README.google
 ====
# action=edit type=text
--- googleclient/gears/opensource/third_party/skia/README.google        
2009-03-19 22:02:58.000000000 +1100
+++ googleclient/gears/opensource/third_party/skia/README.google        
2009-03-19 22:09:15.000000000 +1100
@@ -6,9 +6,10 @@
 plus the following changes:
 
 
-skia/include/core/SkUserConfig.h lines 20-42 were added to set Gears-specific
+skia/include/core/SkUserConfig.h lines 20-52 were added to set Gears-specific
 build configuration options, based on Chromium's Skia/Win32 edits visible at
 
http://src.chromium.org/viewvc/chrome/trunk/src/skia/include/corecg/SkUserConfig.h
+as well as adding the SkBitmap BGRA byte ordering.
 
 
 skia/src/core/SkCanvas.cpp line 282 (fOnce = false) was added to avoid a
==== 
//depot/googleclient/gears/opensource/third_party/skia/include/core/SkUserConfig.h#2
 - 
c:\devel\srcwingears2/googleclient/gears/opensource/third_party/skia/include/core/SkUserConfig.h
 ====
# action=edit type=text
--- googleclient/gears/opensource/third_party/skia/include/core/SkUserConfig.h  
2009-03-19 22:02:58.000000000 +1100
+++ googleclient/gears/opensource/third_party/skia/include/core/SkUserConfig.h  
2009-03-21 12:04:55.000000000 +1100
@@ -37,6 +37,16 @@
   #undef SK_RESTRICT
   #define SK_RESTRICT
 #endif
+
+// Make SkBitmap's ARGB byte ordering the same as GDI+'s PixelFormat32bppARGB.
+// For example, on little-endian systems, bytes at addresses 3,2,1,0 (mod 4)
+// map to ARGB -- B is the least significant byte, so SK_B32_SHIFT is zero.
+// Skia's default (in SkColorPriv.h) is different, namely ABGR (i.e.
+// SK_R32_SHIFT is 0, SK_G32_SHIFT is 8, SK_B32_SHIFT is 16).
+#define SK_R32_SHIFT 16
+#define SK_G32_SHIFT 8
+#define SK_B32_SHIFT 0
+#define SK_A32_SHIFT 24
 
 #endif  // WIN32
 // END Gears changes

Reply via email to