X-Git-Url: http://git.webkit.org/?p=WebKit-https.git;a=blobdiff_plain;f=WebCore%2Fplatform%2Fgraphics%2Fcairo%2FPathCairo.cpp;h=c61f2ac9bd221f164c0831f029e222759e757a0f;hp=4ba0b6e6d85858c69c3dc51eb75529138aa19994;hb=cb0201b8c43bd7aa57b28c6267879a89256bf8db;hpb=a6d97dfbea44a670122c40f1e4880dc15a55bdf5 diff --git a/WebCore/platform/graphics/cairo/PathCairo.cpp b/WebCore/platform/graphics/cairo/PathCairo.cpp index 4ba0b6e..c61f2ac 100644 --- a/WebCore/platform/graphics/cairo/PathCairo.cpp +++ b/WebCore/platform/graphics/cairo/PathCairo.cpp @@ -4,6 +4,7 @@ 2004, 2005, 2006 Rob Buis 2005, 2007 Apple Inc. All Rights reserved. 2007 Alp Toker + 2008 Dirk Schulze This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -155,9 +156,78 @@ void Path::addArc(const FloatPoint& p, float r, float sa, float ea, bool anticlo void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius) { - // FIXME: cairo_arc_to not yet in cairo see cairo.h - // cairo_arc_to(m_cr, p1.x(), p1.y(), p2.x(), p2.y()); - notImplemented(); + if (isEmpty()) + return; + + cairo_t* cr = platformPath()->m_cr; + + double x0, y0; + cairo_get_current_point(cr, &x0, &y0); + FloatPoint p0(x0, y0); + if ((p1.x() == p0.x() && p1.y() == p0.y()) || (p1.x() == p2.x() && p1.y() == p2.y()) || radius == 0.f) { + cairo_line_to(cr, p1.x(), p1.y()); + 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) { + cairo_line_to(cr, p1.x(), p1.y()); + 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())); + cairo_line_to(cr, ep.x(), ep.y()); + 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; + + cairo_line_to(cr, t_p1p0.x(), t_p1p0.y()); + + addArc(p, radius, sa, ea, anticlockwise); } void Path::addEllipse(const FloatRect& rect)