Author: spouliot
Date: 2008-01-23 13:55:50 -0500 (Wed, 23 Jan 2008)
New Revision: 93688

Modified:
   trunk/moon/src/ChangeLog
   trunk/moon/src/shape.cpp
   trunk/moon/src/shape.h
Log:
2008-01-23  Sebastien Pouliot  <[EMAIL PROTECTED]>

        * shape.cpp|h: Add support for different PenLineCap on Line (part 
        of #345888). Fix Polyline when a single segment is used (removed 
        TODO). Avoid extra work when a start/end PenLineCap is Flat (default)



Modified: trunk/moon/src/ChangeLog
===================================================================
--- trunk/moon/src/ChangeLog    2008-01-23 18:45:54 UTC (rev 93687)
+++ trunk/moon/src/ChangeLog    2008-01-23 18:55:50 UTC (rev 93688)
@@ -1,3 +1,9 @@
+2008-01-23  Sebastien Pouliot  <[EMAIL PROTECTED]>
+
+       * shape.cpp|h: Add support for different PenLineCap on Line (part 
+       of #345888). Fix Polyline when a single segment is used (removed 
+       TODO). Avoid extra work when a start/end PenLineCap is Flat (default)
+
 2008-01-23  Jeffrey Stedfast  <[EMAIL PROTECTED]>
 
        * media.cpp (SetSource): Initialize the ProgressiveSource.

Modified: trunk/moon/src/shape.cpp
===================================================================
--- trunk/moon/src/shape.cpp    2008-01-23 18:45:54 UTC (rev 93687)
+++ trunk/moon/src/shape.cpp    2008-01-23 18:55:50 UTC (rev 93688)
@@ -1050,6 +1050,63 @@
 DependencyProperty* Line::X2Property;
 DependencyProperty* Line::Y2Property;
 
+#define LINECAP_SMALL_OFFSET   0.1
+
+// Draw the start and end line caps, if not flat. This doesn't draw the line 
itself
+// note: function shared with single-segment Polyline
+static void
+line_draw_caps (cairo_t *cr, Shape* shape, double x1, double y1, PenLineCap 
start, double x2, double y2, PenLineCap end)
+{
+       double sx1, sx2, sy1, sy2;
+       if (x1 == x2) {
+               // vertical line
+               sx1 = x1;
+               sx2 = x2;
+               if (y1 > y2) {
+                       sy1 = y1 + LINECAP_SMALL_OFFSET;
+                       sy2 = y2 - LINECAP_SMALL_OFFSET;
+               } else {
+                       sy1 = y1 - LINECAP_SMALL_OFFSET;
+                       sy2 = y2 + LINECAP_SMALL_OFFSET;
+               }
+       } else if (y1 == y2) {
+               // horizontal line
+               sy1 = y1;
+               sy2 = y2;
+               if (x1 > x2) {
+                       sx1 = x1 + LINECAP_SMALL_OFFSET;
+                       sx2 = x2 - LINECAP_SMALL_OFFSET;
+               } else {
+                       sx1 = x1 - LINECAP_SMALL_OFFSET;
+                       sx2 = x2 + LINECAP_SMALL_OFFSET;
+               }
+       } else {
+               double m = fabs ((y1 - y2) / (x1 - x2));
+               if (x1 > x2) {
+                       sx1 = x1 + LINECAP_SMALL_OFFSET;
+                       sx2 = x2 - LINECAP_SMALL_OFFSET;
+               } else {
+                       sx1 = x1 - LINECAP_SMALL_OFFSET;
+                       sx2 = x2 + LINECAP_SMALL_OFFSET;
+               }
+               sy1 = m * sx1 + y1 - (m * x1);
+               sy2 = m * sx2 + y2 - (m * x2);
+       }
+
+       if (start != PenLineCapFlat) {
+               cairo_set_line_cap (cr, convert_line_cap (start));
+               cairo_move_to (cr, x1, y1);
+               cairo_line_to (cr, sx1, sy1);
+               shape->Stroke (cr, true);
+       }
+       if (end != PenLineCapFlat) {
+               cairo_set_line_cap (cr, convert_line_cap (end));
+               cairo_move_to (cr, x2, y2);
+               cairo_line_to (cr, sx2, sy2);
+               shape->Stroke (cr, true);
+       }
+}
+
 // The Line shape can be drawn while ignoring properties:
 // * Shape::StrokeLineJoin
 // * Shape::StrokeMiterLimit
@@ -1063,8 +1120,20 @@
 
        if (!SetupLine (cr))
                return false;
-       SetupLineCaps (cr);
 
+       // here we hack around #345888 where Cairo doesn't support different 
start and end linecaps
+       PenLineCap start = shape_get_stroke_start_line_cap (this);
+       PenLineCap end = shape_get_stroke_end_line_cap (this);
+       if (do_op && (start != end)) {
+               // draw start and end line caps
+               line_draw_caps (cr, this, line_get_x1 (this), line_get_y1 
(this), start, 
+                       line_get_x2 (this), line_get_y2 (this), end);
+
+               cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
+       } else {
+               cairo_set_line_cap (cr, convert_line_cap (start));
+       }
+
        Draw (cr);
        Stroke (cr, do_op);
        return true; 
@@ -1633,22 +1702,25 @@
 
                cairo_path_data_t *data = path->cairo.data;
                int length = path->cairo.num_data;
-               // we need to treat a single line scenario differently (like 
Line::DrawShape)
-               if (length <= MOON_PATH_MOVE_TO_LENGTH + 
MOON_PATH_LINE_TO_LENGTH) {
-                       // note: this means either no, one or two points
-// TODO (right now a straight line is drawn (without caps)
-               } else {
+               // single point polylines are not rendered
+               if (length == MOON_PATH_MOVE_TO_LENGTH + 
MOON_PATH_LINE_TO_LENGTH) {
+                       // draw a single line
+                       line_draw_caps (cr, this, data[1].point.x, 
data[1].point.y, start, data[3].point.x, data[3].point.y, end);
+               } else if (length > MOON_PATH_MOVE_TO_LENGTH + 
MOON_PATH_LINE_TO_LENGTH) {
                        // draw line #1 with start cap
-                       cairo_set_line_cap (cr, convert_line_cap (start));
-                       cairo_move_to (cr, data[1].point.x, data[1].point.y);
-                       cairo_line_to (cr, data[3].point.x, data[3].point.y);
-                       Stroke (cr, do_op);
-
+                       if (start != PenLineCapFlat) {
+                               cairo_set_line_cap (cr, convert_line_cap 
(start));
+                               cairo_move_to (cr, data[1].point.x, 
data[1].point.y);
+                               cairo_line_to (cr, data[3].point.x, 
data[3].point.y);
+                               Stroke (cr, true);
+                       }
                        // draw last line with end cap
-                       cairo_set_line_cap (cr, convert_line_cap (end));
-                       cairo_move_to (cr, data[length - 3].point.x, 
data[length - 3].point.y);
-                       cairo_line_to (cr, data[length - 1].point.x, 
data[length - 1].point.y);
-                       Stroke (cr, do_op);
+                       if (end != PenLineCapFlat) {
+                               cairo_set_line_cap (cr, convert_line_cap (end));
+                               cairo_move_to (cr, data[length - 3].point.x, 
data[length - 3].point.y);
+                               cairo_line_to (cr, data[length - 1].point.x, 
data[length - 1].point.y);
+                               Stroke (cr, true);
+                       }
                }
 
                // now all lines (including first and last) will be drawn with 
no caps

Modified: trunk/moon/src/shape.h
===================================================================
--- trunk/moon/src/shape.h      2008-01-23 18:45:54 UTC (rev 93687)
+++ trunk/moon/src/shape.h      2008-01-23 18:55:50 UTC (rev 93688)
@@ -3,8 +3,9 @@
  *
  * Author:
  *   Miguel de Icaza ([EMAIL PROTECTED])
+ *   Sebastien Pouliot  <[EMAIL PROTECTED]>
  *
- * Copyright 2007 Novell, Inc. (http://www.novell.com)
+ * Copyright 2007-2008 Novell, Inc. (http://www.novell.com)
  *
  * See the LICENSE file included with the distribution for details.
  * 
@@ -41,7 +42,6 @@
        virtual bool SetupLine (cairo_t* cr);
        bool SetupDashes (cairo_t *cr, double thickness);
        bool Fill (cairo_t *cr, bool do_op);
-       void Stroke (cairo_t *cr, bool do_op);
        void Clip (cairo_t *cr);
        virtual bool DrawShape (cairo_t *cr, bool do_op) = 0;
 //     virtual bool DrawDegenerateShape (cairo_t *cr, bool do_op) = 0;
@@ -92,6 +92,7 @@
        virtual void Draw (cairo_t *cr);
        virtual void BuildPath () {};
        virtual bool ClipOnHeightAndWidth () { return false; }
+       void Stroke (cairo_t *cr, bool do_op);
        bool NeedsClipping ();
        bool MixedHeightWidth (Value **width, Value **height);
 

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to