[webkit-changes] cvs commit: SVGSupport/ksvg2/svg
SVGMarkerElementImpl.cpp
Eric
eseidel at opensource.apple.com
Mon Nov 28 18:03:58 PST 2005
eseidel 05/11/28 18:03:57
Modified: . ChangeLog
kcanvas KCanvasResources.cpp KCanvasResources.h
kcanvas/device/quartz KCanvasItemQuartz.h
KCanvasItemQuartz.mm QuartzSupport.h
ksvg2/misc KCanvasRenderingStyle.cpp KCanvasRenderingStyle.h
ksvg2/svg SVGMarkerElementImpl.cpp
Log:
Bug #: 5359
Submitted by: Julien Palmas <julien.palmas at gmail.com>
Reviewed by: eseidel
Fixes 2 marker test cases.
This patch makes WebCore+SVG's marker support 90% complete
This fixes marker drawing as well as auto-orientation & scaling.
http://bugzilla.opendarwin.org/show_bug.cgi?id=5359
* kcanvas/KCanvasResources.cpp:
(KCanvasMarker::setRef): combined setRefX and setRefY
(KCanvasMarker::setScale): combined setScaleX and setScaleY
(KCanvasMarker::draw): updated post-merger
* kcanvas/KCanvasResources.h:
* kcanvas/device/quartz/KCanvasItemQuartz.h:
* kcanvas/device/quartz/KCanvasItemQuartz.mm:
(DrawMarkersData::DrawMarkersData): new struct
(drawMarkerWithData): added, draws one marker
(updateMarkerDataForElement): added, helper function during draw
(DrawStartAndMidMarkers): added, CGPathApply helper function
(KCanvasItemQuartz::drawMarkersIfNeeded): updated
(KCanvasItemQuartz::paint): updated.
* kcanvas/device/quartz/QuartzSupport.h:
(CGPointSubtractPoints): added
* ksvg2/misc/KCanvasRenderingStyle.cpp:
(KCanvasRenderingStyle::updateStroke): updated to use static method
(KCanvasRenderingStyle::cssPrimitiveToLength): now static
* ksvg2/misc/KCanvasRenderingStyle.h:
* ksvg2/svg/SVGMarkerElementImpl.cpp:
(SVGMarkerElementImpl::parseMappedAttribute): updated
(SVGMarkerElementImpl::canvasResource): fixed
Revision Changes Path
1.416 +33 -1 WebCore/ChangeLog
Index: ChangeLog
===================================================================
RCS file: /cvs/root/WebCore/ChangeLog,v
retrieving revision 1.415
retrieving revision 1.416
diff -u -r1.415 -r1.416
--- ChangeLog 29 Nov 2005 01:43:44 -0000 1.415
+++ ChangeLog 29 Nov 2005 02:03:48 -0000 1.416
@@ -1,3 +1,35 @@
+2005-11-28 Julien Palmas <julien.palmas at gmail.com>
+
+ Reviewed by eseidel. Committed by eseidel.
+
+ Fixes 2 marker test cases.
+
+ This patch makes WebCore+SVG's marker support 90% complete
+ This fixes marker drawing as well as auto-orientation & scaling.
+
+ * kcanvas/KCanvasResources.cpp:
+ (KCanvasMarker::setRef): combined setRefX and setRefY
+ (KCanvasMarker::setScale): combined setScaleX and setScaleY
+ (KCanvasMarker::draw): updated post-merger
+ * kcanvas/KCanvasResources.h:
+ * kcanvas/device/quartz/KCanvasItemQuartz.h:
+ * kcanvas/device/quartz/KCanvasItemQuartz.mm:
+ (DrawMarkersData::DrawMarkersData): new struct
+ (drawMarkerWithData): added, draws one marker
+ (updateMarkerDataForElement): added, helper function during draw
+ (DrawStartAndMidMarkers): added, CGPathApply helper function
+ (KCanvasItemQuartz::drawMarkersIfNeeded): updated
+ (KCanvasItemQuartz::paint): updated.
+ * kcanvas/device/quartz/QuartzSupport.h:
+ (CGPointSubtractPoints): added
+ * ksvg2/misc/KCanvasRenderingStyle.cpp:
+ (KCanvasRenderingStyle::updateStroke): updated to use static method
+ (KCanvasRenderingStyle::cssPrimitiveToLength): now static
+ * ksvg2/misc/KCanvasRenderingStyle.h:
+ * ksvg2/svg/SVGMarkerElementImpl.cpp:
+ (SVGMarkerElementImpl::parseMappedAttribute): updated
+ (SVGMarkerElementImpl::canvasResource): fixed
+
2005-11-28 Adele Peterson <adele at apple.com>
Reviewed by Justin.
@@ -37,7 +69,7 @@
No review, build fix only.
- Corrected typo in last commit causing build failure.
+ Corrected typo in last commit causing WebKit+SVG build failure.
* kcanvas/KCanvasFilters.h:
(QSizeF::QSizeF): fixed typo.
1.11 +11 -16 SVGSupport/kcanvas/KCanvasResources.cpp
Index: KCanvasResources.cpp
===================================================================
RCS file: /cvs/root/SVGSupport/kcanvas/KCanvasResources.cpp,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- KCanvasResources.cpp 23 Nov 2005 15:14:05 -0000 1.10
+++ KCanvasResources.cpp 29 Nov 2005 02:03:55 -0000 1.11
@@ -138,9 +138,10 @@
m_marker = marker;
}
-void KCanvasMarker::setRefX(double refX)
+void KCanvasMarker::setRef(double refX, double refY)
{
m_refX = refX;
+ m_refY = refY;
}
double KCanvasMarker::refX() const
@@ -148,11 +149,6 @@
return m_refX;
}
-void KCanvasMarker::setRefY(double refY)
-{
- m_refY = refY;
-}
-
double KCanvasMarker::refY() const
{
return m_refY;
@@ -183,9 +179,10 @@
return m_useStrokeWidth;
}
-void KCanvasMarker::setScaleX(float scaleX)
+void KCanvasMarker::setScale(float scaleX, float scaleY)
{
m_scaleX = scaleX;
+ m_scaleY = scaleY;
}
float KCanvasMarker::scaleX() const
@@ -193,21 +190,16 @@
return m_scaleX;
}
-void KCanvasMarker::setScaleY(float scaleY)
-{
- m_scaleY = scaleY;
-}
-
float KCanvasMarker::scaleY() const
{
return m_scaleY;
}
-void KCanvasMarker::draw(const QRect &rect, const KCanvasMatrix &objectMatrix, double x, double y, double strokeWidth, double angle)
+void KCanvasMarker::draw(const QRect &rect, double x, double y, double strokeWidth, double angle)
{
if(m_marker)
{
- KCanvasMatrix translation = objectMatrix;
+ KCanvasMatrix translation;
translation.translate(x, y);
KCanvasMatrix rotation;
@@ -220,10 +212,13 @@
if(m_useStrokeWidth)
rotation.scale(strokeWidth, strokeWidth);
- // FIXME: I'm not sure if this is right yet...
+ // FIXME: PaintInfo should be passed into this method instead.
QPainter p;
- khtml::RenderObject::PaintInfo info(&p, QRect(), PaintActionForeground, 0);
+ khtml::RenderObject::PaintInfo info(&p, rect, PaintActionForeground, 0);
+ m_marker->setLocalTransform(rotation.multiply(translation).qmatrix());
+ static_cast<KCanvasContainer *>(m_marker)->setDrawsContents(true);
m_marker->paint(info, 0, 0);
+ static_cast<KCanvasContainer *>(m_marker)->setDrawsContents(false);
}
}
1.10 +4 -8 SVGSupport/kcanvas/KCanvasResources.h
Index: KCanvasResources.h
===================================================================
RCS file: /cvs/root/SVGSupport/kcanvas/KCanvasResources.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- KCanvasResources.h 23 Nov 2005 15:14:05 -0000 1.9
+++ KCanvasResources.h 29 Nov 2005 02:03:55 -0000 1.10
@@ -98,10 +98,8 @@
void setMarker(khtml::RenderObject *marker);
- void setRefX(double refX);
- double refX() const;
-
- void setRefY(double refY);
+ void setRef(double refX, double refY);
+ double refX() const;
double refY() const;
void setAngle(float angle);
@@ -111,14 +109,12 @@
void setUseStrokeWidth(bool useStrokeWidth = true);
bool useStrokeWidth() const;
- void setScaleX(float scaleX);
+ void setScale(float scaleX, float scaleY);
float scaleX() const;
-
- void setScaleY(float scaleY);
float scaleY() const;
// Draw onto the canvas
- void draw(const QRect &rect, const KCanvasMatrix &objectMatrix, double x, double y, double strokeWidth = 1., double angle = 0.0);
+ void draw(const QRect &rect, double x, double y, double strokeWidth = 1., double angle = 0.0);
QTextStream& externalRepresentation(QTextStream &) const;
private:
1.5 +1 -1 SVGSupport/kcanvas/device/quartz/KCanvasItemQuartz.h
Index: KCanvasItemQuartz.h
===================================================================
RCS file: /cvs/root/SVGSupport/kcanvas/device/quartz/KCanvasItemQuartz.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- KCanvasItemQuartz.h 23 Nov 2005 15:14:07 -0000 1.4
+++ KCanvasItemQuartz.h 29 Nov 2005 02:03:55 -0000 1.5
@@ -42,5 +42,5 @@
virtual bool nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
HitTestAction hitTestAction);
private:
- void drawMarkersIfNeeded(const QRect &rect) const;
+ void drawMarkersIfNeeded(const QRect &rect, CGPathRef path) const;
};
1.12 +128 -14 SVGSupport/kcanvas/device/quartz/KCanvasItemQuartz.mm
Index: KCanvasItemQuartz.mm
===================================================================
RCS file: /cvs/root/SVGSupport/kcanvas/device/quartz/KCanvasItemQuartz.mm,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- KCanvasItemQuartz.mm 27 Nov 2005 11:02:16 -0000 1.11
+++ KCanvasItemQuartz.mm 29 Nov 2005 02:03:55 -0000 1.12
@@ -41,6 +41,7 @@
#import "QuartzSupport.h"
#import "SVGRenderStyle.h"
+#import "KCanvasRenderingStyle.h"
KCanvasItemQuartz::KCanvasItemQuartz(khtml::RenderStyle *style, KSVG::SVGStyledElementImpl *node) : RenderPath(style, node)
@@ -48,22 +49,135 @@
}
-void KCanvasItemQuartz::drawMarkersIfNeeded(const QRect &rect) const
+typedef enum {
+ Start,
+ Mid,
+ End
+} MarkerType;
+
+struct MarkerData {
+ CGPoint origin;
+ double strokeWidth;
+ CGPoint inslopePoints[2];
+ CGPoint outslopePoints[2];
+ MarkerType type;
+ KCanvasMarker *marker;
+};
+
+struct DrawMarkersData {
+ DrawMarkersData(KCanvasMarker *startMarker, KCanvasMarker *midMarker, double strokeWidth);
+
+ int elementIndex;
+ MarkerData previousMarkerData;
+ KCanvasMarker *midMarker;
+};
+
+DrawMarkersData::DrawMarkersData(KCanvasMarker *start, KCanvasMarker *mid, double strokeWidth)
+{
+ elementIndex = 0;
+ midMarker = mid;
+
+ previousMarkerData.origin = CGPointZero;
+ previousMarkerData.strokeWidth = strokeWidth;
+ previousMarkerData.marker = start;
+ previousMarkerData.type = Start;
+}
+
+void drawMarkerWithData(MarkerData &data)
+{
+ if (!data.marker)
+ return;
+
+ CGPoint inslopeChange = CGPointSubtractPoints(data.inslopePoints[1], data.inslopePoints[0]);
+ CGPoint outslopeChange = CGPointSubtractPoints(data.outslopePoints[1], data.outslopePoints[0]);
+
+ static const double deg2rad = M_PI/180.0;
+ double inslope = atan2(inslopeChange.y, inslopeChange.x) / deg2rad;
+ double outslope = atan2(outslopeChange.y, outslopeChange.x) / deg2rad;
+
+ double angle;
+ if (data.type == Start)
+ angle = outslope;
+ else if (data.type == Mid)
+ angle = (inslope + outslope) / 2;
+ else // (data.type == End)
+ angle = inslope;
+
+ data.marker->draw(QRect(), data.origin.x, data.origin.y, data.strokeWidth, angle);
+}
+
+static inline void updateMarkerDataForElement(MarkerData &previousMarkerData, const CGPathElement *element)
+{
+ CGPoint *points = element->points;
+
+ switch (element->type) {
+ case kCGPathElementAddQuadCurveToPoint:
+ // TODO
+ previousMarkerData.origin = points[1];
+ break;
+ case kCGPathElementAddCurveToPoint:
+ previousMarkerData.inslopePoints[0] = points[1];
+ previousMarkerData.inslopePoints[1] = points[2];
+ previousMarkerData.origin = points[2];
+ break;
+ default:
+ previousMarkerData.inslopePoints[0] = previousMarkerData.origin;
+ previousMarkerData.inslopePoints[1] = points[0];
+ previousMarkerData.origin = points[0];
+ break;
+ }
+}
+
+void DrawStartAndMidMarkers(void *info, const CGPathElement *element)
+{
+ DrawMarkersData &data = *(DrawMarkersData *)info;
+
+ int elementIndex = data.elementIndex;
+ MarkerData &previousMarkerData = data.previousMarkerData;
+
+ CGPoint *points = element->points;
+
+ // First update the outslope for the previous element
+ previousMarkerData.outslopePoints[0] = previousMarkerData.origin;
+ previousMarkerData.outslopePoints[1] = points[0];
+
+ // Draw the marker for the previous element
+ if (elementIndex != 0)
+ drawMarkerWithData(previousMarkerData);
+
+ // Update our marker data for this element
+ updateMarkerDataForElement(previousMarkerData, element);
+
+ if (elementIndex == 1) {
+ // After drawing the start marker, switch to drawing mid markers
+ previousMarkerData.marker = data.midMarker;
+ previousMarkerData.type = Mid;
+ }
+
+ data.elementIndex++;
+}
+
+void KCanvasItemQuartz::drawMarkersIfNeeded(const QRect &rect, CGPathRef path) const
{
KDOM::DocumentImpl *doc = document();
KSVG::SVGRenderStyle *svgStyle = style()->svgStyle();
- // find the start verticies...
- if(KCanvasMarker *marker = getMarkerById(doc, svgStyle->startMarker().mid(1)))
- marker->draw(rect, localTransform(), 0, 0, 0);
-
- // find the middle verticies...
- if(KCanvasMarker *marker = getMarkerById(doc, svgStyle->midMarker().mid(1)))
- marker->draw(rect, localTransform(), 0, 0, 0);
-
- // find the end verticies...
- if(KCanvasMarker *marker = getMarkerById(doc, svgStyle->endMarker().mid(1)))
- marker->draw(rect, localTransform(), 0, 0, 0);
+ KCanvasMarker *startMarker = getMarkerById(doc, svgStyle->startMarker().mid(1));
+ KCanvasMarker *midMarker = getMarkerById(doc, svgStyle->midMarker().mid(1));
+ KCanvasMarker *endMarker = getMarkerById(doc, svgStyle->endMarker().mid(1));
+
+ if (!startMarker && !midMarker && !endMarker)
+ return;
+
+ double strokeWidth = KSVG::KCanvasRenderingStyle::cssPrimitiveToLength(this, style()->svgStyle()->strokeWidth(), 1.0);
+
+ DrawMarkersData data(startMarker, midMarker, strokeWidth);
+
+ CGPathApply(path, &data, DrawStartAndMidMarkers);
+
+ data.previousMarkerData.marker = endMarker;
+ data.previousMarkerData.type = End;
+ drawMarkerWithData(data.previousMarkerData);
}
void KCanvasItemQuartz::paint(PaintInfo &paintInfo, int parentX, int parentY)
@@ -117,14 +231,14 @@
canvasStyle()->strokePainter()->draw(quartzDevice->currentContext(), args);
}
- drawMarkersIfNeeded(dirtyRect);
+ drawMarkersIfNeeded(dirtyRect, cgPath);
// actually apply the filter
if (filter) {
filter->applyFilter(quartzDevice, relativeBBox(true));
context = quartzDevice->currentCGContext();
}
-
+
// restore drawing state
paintInfo.p->restore();
if (!parent()->isKCanvasContainer()) {
1.4 +2 -0 SVGSupport/kcanvas/device/quartz/QuartzSupport.h
Index: QuartzSupport.h
===================================================================
RCS file: /cvs/root/SVGSupport/kcanvas/device/quartz/QuartzSupport.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- QuartzSupport.h 21 Nov 2005 08:29:15 -0000 1.3
+++ QuartzSupport.h 29 Nov 2005 02:03:56 -0000 1.4
@@ -59,3 +59,5 @@
return kCGLineJoinMiter;
}
+
+static inline CGPoint CGPointSubtractPoints(CGPoint a, CGPoint b) { return CGPointMake(a.x - b.x, a.y - b.y); }
1.12 +4 -4 SVGSupport/ksvg2/misc/KCanvasRenderingStyle.cpp
Index: KCanvasRenderingStyle.cpp
===================================================================
RCS file: /cvs/root/SVGSupport/ksvg2/misc/KCanvasRenderingStyle.cpp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- KCanvasRenderingStyle.cpp 27 Nov 2005 11:02:20 -0000 1.11
+++ KCanvasRenderingStyle.cpp 29 Nov 2005 02:03:56 -0000 1.12
@@ -133,7 +133,7 @@
}
strokePainter()->setOpacity(m_style->svgStyle()->strokeOpacity());
- strokePainter()->setStrokeWidth(cssPrimitiveToLength(item, m_style->svgStyle()->strokeWidth(), 1.0));
+ strokePainter()->setStrokeWidth(KCanvasRenderingStyle::cssPrimitiveToLength(item, m_style->svgStyle()->strokeWidth(), 1.0));
KDOM::CSSValueListImpl *dashes = m_style->svgStyle()->strokeDashArray();
if(dashes)
@@ -155,7 +155,7 @@
}
strokePainter()->setDashArray(array);
- strokePainter()->setDashOffset(cssPrimitiveToLength(item, m_style->svgStyle()->strokeDashOffset(), 0.0));
+ strokePainter()->setDashOffset(KCanvasRenderingStyle::cssPrimitiveToLength(item, m_style->svgStyle()->strokeDashOffset(), 0.0));
}
strokePainter()->setStrokeMiterLimit(m_style->svgStyle()->strokeMiterLimit());
@@ -183,7 +183,7 @@
}
}
-double KCanvasRenderingStyle::cssPrimitiveToLength(RenderPath *item, KDOM::CSSValueImpl *value, double defaultValue) const
+double KCanvasRenderingStyle::cssPrimitiveToLength(const RenderPath *item, KDOM::CSSValueImpl *value, double defaultValue)
{
KDOM::CSSPrimitiveValueImpl *primitive = static_cast<KDOM::CSSPrimitiveValueImpl *>(value);
@@ -207,7 +207,7 @@
}
}
- return primitive->computeLengthFloat(const_cast<khtml::RenderStyle *>(m_style), paintDeviceMetrics);
+ return primitive->computeLengthFloat(const_cast<khtml::RenderStyle *>(item->style()), paintDeviceMetrics);
}
// Stroke (aka Pen) properties
1.8 +1 -1 SVGSupport/ksvg2/misc/KCanvasRenderingStyle.h
Index: KCanvasRenderingStyle.h
===================================================================
RCS file: /cvs/root/SVGSupport/ksvg2/misc/KCanvasRenderingStyle.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- KCanvasRenderingStyle.h 27 Nov 2005 11:02:20 -0000 1.7
+++ KCanvasRenderingStyle.h 29 Nov 2005 02:03:56 -0000 1.8
@@ -76,7 +76,7 @@
KRenderingStrokePainter *strokePainter();
void disableStrokePainter();
- double cssPrimitiveToLength(RenderPath *item, KDOM::CSSValueImpl *value, double defaultValue = 0.0) const;
+ static double cssPrimitiveToLength(const RenderPath *item, KDOM::CSSValueImpl *value, double defaultValue = 0.0);
// Fill (aka Brush) properties
bool isFilled() const;
1.11 +16 -6 SVGSupport/ksvg2/svg/SVGMarkerElementImpl.cpp
Index: SVGMarkerElementImpl.cpp
===================================================================
RCS file: /cvs/root/SVGSupport/ksvg2/svg/SVGMarkerElementImpl.cpp,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- SVGMarkerElementImpl.cpp 27 Nov 2005 11:02:26 -0000 1.10
+++ SVGMarkerElementImpl.cpp 29 Nov 2005 02:03:57 -0000 1.11
@@ -35,6 +35,7 @@
#include "SVGHelper.h"
#include "SVGAngleImpl.h"
#include "SVGLengthImpl.h"
+#include "SVGMatrixImpl.h"
#include "SVGSVGElementImpl.h"
#include "SVGFitToViewBoxImpl.h"
#include "SVGMarkerElementImpl.h"
@@ -59,7 +60,11 @@
void SVGMarkerElementImpl::parseMappedAttribute(KDOM::MappedAttributeImpl *attr)
{
const KDOM::AtomicString& value = attr->value();
- if (attr->name() == SVGNames::refXAttr)
+ if (attr->name() == SVGNames::markerUnitsAttr) {
+ if (value == "userSpaceOnUse")
+ markerUnits()->setBaseVal(SVG_MARKERUNITS_USERSPACEONUSE);
+ }
+ else if (attr->name() == SVGNames::refXAttr)
refX()->baseVal()->setValueAsString(value.impl());
else if (attr->name() == SVGNames::refYAttr)
refY()->baseVal()->setValueAsString(value.impl());
@@ -69,10 +74,9 @@
markerHeight()->baseVal()->setValueAsString(value.impl());
else if (attr->name() == SVGNames::orientAttr)
{
- if(KDOM::DOMString(value) == "auto")
+ if (value == "auto")
setOrientToAuto();
- else
- {
+ else {
SVGAngleImpl *angle = SVGSVGElementImpl::createSVGAngle();
angle->setValueAsString(value.impl());
setOrientToAngle(angle);
@@ -160,8 +164,14 @@
else
m_marker->setAutoAngle();
- m_marker->setRefX(refX()->baseVal()->value());
- m_marker->setRefY(refY()->baseVal()->value());
+ m_marker->setRef(refX()->baseVal()->value(), refY()->baseVal()->value());
+
+ m_marker->setUseStrokeWidth(markerUnits()->baseVal() == SVG_MARKERUNITS_STROKEWIDTH);
+ double w = markerWidth()->baseVal()->value();
+ double h = markerHeight()->baseVal()->value();
+ SharedPtr<SVGMatrixImpl> viewBox = viewBoxToViewTransform(w, h);
+ m_marker->setScale(viewBox->qmatrix().m11(), viewBox->qmatrix().m22());
+
return m_marker;
}
More information about the webkit-changes
mailing list