[haiku-webkit-commits] r327 - webkit/trunk/WebCore/platform/graphics/haiku

  • From: webkit@xxxxxxxxxxxxxxx
  • To: haiku-webkit-commits@xxxxxxxxxxxxx
  • Date: Fri, 19 Mar 2010 01:35:08 +0000

Author: stippi
Date: Fri Mar 19 01:35:08 2010
New Revision: 327
URL: http://mmlr.dyndns.org/changeset/327

Log:
* Cleanup in the existing BShapeIterators, the BShape does not need to be
   passed.
 * Handling of the new IterateArcTo().
 * Implemented addEllipse() via Bezier curves.
 * Implemented addArcTo(). Pretty much copy&paste from the Qt version. The
   GTK implementation has the exact same code. Not sure about copyright, I've
   added Dirk Schulze for now, the GTK port also mentions him. I've tried to
   track revision history, but I am not 100% sure still. Needs coding style
   cleanup.
 * addArcTo() calls addArc(), which could now be implemented with the new
   BShape features. So far, my testing shows that at least the edge-case of
   drawing a full ellipse works. I believe the actual arc implementation to
   be correct, following the documentation of QPainterPath::arcTo() and what
   the Qt port does.
 * Implemented the apply() method.

Modified:
   webkit/trunk/WebCore/platform/graphics/haiku/PathHaiku.cpp

Modified: webkit/trunk/WebCore/platform/graphics/haiku/PathHaiku.cpp
==============================================================================
--- webkit/trunk/WebCore/platform/graphics/haiku/PathHaiku.cpp  Fri Mar 19 
01:29:25 2010        (r326)
+++ webkit/trunk/WebCore/platform/graphics/haiku/PathHaiku.cpp  Fri Mar 19 
01:35:08 2010        (r327)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2007 Ryan Leavengood <leavengood@xxxxxxxxx>
+ * Copyright (C) 2009, 2010 Dirk Schulze <krit@xxxxxxxxxx>
  * Copyright (C) 2010 Stephan Aßmus <superstippi@xxxxxx>
  * Copyright (C) 2010 Michael Lotz <mmlr@xxxxxxxx>
  *
@@ -40,6 +41,7 @@
 #include <Bitmap.h>
 #include <Shape.h>
 #include <View.h>
+#include <math.h>
 #include <stdio.h>
 
 namespace WebCore {
@@ -222,9 +224,8 @@
     // BShapeIterator allows us to modify the path data "in place"
     class TranslateIterator : public BShapeIterator {
     public:
-        TranslateIterator(BShape* shape, const FloatSize& size)
-            : m_shape(shape)
-            , m_size(size)
+        TranslateIterator(const FloatSize& size)
+            : m_size(size)
         {
         }
         virtual status_t IterateMoveTo(BPoint* point)
@@ -258,15 +259,23 @@
             return B_OK;
         }
 
+        virtual status_t IterateArcTo(float& rx, float& ry,
+               float& angle, bool largeArc, bool counterClockWise, BPoint& 
point)
+        {
+            point.x += m_size.width();
+            point.y += m_size.height();
+
+            return B_OK;
+        }
+
         virtual status_t IterateClose()
         {
             return B_OK;
         }
 
     private:
-        BShape* m_shape;
         const FloatSize& m_size;
-    } translateIterator(m_path, size);
+    } translateIterator(size);
 
     translateIterator.Iterate(m_path);
 }
@@ -314,7 +323,75 @@
 
 void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
 {
-    notImplemented();
+    if (isEmpty())
+        return;
+
+    FloatPoint p0(m_path->CurrentPosition());
+
+    if ((p1.x() == p0.x() && p1.y() == p0.y()) || (p1.x() == p2.x() && p1.y() 
== p2.y()) || radius == 0.f) {
+        m_path->LineTo(p1);
+        return;
+    }
+
+    FloatPoint p1p0((p0.x() - p1.x()), (p0.y() - p1.y()));
+    FloatPoint p1p2((p2.x() - p1.x()), (p2.y() - p1.y()));
+    float p1p0_length = sqrtf(p1p0.x() * p1p0.x() + p1p0.y() * p1p0.y());
+    float p1p2_length = sqrtf(p1p2.x() * p1p2.x() + p1p2.y() * p1p2.y());
+
+    double cos_phi = (p1p0.x() * p1p2.x() + p1p0.y() * p1p2.y()) / 
(p1p0_length * p1p2_length);
+    // all points on a line logic
+    if (cos_phi == -1) {
+        m_path->LineTo(p1);
+        return;
+    }
+    if (cos_phi == 1) {
+        // add infinite far away point
+        unsigned int max_length = 65535;
+        double factor_max = max_length / p1p0_length;
+        FloatPoint ep((p0.x() + factor_max * p1p0.x()), (p0.y() + factor_max * 
p1p0.y()));
+        m_path->LineTo(ep);
+        return;
+    }
+
+    float tangent = radius / tan(acos(cos_phi) / 2);
+    float factor_p1p0 = tangent / p1p0_length;
+    FloatPoint t_p1p0((p1.x() + factor_p1p0 * p1p0.x()), (p1.y() + factor_p1p0 
* p1p0.y()));
+
+    FloatPoint orth_p1p0(p1p0.y(), -p1p0.x());
+    float orth_p1p0_length = sqrt(orth_p1p0.x() * orth_p1p0.x() + 
orth_p1p0.y() * orth_p1p0.y());
+    float factor_ra = radius / orth_p1p0_length;
+
+    // angle between orth_p1p0 and p1p2 to get the right vector orthographic 
to p1p0
+    double cos_alpha = (orth_p1p0.x() * p1p2.x() + orth_p1p0.y() * p1p2.y()) / 
(orth_p1p0_length * p1p2_length);
+    if (cos_alpha < 0.f)
+        orth_p1p0 = FloatPoint(-orth_p1p0.x(), -orth_p1p0.y());
+
+    FloatPoint p((t_p1p0.x() + factor_ra * orth_p1p0.x()), (t_p1p0.y() + 
factor_ra * orth_p1p0.y()));
+
+    // calculate angles for addArc
+    orth_p1p0 = FloatPoint(-orth_p1p0.x(), -orth_p1p0.y());
+    float sa = acos(orth_p1p0.x() / orth_p1p0_length);
+    if (orth_p1p0.y() < 0.f)
+        sa = 2 * piDouble - sa;
+
+    // anticlockwise logic
+    bool anticlockwise = false;
+
+    float factor_p1p2 = tangent / p1p2_length;
+    FloatPoint t_p1p2((p1.x() + factor_p1p2 * p1p2.x()), (p1.y() + factor_p1p2 
* p1p2.y()));
+    FloatPoint orth_p1p2((t_p1p2.x() - p.x()), (t_p1p2.y() - p.y()));
+    float orth_p1p2_length = sqrtf(orth_p1p2.x() * orth_p1p2.x() + 
orth_p1p2.y() * orth_p1p2.y());
+    float ea = acos(orth_p1p2.x() / orth_p1p2_length);
+    if (orth_p1p2.y() < 0)
+        ea = 2 * piDouble - ea;
+    if ((sa > ea) && ((sa - ea) < piDouble))
+        anticlockwise = true;
+    if ((sa < ea) && ((ea - sa) > piDouble))
+        anticlockwise = true;
+
+    m_path->LineTo(t_p1p0);
+
+    addArc(p, radius, sa, ea, anticlockwise);
 }
 
 void Path::closeSubpath()
@@ -322,24 +399,69 @@
     m_path->Close();
 }
 
-void Path::addArc(const FloatPoint& p, float r, float sar, float ear, bool 
anticlockwise)
+void Path::addArc(const FloatPoint& center, float radius,
+       float startAnglgeRadiants, float endAngleRadiants, bool anticlockwise)
 {
-    notImplemented();
+       if (endAngleRadiants - startAnglgeRadiants + 0.000001 >= M_PI * 2) {
+               addEllipse(FloatRect(center.x() - radius, center.y() - radius,
+                   radius * 2, radius * 2));
+               return;
+       }
+    m_path->MoveTo(BPoint(center.x() + radius * cos(startAnglgeRadiants),
+                          center.y() + radius * sin(startAnglgeRadiants)));
+    m_path->ArcTo(radius, radius, 0, false, anticlockwise,
+                 BPoint(center.x() + radius * cos(endAngleRadiants),
+                         center.y() + radius * sin(endAngleRadiants)));
 }
 
 void Path::addRect(const FloatRect& r)
 {
-    m_path->Close();
     m_path->MoveTo(BPoint(r.x(), r.y()));
-    m_path->LineTo(BPoint(r.x() + r.width(), r.y()));
-    m_path->LineTo(BPoint(r.x() + r.width(), r.y() + r.height()));
-    m_path->LineTo(BPoint(r.x(), r.y() + r.height()));
+    m_path->LineTo(BPoint(r.right(), r.y()));
+    m_path->LineTo(BPoint(r.right(), r.bottom()));
+    m_path->LineTo(BPoint(r.x(), r.bottom()));
     m_path->Close();
 }
 
 void Path::addEllipse(const FloatRect& r)
 {
-    notImplemented();
+    BPoint points[3];
+    const float radiusH = r.width() / 2;
+    const float radiusV = r.height() / 2;
+    const float middleH = r.x() + radiusH;
+    const float middleV = r.y() + radiusV;
+    const float kRadiusBezierScale = 0.552284;
+
+    m_path->MoveTo(BPoint(middleH, r.y()));
+    points[0].x = middleH + kRadiusBezierScale * radiusH;
+    points[0].y = r.y();
+    points[1].x = r.right();
+    points[1].y = middleV - kRadiusBezierScale * radiusV;
+    points[2].x = r.right();
+    points[2].y = middleV;
+    m_path->BezierTo(points);
+    points[0].x = r.right();
+    points[0].y = middleV + kRadiusBezierScale * radiusV;
+    points[1].x = middleH + kRadiusBezierScale * radiusH;
+    points[1].y = r.bottom();
+    points[2].x = middleH;
+    points[2].y = r.bottom();
+    m_path->BezierTo(points);
+    points[0].x = middleH - kRadiusBezierScale * radiusH;
+    points[0].y = r.bottom();
+    points[1].x = r.x();
+    points[1].y = middleV + kRadiusBezierScale * radiusV;
+    points[2].x = r.x();
+    points[2].y = middleV;
+    m_path->BezierTo(points);
+    points[0].x = r.x();
+    points[0].y = middleV - kRadiusBezierScale * radiusV;
+    points[1].x = middleH - kRadiusBezierScale * radiusH;
+    points[1].y = r.y();
+    points[2].x = middleH;
+    points[2].y = r.y();
+    m_path->BezierTo(points);
+    m_path->Close();
 }
 
 void Path::clear()
@@ -360,7 +482,79 @@
 
 void Path::apply(void* info, PathApplierFunction function) const
 {
-    notImplemented();
+    // BShapeIterator allows us to modify the path data "in place"
+    class ApplyIterator : public BShapeIterator {
+    public:
+        ApplyIterator(void* info, PathApplierFunction function)
+            : m_info(info)
+            , m_function(function)
+        {
+        }
+
+        virtual status_t IterateMoveTo(BPoint* point)
+        {
+               PathElement pathElement;
+               pathElement.type = PathElementMoveToPoint;
+            pathElement.points = m_pathPoints;
+            m_pathPoints[0] = point[0];
+            m_function(m_info, &pathElement);
+            return B_OK;
+        }
+
+        virtual status_t IterateLineTo(int32 lineCount, BPoint* linePts)
+        {
+               PathElement pathElement;
+               pathElement.type = PathElementAddLineToPoint;
+            pathElement.points = m_pathPoints;
+            while (lineCount--) {
+                m_pathPoints[0] = linePts[0];
+                m_function(m_info, &pathElement);
+                linePts++;
+            }
+            return B_OK;
+        }
+
+        virtual status_t IterateBezierTo(int32 bezierCount, BPoint* bezierPts)
+        {
+               PathElement pathElement;
+               pathElement.type = PathElementAddCurveToPoint;
+            pathElement.points = m_pathPoints;
+            while (bezierCount--) {
+                m_pathPoints[0] = bezierPts[0];
+                m_pathPoints[1] = bezierPts[1];
+                m_pathPoints[2] = bezierPts[2];
+                m_function(m_info, &pathElement);
+                bezierPts += 3;
+            }
+            return B_OK;
+        }
+
+        virtual status_t IterateArcTo(float& rx, float& ry,
+               float& angle, bool largeArc, bool counterClockWise, BPoint& 
point)
+        {
+               // FIXME: This doesn't seem to be supported by WebCore.
+               // Maybe we are supposed to convert arc into cubic curve
+               // segments when adding them to a path?
+
+            return B_OK;
+        }
+
+        virtual status_t IterateClose()
+        {
+               PathElement pathElement;
+               pathElement.type = PathElementCloseSubpath;
+            pathElement.points = m_pathPoints;
+            m_function(m_info, &pathElement);
+            return B_OK;
+        }
+
+    private:
+        void* m_info;
+        PathApplierFunction m_function;
+        FloatPoint m_pathPoints[3];
+    } applyIterator(info, function);
+
+    applyIterator.Iterate(m_path);
 }
 
 void Path::transform(const AffineTransform& transform)
@@ -368,9 +562,8 @@
     // BShapeIterator allows us to modify the path data "in place"
     class TransformIterator : public BShapeIterator {
     public:
-        TransformIterator(BShape* shape, const AffineTransform& transform)
-            : m_shape(shape)
-            , m_transform(transform)
+        TransformIterator(const AffineTransform& transform)
+            : m_transform(transform)
         {
         }
         virtual status_t IterateMoveTo(BPoint* point)
@@ -399,15 +592,25 @@
             return B_OK;
         }
 
+        virtual status_t IterateArcTo(float& rx, float& ry,
+               float& angle, bool largeArc, bool counterClockWise, BPoint& 
point)
+        {
+            point = m_transform.mapPoint(point);
+            rx *= m_transform.a();
+            ry *= m_transform.d();
+            // FIXME: rotate angle...
+
+            return B_OK;
+        }
+
         virtual status_t IterateClose()
         {
             return B_OK;
         }
 
     private:
-        BShape* m_shape;
         const AffineTransform& m_transform;
-    } transformIterator(m_path, transform);
+    } transformIterator(transform);
 
     transformIterator.Iterate(m_path);
 }

Other related posts:

  • » [haiku-webkit-commits] r327 - webkit/trunk/WebCore/platform/graphics/haiku - webkit