Hello cprince,

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

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

to review the following code:

Change 10345804 by nigel...@nigeltao-srcgears2 on 2009/03/03 17:11:35 *pending*

        Implement the following canvas methods and properties:
        save, restore, scale, translate, transform, setTransform,
        strokeStyle, lineWidth, lineCap, lineJoin, miterLimit.
        
        PRESUBMIT=passed
        R=cprince
        [email protected]
        DELTA=399  (247 added, 48 deleted, 104 changed)
        OCL=10345804

Affected files ...

... //depot/googleclient/gears/opensource/gears/base/common/js_types.h#40 edit
... 
//depot/googleclient/gears/opensource/gears/canvas/canvas_rendering_context_2d.cc#19
 edit
... 
//depot/googleclient/gears/opensource/gears/canvas/canvas_rendering_context_2d.h#14
 edit
... //depot/googleclient/gears/opensource/gears/test/manual/canvas.html#2 edit

399 delta lines: 247 added, 48 deleted, 104 changed

Also consider running:
        g4 lint -c 10345804

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 10345804 by nigel...@nigeltao-srcgears2 on 2009/03/03 17:11:35 *pending*

        Implement the following canvas methods and properties:
        save, restore, scale, translate, transform, setTransform,
        strokeStyle, lineWidth, lineCap, lineJoin, miterLimit.

Affected files ...

... //depot/googleclient/gears/opensource/gears/base/common/js_types.h#40 edit
... 
//depot/googleclient/gears/opensource/gears/canvas/canvas_rendering_context_2d.cc#19
 edit
... 
//depot/googleclient/gears/opensource/gears/canvas/canvas_rendering_context_2d.h#14
 edit
... //depot/googleclient/gears/opensource/gears/test/manual/canvas.html#2 edit

==== //depot/googleclient/gears/opensource/gears/base/common/js_types.h#40 - 
/home/nigeltao/srcgears2/googleclient/gears/opensource/gears/base/common/js_types.h
 ====
# action=edit type=text
--- googleclient/gears/opensource/gears/base/common/js_types.h  2009-03-03 
17:05:37.000000000 +1100
+++ googleclient/gears/opensource/gears/base/common/js_types.h  2009-03-02 
15:53:57.000000000 +1100
@@ -520,6 +520,7 @@
 
   // Get the type of an argument that was passed in.
   JsParamType GetArgumentType(int i);
+  int GetArgumentCount();
 
   // TODO(nigeltao): Do we really need the coercion parameter? JS type coercion
   // was introduced as part of the Console code, and was to be introduced
@@ -546,7 +547,6 @@
 #endif
 
  private:
-  int GetArgumentCount();
   const JsToken &GetArgument(int index);
 
   JsContextPtr js_context_;
==== 
//depot/googleclient/gears/opensource/gears/canvas/canvas_rendering_context_2d.cc#19
 - 
/home/nigeltao/srcgears2/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-03 17:05:37.000000000 +1100
+++ googleclient/gears/opensource/gears/canvas/canvas_rendering_context_2d.cc   
2009-03-03 16:58:50.000000000 +1100
@@ -29,6 +29,11 @@
 #include "third_party/skia/include/core/SkPorterDuff.h"
 #include "third_party/skia/include/utils/SkParse.h"
 
+// TODO(nigeltao): For any JavaScript-visible method, we should do sanity
+// checking on the args (e.g. ensure that we're not scaling by 1e100), and
+// also check the return value for overflow (if applicable) and handle that
+// gracefully. I think that WebKit's Skia-backed canvas already does this.
+
 DECLARE_DISPATCHER(GearsCanvasRenderingContext2D);
 const std::string
     
GearsCanvasRenderingContext2D::kModuleName("GearsCanvasRenderingContext2D");
@@ -36,8 +41,14 @@
 using canvas::skia_config;
 
 GearsCanvasRenderingContext2D::GearsCanvasRenderingContext2D()
-    : ModuleImplBaseClass(kModuleName) {
+    : ModuleImplBaseClass(kModuleName),
+      fill_style_as_string_(STRING16(L"#000000")),
+      stroke_style_as_string_(STRING16(L"#000000")) {
+  clear_style_as_paint_.setAntiAlias(true);
+  clear_style_as_paint_.setPorterDuffXfermode(SkPorterDuff::kClear_Mode);
   fill_style_as_paint_.setAntiAlias(true);
+  stroke_style_as_paint_.setAntiAlias(true);
+  stroke_style_as_paint_.setStyle(SkPaint::kStroke_Style);
 }
 
 void GearsCanvasRenderingContext2D::SetCanvas(
@@ -104,7 +115,9 @@
       &GearsCanvasRenderingContext2D::SetGlobalCompositeOperation);
 
   // colors and styles
-  // Missing wrt HTML5: strokeStyle.
+  RegisterProperty("strokeStyle",
+      &GearsCanvasRenderingContext2D::GetStrokeStyle,
+      &GearsCanvasRenderingContext2D::SetStrokeStyle);
   RegisterProperty("fillStyle",
       &GearsCanvasRenderingContext2D::GetFillStyle,
       &GearsCanvasRenderingContext2D::SetFillStyle);
@@ -113,10 +126,18 @@
   // Missing wrt HTML5: createPattern.
 
   // line caps/joins
-  // Missing wrt HTML5: lineWidth.
-  // Missing wrt HTML5: lineCap.
-  // Missing wrt HTML5: lineJoin.
-  // Missing wrt HTML5: miterLimit.
+  RegisterProperty("lineWidth",
+      &GearsCanvasRenderingContext2D::GetLineWidth,
+      &GearsCanvasRenderingContext2D::SetLineWidth);
+  RegisterProperty("lineCap",
+      &GearsCanvasRenderingContext2D::GetLineCap,
+      &GearsCanvasRenderingContext2D::SetLineCap);
+  RegisterProperty("lineJoin",
+      &GearsCanvasRenderingContext2D::GetLineJoin,
+      &GearsCanvasRenderingContext2D::SetLineJoin);
+  RegisterProperty("miterLimit",
+      &GearsCanvasRenderingContext2D::GetMiterLimit,
+      &GearsCanvasRenderingContext2D::SetMiterLimit);
 
   // shadows
   // Missing wrt HTML5: shadowOffsetX.
@@ -171,28 +192,30 @@
 }
 
 void GearsCanvasRenderingContext2D::Save(JsCallContext *context) {
-  context->SetException(STRING16(L"Unimplemented"));
+  skia_canvas_->save();
 }
 
 void GearsCanvasRenderingContext2D::Restore(JsCallContext *context) {
-  context->SetException(STRING16(L"Unimplemented"));
+  // SkCanvas silently ignores any restore() calls over and above the number of
+  // save() calls.
+  skia_canvas_->restore();
 }
 
 void GearsCanvasRenderingContext2D::Scale(JsCallContext *context) {
-  double scale_x, scale_y;
-  JsArgument args[] = {
-    { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &scale_x },
-    { JSPARAM_OPTIONAL, JSPARAM_DOUBLE, &scale_y }
-  };
-  context->GetArguments(ARRAYSIZE(args), args);
-  if (context->is_exception_set())
-    return;
-  if (context->GetArgumentType(1) == JSPARAM_UNDEFINED) {
+  double sx, sy;
+  JsArgument args[] = {
+    { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &sx },
+    { JSPARAM_OPTIONAL, JSPARAM_DOUBLE, &sy }
+  };
+  context->GetArguments(ARRAYSIZE(args), args);
+  if (context->is_exception_set())
+    return;
+
+  if (context->GetArgumentCount() == 1) {
     // If only one scale argument is supplied, use it for both dimensions.
-    // TODO(nigeltao): Test this.
-    scale_y = scale_x;
-  }
-  context->SetException(STRING16(L"Unimplemented"));
+    sy = sx;
+  }
+  skia_canvas_->scale(SkDoubleToScalar(sx), SkDoubleToScalar(sy));
 }
 
 void GearsCanvasRenderingContext2D::Rotate(JsCallContext *context) {
@@ -203,27 +226,26 @@
   context->GetArguments(ARRAYSIZE(args), args);
   if (context->is_exception_set())
     return;
-  // Convert to degrees.
-  const double kPi = 3.1415926535;
-  const double kDegreesPerRadian = 180.0/kPi;
-  angle *= kDegreesPerRadian;
-
-  skia_canvas_->rotate(SkDoubleToScalar(angle));
+
+  skia_canvas_->rotate(SkDoubleToScalar(angle * 180.0 / 3.1415926535));
 }
 
 void GearsCanvasRenderingContext2D::Translate(JsCallContext *context) {
-  int x, y;
-  JsArgument args[] = {
-    { JSPARAM_REQUIRED, JSPARAM_INT, &x },
-    { JSPARAM_REQUIRED, JSPARAM_INT, &y }
-  };
-  context->GetArguments(ARRAYSIZE(args), args);
-  if (context->is_exception_set())
-    return;
-  context->SetException(STRING16(L"Unimplemented"));
-}
-
-void GearsCanvasRenderingContext2D::Transform(JsCallContext *context) {
+  double tx, ty;
+  JsArgument args[] = {
+    { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &tx },
+    { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &ty }
+  };
+  context->GetArguments(ARRAYSIZE(args), args);
+  if (context->is_exception_set())
+    return;
+
+  skia_canvas_->translate(SkDoubleToScalar(tx), SkDoubleToScalar(ty));
+}
+
+void GearsCanvasRenderingContext2D::Transform(
+    JsCallContext *context,
+    bool reset_matrix) {
   double m11, m12, m21, m22, dx, dy;
   JsArgument args[] = {
     { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &m11 },
@@ -236,23 +258,28 @@
   context->GetArguments(ARRAYSIZE(args), args);
   if (context->is_exception_set())
     return;
-  context->SetException(STRING16(L"Unimplemented"));
+
+  SkMatrix m;
+  m.reset();
+  m.set(0, SkDoubleToScalar(m11));
+  m.set(1, SkDoubleToScalar(m21));
+  m.set(2, SkDoubleToScalar(dx));
+  m.set(3, SkDoubleToScalar(m12));
+  m.set(4, SkDoubleToScalar(m22));
+  m.set(5, SkDoubleToScalar(dy));
+  if (reset_matrix) {
+    skia_canvas_->concat(m);
+  } else {
+    skia_canvas_->setMatrix(m);
+  }
+}
+
+void GearsCanvasRenderingContext2D::Transform(JsCallContext *context) {
+  Transform(context, false);
 }
 
 void GearsCanvasRenderingContext2D::SetTransform(JsCallContext *context) {
-  double m11, m12, m21, m22, dx, dy;
-  JsArgument args[] = {
-    { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &m11 },
-    { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &m12 },
-    { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &m21 },
-    { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &m22 },
-    { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &dx },
-    { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &dy }
-  };
-  context->GetArguments(ARRAYSIZE(args), args);
-  if (context->is_exception_set())
-    return;
-  context->SetException(STRING16(L"Unimplemented"));
+  Transform(context, true);
 }
 
 void GearsCanvasRenderingContext2D::GetGlobalAlpha(
@@ -297,18 +324,13 @@
   }
 }
 
-void GearsCanvasRenderingContext2D::GetFillStyle(
-    JsCallContext *context) {
-  context->SetReturnValue(JSPARAM_STRING16, &fill_style_as_string_);
-}
-
-// TODO(nigeltao): Generate a better error if given a CanvasGradient or
-// CanvasPattern object (from the browser's canvas implementation).
-void GearsCanvasRenderingContext2D::SetFillStyle(
-    JsCallContext *context) {
-  std::string16 new_fill_style;
-  JsArgument args[] = {
-    { JSPARAM_REQUIRED, JSPARAM_STRING16, &new_fill_style }
+void GearsCanvasRenderingContext2D::SetStyle(
+    JsCallContext *context,
+    std::string16 *style_as_string,
+    SkPaint *style_as_paint) {
+  std::string16 new_style_as_string;
+  JsArgument args[] = {
+    { JSPARAM_REQUIRED, JSPARAM_STRING16, &new_style_as_string }
   };
   context->GetArguments(ARRAYSIZE(args), args);
   // TODO(nigeltao): Do not generate error on type mismatch; fail silently
@@ -316,41 +338,163 @@
   if (context->is_exception_set())
     return;
 
-  std::string new_fill_style_as_utf8;
-  if (!String16ToUTF8(new_fill_style, &new_fill_style_as_utf8)) {
+  std::string new_style_as_utf8;
+  if (!String16ToUTF8(new_style_as_string, &new_style_as_utf8)) {
     return;
   }
 
   // SkParse::FindColor re-uses color's existing alpha value, if unspecified
   // by the string, so we initialize color with alpha=255.
   SkColor color = 0xFFFFFFFF;
-  if (SkParse::FindColor(new_fill_style_as_utf8.c_str(), &color)) {
-    fill_style_as_paint_.setColor(color);
-    fill_style_as_string_ = new_fill_style;
-  }
-}
-
-void GearsCanvasRenderingContext2D::ClearRect(JsCallContext *context) {
-  int x, y, width, height;
-  JsArgument args[] = {
-    { JSPARAM_REQUIRED, JSPARAM_INT, &x },
-    { JSPARAM_REQUIRED, JSPARAM_INT, &y },
-    { JSPARAM_REQUIRED, JSPARAM_INT, &width },
-    { JSPARAM_REQUIRED, JSPARAM_INT, &height }
-  };
-  context->GetArguments(ARRAYSIZE(args), args);
-  if (context->is_exception_set())
-    return;
-  context->SetException(STRING16(L"Unimplemented"));
-}
-
-void GearsCanvasRenderingContext2D::FillRect(JsCallContext *context) {
-  double x, y, width, height;
+  if (SkParse::FindColor(new_style_as_utf8.c_str(), &color)) {
+    style_as_paint->setColor(color);
+    *style_as_string = new_style_as_string;
+  }
+}
+
+void GearsCanvasRenderingContext2D::GetStrokeStyle(JsCallContext *context) {
+  context->SetReturnValue(JSPARAM_STRING16, &stroke_style_as_string_);
+}
+
+void GearsCanvasRenderingContext2D::SetStrokeStyle(JsCallContext *context) {
+  SetStyle(context, &stroke_style_as_string_, &stroke_style_as_paint_);
+}
+
+void GearsCanvasRenderingContext2D::GetFillStyle(JsCallContext *context) {
+  context->SetReturnValue(JSPARAM_STRING16, &fill_style_as_string_);
+}
+
+void GearsCanvasRenderingContext2D::SetFillStyle(JsCallContext *context) {
+  SetStyle(context, &fill_style_as_string_, &fill_style_as_paint_);
+}
+
+void GearsCanvasRenderingContext2D::GetLineWidth(JsCallContext *context) {
+  double line_width = SkScalarToDouble(
+      stroke_style_as_paint_.getStrokeWidth());
+  context->SetReturnValue(JSPARAM_DOUBLE, &line_width);
+}
+
+void GearsCanvasRenderingContext2D::SetLineWidth(JsCallContext *context) {
+  double width;
+  JsArgument args[] = {
+    { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &width }
+  };
+  context->GetArguments(ARRAYSIZE(args), args);
+  if (context->is_exception_set())
+    return;
+
+  stroke_style_as_paint_.setStrokeWidth(SkDoubleToScalar(width));
+}
+
+void GearsCanvasRenderingContext2D::GetLineCap(JsCallContext *context) {
+  switch (stroke_style_as_paint_.getStrokeCap()) {
+    case SkPaint::kButt_Cap: {
+      std::string16 result(STRING16(L"butt"));
+      context->SetReturnValue(JSPARAM_STRING16, &result);
+      break;
+    }
+    case SkPaint::kRound_Cap: {
+      std::string16 result(STRING16(L"round"));
+      context->SetReturnValue(JSPARAM_STRING16, &result);
+      break;
+    }
+    case SkPaint::kSquare_Cap: {
+      std::string16 result(STRING16(L"square"));
+      context->SetReturnValue(JSPARAM_STRING16, &result);
+      break;
+    }
+    default:
+      // Do nothing.
+      break;
+  }
+}
+
+void GearsCanvasRenderingContext2D::SetLineCap(JsCallContext *context) {
+  std::string16 s;
+  JsArgument args[] = {
+    { JSPARAM_REQUIRED, JSPARAM_STRING16, &s }
+  };
+  context->GetArguments(ARRAYSIZE(args), args);
+  if (context->is_exception_set())
+    return;
+
+  if (s == STRING16(L"butt")) {
+    stroke_style_as_paint_.setStrokeCap(SkPaint::kButt_Cap);
+  } else if (s == STRING16(L"round")) {
+    stroke_style_as_paint_.setStrokeCap(SkPaint::kRound_Cap);
+  } else if (s == STRING16(L"square")) {
+    stroke_style_as_paint_.setStrokeCap(SkPaint::kSquare_Cap);
+  }
+}
+
+void GearsCanvasRenderingContext2D::GetLineJoin(JsCallContext *context) {
+  switch (stroke_style_as_paint_.getStrokeJoin()) {
+    case SkPaint::kMiter_Join: {
+      std::string16 result(STRING16(L"miter"));
+      context->SetReturnValue(JSPARAM_STRING16, &result);
+      break;
+    }
+    case SkPaint::kRound_Join: {
+      std::string16 result(STRING16(L"round"));
+      context->SetReturnValue(JSPARAM_STRING16, &result);
+      break;
+    }
+    case SkPaint::kBevel_Join: {
+      std::string16 result(STRING16(L"bevel"));
+      context->SetReturnValue(JSPARAM_STRING16, &result);
+      break;
+    }
+    default:
+      // Do nothing.
+      break;
+  }
+}
+
+void GearsCanvasRenderingContext2D::SetLineJoin(JsCallContext *context) {
+  std::string16 s;
+  JsArgument args[] = {
+    { JSPARAM_REQUIRED, JSPARAM_STRING16, &s }
+  };
+  context->GetArguments(ARRAYSIZE(args), args);
+  if (context->is_exception_set())
+    return;
+
+  if (s == STRING16(L"miter")) {
+    stroke_style_as_paint_.setStrokeJoin(SkPaint::kMiter_Join);
+  } else if (s == STRING16(L"round")) {
+    stroke_style_as_paint_.setStrokeJoin(SkPaint::kRound_Join);
+  } else if (s == STRING16(L"bevel")) {
+    stroke_style_as_paint_.setStrokeJoin(SkPaint::kBevel_Join);
+  }
+}
+
+void GearsCanvasRenderingContext2D::GetMiterLimit(JsCallContext *context) {
+  double miter_limit = SkScalarToDouble(
+      stroke_style_as_paint_.getStrokeMiter());
+  context->SetReturnValue(JSPARAM_DOUBLE, &miter_limit);
+}
+
+void GearsCanvasRenderingContext2D::SetMiterLimit(JsCallContext *context) {
+  double miter_limit;
+  JsArgument args[] = {
+    { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &miter_limit }
+  };
+  context->GetArguments(ARRAYSIZE(args), args);
+  if (context->is_exception_set())
+    return;
+
+  stroke_style_as_paint_.setStrokeMiter(SkDoubleToScalar(miter_limit));
+}
+
+void GearsCanvasRenderingContext2D::PaintRect(
+    JsCallContext *context,
+    SkPaint *paint) {
+  double x, y, w, h;
   JsArgument args[] = {
     { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &x },
     { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &y },
-    { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &width },
-    { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &height }
+    { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &w },
+    { JSPARAM_REQUIRED, JSPARAM_DOUBLE, &h }
   };
   context->GetArguments(ARRAYSIZE(args), args);
   if (context->is_exception_set())
@@ -358,22 +502,20 @@
 
   SkRect rect;
   rect.set(SkDoubleToScalar(x), SkDoubleToScalar(y),
-      SkDoubleToScalar(x + width), SkDoubleToScalar(y + height));
-  skia_canvas_->drawRect(rect, fill_style_as_paint_);
+      SkDoubleToScalar(x + w), SkDoubleToScalar(y + h));
+  skia_canvas_->drawRect(rect, *paint);
+}
+
+void GearsCanvasRenderingContext2D::ClearRect(JsCallContext *context) {
+  PaintRect(context, &clear_style_as_paint_);
+}
+
+void GearsCanvasRenderingContext2D::FillRect(JsCallContext *context) {
+  PaintRect(context, &fill_style_as_paint_);
 }
 
 void GearsCanvasRenderingContext2D::StrokeRect(JsCallContext *context) {
-  int x, y, width, height;
-  JsArgument args[] = {
-    { JSPARAM_REQUIRED, JSPARAM_INT, &x },
-    { JSPARAM_REQUIRED, JSPARAM_INT, &y },
-    { JSPARAM_REQUIRED, JSPARAM_INT, &width },
-    { JSPARAM_REQUIRED, JSPARAM_INT, &height }
-  };
-  context->GetArguments(ARRAYSIZE(args), args);
-  if (context->is_exception_set())
-    return;
-  context->SetException(STRING16(L"Unimplemented"));
+  PaintRect(context, &stroke_style_as_paint_);
 }
 
 void GearsCanvasRenderingContext2D::DrawImage(JsCallContext *context) {
==== 
//depot/googleclient/gears/opensource/gears/canvas/canvas_rendering_context_2d.h#14
 - 
/home/nigeltao/srcgears2/googleclient/gears/opensource/gears/canvas/canvas_rendering_context_2d.h
 ====
# action=edit type=text
--- googleclient/gears/opensource/gears/canvas/canvas_rendering_context_2d.h    
2009-03-03 17:05:37.000000000 +1100
+++ googleclient/gears/opensource/gears/canvas/canvas_rendering_context_2d.h    
2009-03-03 17:08:03.000000000 +1100
@@ -66,13 +66,13 @@
 
   // Sets the geometry transformation matrix to scale future drawing 
operations.
   // If only one scale argument is supplied, we use it for both dimensions.
-  // IN: double x, double y
+  // IN: float x, float y
   // OUT: -
   void Scale(JsCallContext *context);
 
   // Sets the geometry transformation matrix to rotate future drawing
   // operations by the given angle, in radians.
-  // IN: double angle
+  // IN: float angle
   // OUT: -
   void Rotate(JsCallContext *context);
 
@@ -82,29 +82,24 @@
   // OUT: -
   void Translate(JsCallContext *context);
 
-  // Multiplies the current geometry transformation matrix by the given
-  // matrix.
+  // Multiplies the current transformation matrix by the given matrix.
   // IN: float m11, float m12, float m21, float m22, float dx, float dy
   // OUT: -
   void Transform(JsCallContext *context);
 
-  // Sets the current geometry transformation matrix to the given matrix.
+  // Sets the current transformation matrix to the given matrix.
   // IN: float m11, float m12, float m21, float m22, float dx, float dy
   // OUT: -
   void SetTransform(JsCallContext *context);
-
-
-  // The following items constitute the state of the context.
-  // They affect future operations on the canvas.
 
   // Returns the current global alpha, which is used for future drawing
   // operations.
   // IN: -
-  // OUT: double
+  // OUT: float
   void GetGlobalAlpha(JsCallContext *context);
 
   // Sets the global alpha, which must be between 0.0 and 1.0.
-  // IN: double
+  // IN: float
   // OUT: -
   void SetGlobalAlpha(JsCallContext *context);
 
@@ -120,26 +115,28 @@
   // OUT: -
   void SetGlobalCompositeOperation(JsCallContext *context);
 
-  // Returns the current fill style, which is used for future drawing
-  // operations.
-  // IN: -
-  // OUT: string
+  // Basic getters / setters.
+  void GetStrokeStyle(JsCallContext *context);
+  void SetStrokeStyle(JsCallContext *context);
   void GetFillStyle(JsCallContext *context);
-
-  // Sets the fill style, which must be a valid CSS3 color specification.
-  // IN: string
-  // OUT: -
   void SetFillStyle(JsCallContext *context);
+  void GetLineWidth(JsCallContext *context);
+  void SetLineWidth(JsCallContext *context);
+  void GetLineCap(JsCallContext *context);
+  void SetLineCap(JsCallContext *context);
+  void GetLineJoin(JsCallContext *context);
+  void SetLineJoin(JsCallContext *context);
+  void GetMiterLimit(JsCallContext *context);
+  void SetMiterLimit(JsCallContext *context);
 
   // Rectangle operations.
-  // IN: int x, int y, int width, int height
-  // OUT: -
-  // Clears the specified rectangle (sets it to transparent black).
+  // IN: float x, float y, float width, float height
+  // OUT: -
+  // Clears the rectangle (sets it to transparent black).
   void ClearRect(JsCallContext *context);
-  // Fills the specified rectangle by the current fill color.
+  // Fills the rectangle with the current fill style.
   void FillRect(JsCallContext *context);
-  // Strokes the rectangle with a one-pixel think border.
-  // TODO(nigeltao): Define stroke color.
+  // Strokes the rectangle with the current stroke style.
   void StrokeRect(JsCallContext *context);
 
   // Draws a canvas onto this canvas. sx, sy, sw, and sh identify a rectangular
@@ -184,10 +181,26 @@
   // Callback used to handle the 'JSEVENT_UNLOAD' event.
   virtual void HandleEvent(JsEventType event_type);
 
+  // Implements ClearRect, FillRect and StrokeRect.
+  void PaintRect(JsCallContext *context, SkPaint *paint);
+
+  // Implements SetFillStyle and SetStrokeStyle.
+  void SetStyle(
+    JsCallContext *context,
+    std::string16 *style_as_string,
+    SkPaint *style_as_paint);
+
+  // Implements Transform and SetTransform.
+  void Transform(JsCallContext *context, bool reset_matrix);
+
   scoped_refptr<GearsCanvas> gears_canvas_;
   scoped_ptr<SkCanvas> skia_canvas_;
+
+  SkPaint clear_style_as_paint_;
+  SkPaint fill_style_as_paint_;
+  SkPaint stroke_style_as_paint_;
   std::string16 fill_style_as_string_;
-  SkPaint fill_style_as_paint_;
+  std::string16 stroke_style_as_string_;
 
   scoped_ptr<JsEventMonitor> unload_monitor_;
 
==== //depot/googleclient/gears/opensource/gears/test/manual/canvas.html#2 - 
/home/nigeltao/srcgears2/googleclient/gears/opensource/gears/test/manual/canvas.html
 ====
# action=edit type=text
--- googleclient/gears/opensource/gears/test/manual/canvas.html 2009-03-03 
17:05:38.000000000 +1100
+++ googleclient/gears/opensource/gears/test/manual/canvas.html 2009-03-03 
17:06:44.000000000 +1100
@@ -1,32 +1,76 @@
 <html><head><title>Gears Canvas</title></head>
-<body>
-<h1>Gears Canvas</h1>
-<img id="outputImg" width="100px" height="80px" style="border:1px solid black">
+<body style="background-color:#FFFFCF">
+<p>Gears' canvas:</p>
+<img id="gc" width="100px" height="80px" style="border:1px solid black">
+<hr>
+<p>Browser's native canvas:</p>
+<canvas id="bnc" width="100px" height="80px" style="border:1px solid black">
+  </canvas>
 <script type="text/javascript" src="../../sdk/gears_init.js"></script>
 <script type="text/javascript">
 
 
-var canvas = google.gears.factory.create('beta.canvas');
-canvas.width = 100;
-canvas.height = 80;
+function draw(c) {
+  // A canvas' default background is fully-transparent black (i.e., #00000000).
+  // However, IE6 doesn't render transparent PNGs particularly well. In that
+  // case, it looks better to initialize the canvas to fully-opaque white
+  // (i.e., #FFFFFFFF).
+  //c.fillStyle = 'white';
+  //c.fillRect(0, 0, 100, 80);
 
-var context = canvas.getContext('gears-2d');
-context.fillStyle = 'silver';
-context.fillRect(15, 25, 30, 30);
-context.rotate(0.3);
-context.fillStyle = '#3F00FF7F';
-context.fillRect(40,  0, 50, 50);
-context.rotate(-0.4);
-context.fillStyle = '#FF0000';
-context.fillRect(20, 20, 15, 15);
+  c.save();
+  c.scale(1.5, 1.5);
+  c.fillStyle = 'silver';
+  c.fillRect(5, 10, 30, 30);
+  c.restore();
 
-var localServer = google.gears.factory.create('beta.localserver');
-localServer.removeStore("test_manual_canvas");
-var store = localServer.createStore("test_manual_canvas");
+  c.rotate(0.3);
+  c.fillStyle = '#3F00FF7F';
+  c.fillRect(40,  0, 50, 50);
 
-var capturedUrl = parseInt(Math.random() * 1000) + '.png';
-store.captureBlob(canvas.toBlob(), capturedUrl, 'image/png');
-document.getElementById('outputImg').src = capturedUrl;
+  c.rotate(-0.4);
+  c.lineWidth = 4.5;
+  c.lineJoin = 'round';
+  c.strokeStyle = '#FF0000';
+  c.strokeRect(20, 20, 65, 15);
+
+  c.transform(1, 0.3, 0, 0.8, 7, 0);
+  c.clearRect(25, 25, 15, 15);
+}
+
+
+var gearsCanvas = null;
+try {
+  gearsCanvas = google.gears.factory.create('beta.canvas');
+} catch (e) {
+  // Silently ignore any exceptions for those Gears builds that don't have a
+  // canvas implementation.
+}
+if (gearsCanvas) {
+  gearsCanvas.width = 100;
+  gearsCanvas.height = 80;
+
+  draw(gearsCanvas.getContext('gears-2d'));
+
+  var localServer = google.gears.factory.create('beta.localserver');
+  localServer.removeStore("test_manual_canvas");
+  var store = localServer.createStore("test_manual_canvas");
+  var capturedUrl = parseInt(Math.random() * 1000) + '.png';
+  store.captureBlob(gearsCanvas.toBlob(), capturedUrl, 'image/png');
+  document.getElementById('gc').src = capturedUrl;
+}
+
+
+var nativeContext = null;
+try {
+  nativeContext = document.getElementById('bnc').getContext('2d');
+} catch (e) {
+  // Silently ignore any exceptions for those browsers that don't have a
+  // native canvas implementation.
+}
+if (nativeContext) {
+  draw(nativeContext);
+}
 
 
 </script>

Reply via email to