Author: spouliot
Date: 2006-06-07 10:04:06 -0400 (Wed, 07 Jun 2006)
New Revision: 61528

Modified:
   trunk/libgdiplus/src/ChangeLog
   trunk/libgdiplus/src/graphics-path.c
   trunk/libgdiplus/src/graphics-path.h
Log:
graphics-path.c|h: Implemented GdipIsOutlineVisiblePathPoint[I] functions 
(except for some cases where a GpGraphics is supplied).

Modified: trunk/libgdiplus/src/ChangeLog
===================================================================
--- trunk/libgdiplus/src/ChangeLog      2006-06-07 14:00:46 UTC (rev 61527)
+++ trunk/libgdiplus/src/ChangeLog      2006-06-07 14:04:06 UTC (rev 61528)
@@ -1,3 +1,8 @@
+2006-06-07  Sebastien Pouliot  <[EMAIL PROTECTED]>
+
+       * graphics-path.c|h: Implemented GdipIsOutlineVisiblePathPoint[I]
+       functions (except for some cases where a GpGraphics is supplied).
+
 2006-06-06  Sebastien Pouliot  <[EMAIL PROTECTED]>
 
        * graphics-path.c|h: Fix declarations (missing GpPen parameter) for 

Modified: trunk/libgdiplus/src/graphics-path.c
===================================================================
--- trunk/libgdiplus/src/graphics-path.c        2006-06-07 14:00:46 UTC (rev 
61527)
+++ trunk/libgdiplus/src/graphics-path.c        2006-06-07 14:04:06 UTC (rev 
61528)
@@ -1751,28 +1751,111 @@
        return Ok;
 }
 
-/* MonoTODO */
+static BOOL
+gdip_check_point_within_distance (float x0, float y0, GpPointF *p1, GpPointF 
*p2, float distance)
+{
+       float x1 = p1->X;
+       float y1 = p1->Y;
+       float x2 = p2->X;
+       float y2 = p2->Y;
+       float x2x1, y2y1;
+
+       /* quick out (to avoid heavy calculations) for out of range points */
+       if ((x0 < min (x1, x2) - distance) || (x0 > max (x1, x2) + distance) ||
+               (y0 < min (y1, y2) - distance) || (y0 > max (y1, y2) + 
distance))
+               return FALSE;
+
+       /* close enough, do the full math */
+       x2x1 = x2 - x1;
+       y2y1 = y2 - y1;
+       /* if the provided line is a point (simpler calculation and avoids a 
division by zero) */
+       if ((x2x1 == 0.0) && (y2y1 == 0.0)) {
+               /* check distance between two points */
+               /* ref: 
http://mathworld.wolfram.com/Point-PointDistance2-Dimensional.html */
+               float x1x0 = x1 - x0;
+               float y1y0 = y1 - y0;
+               return (sqrt ((x1x0 * x1x0) + (y1y0 * y1y0)) <= distance);
+       } else {
+               /* normal case: distance of a point to a line */
+               /* ref: 
http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html */
+               float d1 = fabs ((x2x1 * (y1 - y0)) - ((x1 - x0) * y2y1));
+               float d2 = sqrt ((x2x1 * x2x1) + (y2y1 * y2y1));
+               return (d1 / d2 <= distance);
+       }
+}
+
+/* MonoTODO - GpGraphics is ignored */
 GpStatus 
 GdipIsOutlineVisiblePathPoint (GpPath *path, float x, float y, GpPen *pen, 
GpGraphics *graphics, bool *result)
 {
-       static int called = 0;
+       GpStatus status = Ok;
+       GpPath *workpath;
 
-       if (!called) {
-               printf("NOT IMPLEMENTED: GdipIsOutlineVisiblePathPoint (GpPath 
*path, float x, float y, GpPen *pen, GpGraphics *graphics, bool *result)\n");
-               called = 1;
+       if (!path || !pen || !result)
+               return InvalidParameter;
+
+       *result = FALSE;
+
+       if (path->count < 2) {
+               /* FIXME - equality check ? */
+               return Ok;
        }
-       return Ok;
+
+       /* we clone the supplied path if it contains curves (we only deal with 
lines) */
+       if (gdip_path_has_curve (path)) {
+               status = GdipClonePath (path, &workpath);
+               if (status != Ok)
+                       return status;
+
+               status = GdipFlattenPath (workpath, NULL, 25.0f);
+       } else {
+               workpath = path;
+       }
+
+       if (graphics) {
+               /* FIXME - graphics isn't always ignored, e.g. when we set the 
matrix, pageunit and pagescale */
+       }
+
+       if (status == Ok) {
+               /* check if the supplied point is within half the pen's width 
of any path segment */
+               float half_width = pen->width / 2;
+               int start_index = 0;
+               int i;
+               byte type = 0;
+
+               GpPointF p1 = g_array_index (workpath->points, GpPointF, 0);
+               GpPointF p2;
+
+               for (i = 1; i < path->count && !*result; i++) {
+                       /* check the line between the previous point and this 
point */
+                       p2 = g_array_index (workpath->points, GpPointF, i);
+                       *result = gdip_check_point_within_distance (x, y, &p1, 
&p2, half_width);
+
+                       /* check for closure (to match with the last starting 
point) */
+                       type = g_array_index (path->types, byte, i);
+                       if (!*result && (type & PathPointTypeCloseSubpath)) {
+                               p1 = g_array_index (workpath->points, GpPointF, 
start_index);
+                               /* compare last point with first (if the path 
is closed) */
+                               *result = gdip_check_point_within_distance (x, 
y, &p2, &p1, half_width);
+                       }
+
+                       /* switch point for the next line */
+                       p1 = p2;
+
+                       /* reset the start index */
+                       if (type == PathPointTypeStart)
+                               start_index = i;
+               }
+       }
+
+       if (workpath != path)
+               GdipDeletePath (workpath);
+       return status;
 }
 
-/* MonoTODO */
+/* MonoTODO - GpGraphics is ignored */
 GpStatus 
 GdipIsOutlineVisiblePathPointI (GpPath *path, int x, int y, GpPen *pen, 
GpGraphics *graphics, bool *result)
 {
-       static int called = 0;
-
-       if (!called) {
-               printf("NOT IMPLEMENTED: GdipIsOutlineVisiblePathPointI (GpPath 
*path, int x, int y, GpPen *pen, GpGraphics *graphics, bool *result)\n");
-               called = 1;
-       }
-       return Ok;
+       return GdipIsOutlineVisiblePathPoint (path, x, y, pen, graphics, 
result);
 }

Modified: trunk/libgdiplus/src/graphics-path.h
===================================================================
--- trunk/libgdiplus/src/graphics-path.h        2006-06-07 14:00:46 UTC (rev 
61527)
+++ trunk/libgdiplus/src/graphics-path.h        2006-06-07 14:04:06 UTC (rev 
61528)
@@ -14,6 +14,9 @@
 
 #include "gdip.h"
 
+#define min(a,b)       (a < b ? a : b)
+#define max(a,b)       (a > b ? a : b)
+
 #define FLATTEN_RECURSION_LIMIT                10
 
 GpStatus GdipCreatePath (GpFillMode brushMode, GpPath **path);

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

Reply via email to