Author: spouliot
Date: 2007-10-18 10:06:32 -0400 (Thu, 18 Oct 2007)
New Revision: 87748

Removed:
   trunk/moon/src/rsvg.cpp
   trunk/moon/src/rsvg.h
Modified:
   trunk/moon/src/ChangeLog
   trunk/moon/src/Makefile.am
   trunk/moon/src/geometry.cpp
   trunk/moon/src/libmoon.h
Log:
2007-10-18  Sebastien Pouliot  <[EMAIL PROTECTED]>

        * geometry.cpp: New code to handle arc segments. No known issues
        (except the handling of near zero values which doesn't seems to
        be constant).
        * libmoon.h, Makefile.am: Remove reference to rsvg.h
        * rsvg.cpp|h: Remove from SVN.



Modified: trunk/moon/src/ChangeLog
===================================================================
--- trunk/moon/src/ChangeLog    2007-10-18 12:27:08 UTC (rev 87747)
+++ trunk/moon/src/ChangeLog    2007-10-18 14:06:32 UTC (rev 87748)
@@ -1,3 +1,11 @@
+2007-10-18  Sebastien Pouliot  <[EMAIL PROTECTED]>
+
+       * geometry.cpp: New code to handle arc segments. No known issues
+       (except the handling of near zero values which doesn't seems to
+       be constant).
+       * libmoon.h, Makefile.am: Remove reference to rsvg.h
+       * rsvg.cpp|h: Remove from SVN.
+
 2007-10-17  Andrew Jorgensen  <[EMAIL PROTECTED]>
 
        * cairo-embed.h, pixman-embed.h: Added symbol renaming headers

Modified: trunk/moon/src/Makefile.am
===================================================================
--- trunk/moon/src/Makefile.am  2007-10-18 12:27:08 UTC (rev 87747)
+++ trunk/moon/src/Makefile.am  2007-10-18 14:06:32 UTC (rev 87748)
@@ -37,7 +37,6 @@
        playlist.h      \
        point.h         \
        rect.h          \
-       rsvg.h          \
        runtime.h       \
        shape.h         \
        stylus.h        \
@@ -83,7 +82,6 @@
        point.cpp       \
        playlist.cpp    \
        rect.cpp        \
-       rsvg.cpp        \
        runtime.cpp     \
        shape.cpp       \
        stylus.cpp      \

Modified: trunk/moon/src/geometry.cpp
===================================================================
--- trunk/moon/src/geometry.cpp 2007-10-18 12:27:08 UTC (rev 87747)
+++ trunk/moon/src/geometry.cpp 2007-10-18 14:06:32 UTC (rev 87748)
@@ -24,8 +24,6 @@
 #include "shape.h"
 #include "array.h"
 
-#include "rsvg.h"
-
 //
 // Geometry
 //
@@ -1010,17 +1008,181 @@
        segment->SetValue (ArcSegment::SweepDirectionProperty, Value 
(direction));
 }
 
+// is it true only for arcs or for everything ? if so using the same values ?
+#define IS_ZERO(x)     (fabs(x) < 0.000019)
+#define IS_TOO_SMALL(x)        (fabs(x) < 0.000117)
+
 void
 ArcSegment::Append (moon_path *path)
 {
+       // from tests it seems that Silverlight closely follows SVG arc 
+       // behavior (which is very different from the model used with GDI+)
+       // some helpful stuff is available here:
+       // http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
+
+       // get start point from the existing path
+       double sx, sy;
+       moon_get_current_point (path, &sx, &sy);
+       // end point
+       Point* ep = arc_segment_get_point (this);
+
+       // if start and end points are identical, then no arc is drawn
+       // FIXME: what's the logic (if any) to compare points
+       // e.g. 60 and 60.000002 are drawn while 80 and 80.000003 aren't
+       if (IS_ZERO (ep->x - sx) && IS_ZERO (ep->y - sy))
+               return;
+
        Point *size = arc_segment_get_size (this);
-       double angle = arc_segment_get_rotation_angle (this);
-       int large = arc_segment_get_is_large_arc (this) ? 1 : 0;
-       int direction = arc_segment_get_sweep_direction (this) == 
SweepDirectionCounterclockwise ? 0 : 1;
-       Point* p = arc_segment_get_point (this);
+       // Correction of out-of-range radii, see F6.6 (step 1)
+       if (IS_ZERO (size->x) || IS_ZERO (size->y)) {
+               // treat this as a straight line (to end point)
+               moon_line_to (path, ep->x, ep->y);
+               return;
+       }
 
-       // FIXME: there's no cairo_arc_to so we reuse librsvg code (see 
rsvg.cpp)
-       rsvg_arc_to (path, size->x, size->y, angle, large, direction, p->x, 
p->y); 
+       // Silverlight "too small to be useful"
+       if (IS_TOO_SMALL (size->x) || IS_TOO_SMALL (size->y)) {
+               // yes it does mean there's a hole between "normal" FP values 
and "zero" FP values
+               // and SL doesn't render anything in this twilight sonze
+               return;
+       }
+
+       // Correction of out-of-range radii, see F6.6.1 (step 2)
+       double rx = fabs (size->x);
+       double ry = fabs (size->y);
+
+       // convert angle into radians
+       double angle = arc_segment_get_rotation_angle (this) * M_PI / 180.0;
+
+       // variables required for F6.3.1
+       double cos_phi = cos (angle);
+       double sin_phi = sin (angle);
+       double dx2 = (sx - ep->x) / 2.0;
+       double dy2 = (sy - ep->y) / 2.0;
+       double x1p = cos_phi * dx2 + sin_phi * dy2;
+       double y1p = cos_phi * dy2 - sin_phi * dx2;
+       double x1p2 = x1p * x1p;
+       double y1p2 = y1p * y1p;
+       double rx2 = rx * rx;
+       double ry2 = ry * ry;
+
+       // Correction of out-of-range radii, see F6.6.2 (step 4)
+       double lambda = (x1p2 / rx2) + (y1p2 / ry2);
+       if (lambda > 1.0) {
+               // see F6.6.3
+               double lambda_root = sqrt (lambda);
+               rx *= lambda_root;
+               ry *= lambda_root;
+               // update rx2 and ry2
+               rx2 = rx * rx;
+               ry2 = ry * ry;
+       }
+
+       bool sweep = arc_segment_get_sweep_direction (this);
+       double cxp, cyp, cx, cy;
+       double c = (rx2 * ry2) - (rx2 * y1p2) - (ry2 * x1p2);
+
+       // check if there is no possible solution (i.e. we can't do a square 
root of a negative value)
+       if (c < 0.0) {
+               // scale uniformly until we have a single solution (see F6.2) 
i.e. when c == 0.0
+               double scale = sqrt (1.0 - c / (rx2 * ry2));
+               rx *= scale;
+               ry *= scale;
+               // update rx2 and ry2
+               rx2 = rx * rx;
+               ry2 = ry * ry;
+
+               // step 2 (F6.5.2) - simplified since c == 0.0
+               cxp = 0.0;
+               cyp = 0.0;
+
+               // step 3 (F6.5.3 first part) - simplified since cxp and cyp == 
0.0
+               cx = 0.0;
+               cy = 0.0;
+       } else {
+               // complete c calculation
+               c = sqrt (c / ((rx2 * y1p2) + (ry2 * x1p2)));
+
+               // inverse sign if Fa == Fs
+               if (arc_segment_get_is_large_arc (this) == sweep)
+                       c = -c;
+
+               // step 2 (F6.5.2)
+               cxp = c * ( rx * y1p / ry);
+               cyp = c * (-ry * x1p / rx);
+
+               // step 3 (F6.5.3 first part)
+               cx = cos_phi * cxp - sin_phi * cyp;
+               cy = sin_phi * cxp + cos_phi * cyp;
+       }
+
+       // step 3 (F6.5.3 second part) we now have the center point of the 
ellipse
+       cx += (sx + ep->x) / 2.0;
+       cy += (sy + ep->y) / 2.0;
+
+       // step 4 (F6.5.4)
+       // we dont' use arccos (as per w3c doc), see 
http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm
+       // note: atan2 (0.0, 1.0) == 0.0
+       double at = atan2 (((y1p - cyp) / ry), ((x1p - cxp) / rx));
+       double theta1 = (at < 0.0) ? 2.0 * M_PI + at : at;
+
+       double nat = atan2 (((-y1p - cyp) / ry), ((-x1p - cxp) / rx));
+       double delta_theta = (nat < at) ? 2.0 * M_PI - at + nat : nat - at;
+
+       if (sweep) {
+               // ensure delta theta < 0 or else add 360 degrees
+               if (delta_theta < 0.0)
+                       delta_theta += 2.0 * M_PI;
+       } else {
+               // ensure delta theta > 0 or else substract 360 degrees
+               if (delta_theta > 0.0)
+                       delta_theta -= 2.0 * M_PI;
+       }
+
+       // add several cubic bezier to approximate the arc (smaller than 90 
degrees)
+       // we add one extra segment because we want something smaller than 
90deg (i.e. not 90 itself)
+       int segments = (int) (fabs (delta_theta / M_PI_2)) + 1;
+       double delta = delta_theta / segments;
+
+       // http://www.stillhq.com/ctpfaq/2001/comp.text.pdf-faq-2001-04.txt 
(section 2.13)
+       double bcp = 4.0 / 3 * (1 - cos (delta / 2)) / sin (delta / 2);
+
+       double cos_phi_rx = cos_phi * rx;
+       double cos_phi_ry = cos_phi * ry;
+       double sin_phi_rx = sin_phi * rx;
+       double sin_phi_ry = sin_phi * ry;
+
+       double cos_theta1 = cos (theta1);
+       double sin_theta1 = sin (theta1);
+
+       for (int i = 0; i < segments; ++i) {
+               // end angle (for this segment) = current + delta
+               double theta2 = theta1 + delta;
+               double cos_theta2 = cos (theta2);
+               double sin_theta2 = sin (theta2);
+
+               // first control point (based on start point sx,sy)
+               double c1x = sx - bcp * (cos_phi_rx * sin_theta1 + sin_phi_ry * 
cos_theta1);
+               double c1y = sy + bcp * (cos_phi_ry * cos_theta1 - sin_phi_rx * 
sin_theta1);
+
+               // end point (for this segment)
+               double ex = cx + (cos_phi_rx * cos_theta2 - sin_phi_ry * 
sin_theta2);
+               double ey = cy + (sin_phi_rx * cos_theta2 + cos_phi_ry * 
sin_theta2);
+
+               // second control point (based on end point ex,ey)
+               double c2x = ex + bcp * (cos_phi_rx * sin_theta2 + sin_phi_ry * 
cos_theta2);
+               double c2y = ey + bcp * (sin_phi_rx * sin_theta2 - cos_phi_ry * 
cos_theta2);
+
+               moon_curve_to (path, c1x, c1y, c2x, c2y, ex, ey);
+
+               // next start point is the current end point (same for angle)
+               sx = ex;
+               sy = ey;
+               theta1 = theta2;
+               // avoid recomputations
+               cos_theta1 = cos_theta2;
+               sin_theta1 = sin_theta2;
+       }
 }
 
 //

Modified: trunk/moon/src/libmoon.h
===================================================================
--- trunk/moon/src/libmoon.h    2007-10-18 12:27:08 UTC (rev 87747)
+++ trunk/moon/src/libmoon.h    2007-10-18 14:06:32 UTC (rev 87748)
@@ -31,7 +31,6 @@
 #include "playlist.h"
 #include "point.h"
 #include "rect.h"
-#include "rsvg.h"
 #include "runtime.h"
 #include "shape.h"
 #include "stylus.h"

Deleted: trunk/moon/src/rsvg.cpp
===================================================================
--- trunk/moon/src/rsvg.cpp     2007-10-18 12:27:08 UTC (rev 87747)
+++ trunk/moon/src/rsvg.cpp     2007-10-18 14:06:32 UTC (rev 87748)
@@ -1,141 +0,0 @@
-/* This is (modified) LGPL code from librsvg 2.16.1
-
-   Copyright (C) 2000 Eazel, Inc.
-  
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-  
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-  
-   You should have received a copy of the GNU Library General Public
-   License along with this program; if not, write to the
-   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.
-  
-   Author: Raph Levien <[EMAIL PROTECTED]>
-*/
-
-#include <config.h>
-#include <glib.h>
-#include <math.h>
-#include <cairo.h>
-#include "rsvg.h"
-
-static void
-rsvg_path_arc_segment (moon_path *path,
-                     double xc, double yc,
-                     double th0, double th1,
-                     double rx, double ry, double x_axis_rotation)
-{
-  double sin_th, cos_th;
-  double a00, a01, a10, a11;
-  double x1, y1, x2, y2, x3, y3;
-  double t;
-  double th_half;
-
-  sin_th = sin (x_axis_rotation * (M_PI / 180.0));
-  cos_th = cos (x_axis_rotation * (M_PI / 180.0)); 
-  /* inverse transform compared with rsvg_path_arc */
-  a00 = cos_th * rx;
-  a01 = -sin_th * ry;
-  a10 = sin_th * rx;
-  a11 = cos_th * ry;
-
-  th_half = 0.5 * (th1 - th0);
-  t = (8.0 / 3.0) * sin (th_half * 0.5) * sin (th_half * 0.5) / sin (th_half);
-  x1 = xc + cos (th0) - t * sin (th0);
-  y1 = yc + sin (th0) + t * cos (th0);
-  x3 = xc + cos (th1);
-  y3 = yc + sin (th1);
-  x2 = x3 + t * sin (th1);
-  y2 = y3 - t * cos (th1);
-  moon_curve_to (path,
-                                 a00 * x1 + a01 * y1, a10 * x1 + a11 * y1,
-                                 a00 * x2 + a01 * y2, a10 * x2 + a11 * y2,
-                                 a00 * x3 + a01 * y3, a10 * x3 + a11 * y3);
-}
-
-/**
- * rsvg_path_arc: Add an RSVG arc to the path context.
- * @ctx: Path context.
- * @rx: Radius in x direction (before rotation).
- * @ry: Radius in y direction (before rotation).
- * @x_axis_rotation: Rotation angle for axes.
- * @large_arc_flag: 0 for arc length <= 180, 1 for arc >= 180.
- * @sweep: 0 for "negative angle", 1 for "positive angle".
- * @x: New x coordinate.
- * @y: New y coordinate.
- *
- **/
-void
-rsvg_arc_to (moon_path *path, double rx, double ry, double x_axis_rotation, 
int large_arc_flag, int sweep_flag,
-       double x, double y)
-{
-  double sin_th, cos_th;
-  double a00, a01, a10, a11;
-  double x0, y0, x1, y1, xc, yc;
-  double d, sfactor, sfactor_sq;
-  double th0, th1, th_arc;
-  int i, n_segs;
-
-  /* Check that neither radius is zero, since its isn't either
-     geometrically or mathematically meaningful and will
-     cause divide by zero and subsequent NaNs.  We should
-     really do some ranged check ie -0.001 < x < 000.1 rather
-     can just a straight check again zero.
-  */
-  if ((rx == 0.0) || (ry == 0.0)) return;
-
-  sin_th = sin (x_axis_rotation * (M_PI / 180.0));
-  cos_th = cos (x_axis_rotation * (M_PI / 180.0));
-  a00 = cos_th / rx;
-  a01 = sin_th / rx;
-  a10 = -sin_th / ry;
-  a11 = cos_th / ry;
-
-       double cpx, cpy;
-       moon_get_current_point (path, &cpx, &cpy);
-
-  x0 = a00 * cpx + a01 * cpy;
-  y0 = a10 * cpx + a11 * cpy;
-  x1 = a00 * x + a01 * y;
-  y1 = a10 * x + a11 * y;
-  /* (x0, y0) is current point in transformed coordinate space.
-     (x1, y1) is new point in transformed coordinate space.
-
-     The arc fits a unit-radius circle in this space.
-  */
-  d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
-  sfactor_sq = 1.0 / d - 0.25;
-  if (sfactor_sq < 0) sfactor_sq = 0;
-  sfactor = sqrt (sfactor_sq);
-  if (sweep_flag == large_arc_flag) sfactor = -sfactor;
-  xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
-  yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
-  /* (xc, yc) is center of the circle. */
-
-  th0 = atan2 (y0 - yc, x0 - xc);
-  th1 = atan2 (y1 - yc, x1 - xc);
-
-  th_arc = th1 - th0;
-  if (th_arc < 0 && sweep_flag)
-    th_arc += 2 * M_PI;
-  else if (th_arc > 0 && !sweep_flag)
-    th_arc -= 2 * M_PI;
-
-  n_segs = (int)ceil (fabs (th_arc / (M_PI * 0.5 + 0.001)));
-
-  for (i = 0; i < n_segs; i++)
-    rsvg_path_arc_segment (path, xc, yc,
-                         th0 + i * th_arc / n_segs,
-                         th0 + (i + 1) * th_arc / n_segs,
-                         rx, ry, x_axis_rotation);
-
-//  ctx->cpx = x;
-//  ctx->cpy = y;
-}

Deleted: trunk/moon/src/rsvg.h
===================================================================
--- trunk/moon/src/rsvg.h       2007-10-18 12:27:08 UTC (rev 87747)
+++ trunk/moon/src/rsvg.h       2007-10-18 14:06:32 UTC (rev 87748)
@@ -1,35 +0,0 @@
-/* This is (modified) LGPL code from librsvg 2.16.1
-
-   Copyright (C) 2000 Eazel, Inc.
-  
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-  
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-  
-   You should have received a copy of the GNU Library General Public
-   License along with this program; if not, write to the
-   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.
-  
-   Author: Raph Levien <[EMAIL PROTECTED]>
-*/
-
-#ifndef __RSVG_H__
-#define __RSVG_H__
-
-#include "moon-path.h"
-
-G_BEGIN_DECLS
-
-void rsvg_arc_to (moon_path *path, double rx, double ry, double 
x_axis_rotation, int large_arc_flag, int sweep_flag,
-       double x, double y);
-
-G_END_DECLS
-
-#endif

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

Reply via email to