• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KHTML

  • sources
  • kde-4.12
  • kdelibs
  • khtml
  • platform
  • graphics
Path.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
3  * 2006 Rob Buis <buis@kde.org>
4  * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 
29 #include "config.h"
30 #include "wtf/Platform.h"
31 #include "Path.h"
32 
33 #include "FloatPoint.h"
34 #include "FloatRect.h"
35 #include "PathTraversalState.h"
36 #include <math.h>
37 #include <wtf/MathExtras.h>
38 
39 const float QUARTER = 0.552f; // approximation of control point positions on a bezier
40  // to simulate a quarter of a circle.
41 
42 using namespace WebCore;
43 
44 namespace khtml {
45 
46 static void pathLengthApplierFunction(void* info, const PathElement* element)
47 {
48  PathTraversalState& traversalState = *static_cast<PathTraversalState*>(info);
49  if (traversalState.m_success)
50  return;
51  traversalState.m_previous = traversalState.m_current;
52  FloatPoint* points = element->points;
53  float segmentLength = 0.0f;
54  switch (element->type) {
55  case PathElementMoveToPoint:
56  segmentLength = traversalState.moveTo(points[0]);
57  break;
58  case PathElementAddLineToPoint:
59  segmentLength = traversalState.lineTo(points[0]);
60  break;
61  case PathElementAddQuadCurveToPoint:
62  segmentLength = traversalState.quadraticBezierTo(points[0], points[1]);
63  break;
64  case PathElementAddCurveToPoint:
65  segmentLength = traversalState.cubicBezierTo(points[0], points[1], points[2]);
66  break;
67  case PathElementCloseSubpath:
68  segmentLength = traversalState.closeSubpath();
69  break;
70  }
71  traversalState.m_totalLength += segmentLength;
72  if ((traversalState.m_action == PathTraversalState::TraversalPointAtLength ||
73  traversalState.m_action == PathTraversalState::TraversalNormalAngleAtLength) &&
74  (traversalState.m_totalLength >= traversalState.m_desiredLength)) {
75  FloatSize change = traversalState.m_current - traversalState.m_previous;
76  float slope = atan2f(change.height(), change.width());
77 
78  if (traversalState.m_action == PathTraversalState::TraversalPointAtLength) {
79  float offset = traversalState.m_desiredLength - traversalState.m_totalLength;
80  traversalState.m_current.move(offset * cosf(slope), offset * sinf(slope));
81  } else {
82  static const float rad2deg = 180.0f / piFloat;
83  traversalState.m_normalAngle = slope * rad2deg;
84  }
85 
86  traversalState.m_success = true;
87  }
88 }
89 
90 float Path::length()
91 {
92  PathTraversalState traversalState(PathTraversalState::TraversalTotalLength);
93  apply(&traversalState, pathLengthApplierFunction);
94  return traversalState.m_totalLength;
95 }
96 
97 FloatPoint Path::pointAtLength(float length, bool& ok)
98 {
99  PathTraversalState traversalState(PathTraversalState::TraversalPointAtLength);
100  traversalState.m_desiredLength = length;
101  apply(&traversalState, pathLengthApplierFunction);
102  ok = traversalState.m_success;
103  return traversalState.m_current;
104 }
105 
106 float Path::normalAngleAtLength(float length, bool& ok)
107 {
108  PathTraversalState traversalState(PathTraversalState::TraversalNormalAngleAtLength);
109  traversalState.m_desiredLength = length;
110  apply(&traversalState, pathLengthApplierFunction);
111  ok = traversalState.m_success;
112  return traversalState.m_normalAngle;
113 }
114 
115 Path Path::createRoundedRectangle(const FloatRect& rectangle, const FloatSize& roundingRadii)
116 {
117  Path path;
118  float x = rectangle.x();
119  float y = rectangle.y();
120  float width = rectangle.width();
121  float height = rectangle.height();
122  float rx = roundingRadii.width();
123  float ry = roundingRadii.height();
124  if (width <= 0.0f || height <= 0.0f)
125  return path;
126 
127  float dx = rx, dy = ry;
128  // If rx is greater than half of the width of the rectangle
129  // then set rx to half of the width (required in SVG spec)
130  if (dx > width * 0.5f)
131  dx = width * 0.5f;
132 
133  // If ry is greater than half of the height of the rectangle
134  // then set ry to half of the height (required in SVG spec)
135  if (dy > height * 0.5f)
136  dy = height * 0.5f;
137 
138  path.moveTo(FloatPoint(x + dx, y));
139 
140  if (dx < width * 0.5f)
141  path.addLineTo(FloatPoint(x + width - rx, y));
142 
143  path.addBezierCurveTo(FloatPoint(x + width - dx * (1 - QUARTER), y), FloatPoint(x + width, y + dy * (1 - QUARTER)), FloatPoint(x + width, y + dy));
144 
145  if (dy < height * 0.5)
146  path.addLineTo(FloatPoint(x + width, y + height - dy));
147 
148  path.addBezierCurveTo(FloatPoint(x + width, y + height - dy * (1 - QUARTER)), FloatPoint(x + width - dx * (1 - QUARTER), y + height), FloatPoint(x + width - dx, y + height));
149 
150  if (dx < width * 0.5)
151  path.addLineTo(FloatPoint(x + dx, y + height));
152 
153  path.addBezierCurveTo(FloatPoint(x + dx * (1 - QUARTER), y + height), FloatPoint(x, y + height - dy * (1 - QUARTER)), FloatPoint(x, y + height - dy));
154 
155  if (dy < height * 0.5)
156  path.addLineTo(FloatPoint(x, y + dy));
157 
158  path.addBezierCurveTo(FloatPoint(x, y + dy * (1 - QUARTER)), FloatPoint(x + dx * (1 - QUARTER), y), FloatPoint(x + dx, y));
159 
160  path.closeSubpath();
161 
162  return path;
163 }
164 
165 Path Path::createRoundedRectangle(const FloatRect& rectangle, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius)
166 {
167  Path path;
168 
169  float width = rectangle.width();
170  float height = rectangle.height();
171  if (width <= 0.0 || height <= 0.0)
172  return path;
173 
174  if (width < topLeftRadius.width() + topRightRadius.width()
175  || width < bottomLeftRadius.width() + bottomRightRadius.width()
176  || height < topLeftRadius.height() + bottomLeftRadius.height()
177  || height < topRightRadius.height() + bottomRightRadius.height())
178  // If all the radii cannot be accommodated, return a rect.
179  return createRectangle(rectangle);
180 
181  float x = rectangle.x();
182  float y = rectangle.y();
183 
184  path.moveTo(FloatPoint(x + topLeftRadius.width(), y));
185 
186  path.addLineTo(FloatPoint(x + width - topRightRadius.width(), y));
187 
188  path.addBezierCurveTo(FloatPoint(x + width - topRightRadius.width() * (1 - QUARTER), y), FloatPoint(x + width, y + topRightRadius.height() * (1 - QUARTER)), FloatPoint(x + width, y + topRightRadius.height()));
189 
190  path.addLineTo(FloatPoint(x + width, y + height - bottomRightRadius.height()));
191 
192  path.addBezierCurveTo(FloatPoint(x + width, y + height - bottomRightRadius.height() * (1 - QUARTER)), FloatPoint(x + width - bottomRightRadius.width() * (1 - QUARTER), y + height), FloatPoint(x + width - bottomRightRadius.width(), y + height));
193 
194  path.addLineTo(FloatPoint(x + bottomLeftRadius.width(), y + height));
195 
196  path.addBezierCurveTo(FloatPoint(x + bottomLeftRadius.width() * (1 - QUARTER), y + height), FloatPoint(x, y + height - bottomLeftRadius.height() * (1 - QUARTER)), FloatPoint(x, y + height - bottomLeftRadius.height()));
197 
198  path.addLineTo(FloatPoint(x, y + topLeftRadius.height()));
199 
200  path.addBezierCurveTo(FloatPoint(x, y + topLeftRadius.height() * (1 - QUARTER)), FloatPoint(x + topLeftRadius.width() * (1 - QUARTER), y), FloatPoint(x + topLeftRadius.width(), y));
201 
202  path.closeSubpath();
203 
204  return path;
205 }
206 
207 Path Path::createRectangle(const FloatRect& rectangle)
208 {
209  Path path;
210  float x = rectangle.x();
211  float y = rectangle.y();
212  float width = rectangle.width();
213  float height = rectangle.height();
214  if (width <= 0.0f || height <= 0.0f)
215  return path;
216 
217  path.moveTo(FloatPoint(x, y));
218  path.addLineTo(FloatPoint(x + width, y));
219  path.addLineTo(FloatPoint(x + width, y + height));
220  path.addLineTo(FloatPoint(x, y + height));
221  path.closeSubpath();
222 
223  return path;
224 }
225 
226 Path Path::createEllipse(const FloatPoint& center, float rx, float ry)
227 {
228  float cx = center.x();
229  float cy = center.y();
230  Path path;
231  if (rx <= 0.0f || ry <= 0.0f)
232  return path;
233 
234  float x = cx;
235  float y = cy;
236 
237  unsigned step = 0, num = 100;
238  bool running = true;
239  while (running)
240  {
241  if (step == num)
242  {
243  running = false;
244  break;
245  }
246 
247  float angle = static_cast<float>(step) / static_cast<float>(num) * 2.0f * piFloat;
248  x = cx + cosf(angle) * rx;
249  y = cy + sinf(angle) * ry;
250 
251  step++;
252  if (step == 1)
253  path.moveTo(FloatPoint(x, y));
254  else
255  path.addLineTo(FloatPoint(x, y));
256  }
257 
258  path.closeSubpath();
259 
260  return path;
261 }
262 
263 Path Path::createCircle(const FloatPoint& center, float r)
264 {
265  return createEllipse(center, r, r);
266 }
267 
268 Path Path::createLine(const FloatPoint& start, const FloatPoint& end)
269 {
270  Path path;
271  if (start.x() == end.x() && start.y() == end.y())
272  return path;
273 
274  path.moveTo(start);
275  path.addLineTo(end);
276 
277  return path;
278 }
279 
280 }
WebCore::FloatRect
Definition: FloatRect.h:59
WebCore::FloatSize::width
float width() const
Definition: FloatSize.h:56
khtml::Path::createEllipse
static Path createEllipse(const FloatPoint &center, float rx, float ry)
Definition: Path.cpp:226
WebCore::FloatRect::width
float width() const
Definition: FloatRect.h:78
WebCore::PathTraversalState::m_success
bool m_success
Definition: PathTraversalState.h:58
WebCore::FloatRect::height
float height() const
Definition: FloatRect.h:79
khtml::Path::createCircle
static Path createCircle(const FloatPoint &center, float r)
Definition: Path.cpp:263
WebCore::PathTraversalState::m_current
FloatPoint m_current
Definition: PathTraversalState.h:60
WebCore::FloatRect::x
float x() const
Definition: FloatRect.h:76
WebCore::PathTraversalState::TraversalPointAtLength
Definition: PathTraversalState.h:43
khtml::Path::addLineTo
void addLineTo(const FloatPoint &)
Definition: PathQt.cpp:97
WebCore::PathTraversalState::moveTo
float moveTo(const FloatPoint &)
Definition: PathTraversalState.cpp:167
WebCore::FloatSize::height
float height() const
Definition: FloatSize.h:57
WebCore::FloatSize
Definition: FloatSize.h:48
WebCore::PathTraversalState::m_desiredLength
float m_desiredLength
Definition: PathTraversalState.h:67
khtml::Path::addBezierCurveTo
void addBezierCurveTo(const FloatPoint &controlPoint1, const FloatPoint &controlPoint2, const FloatPoint &)
Definition: PathQt.cpp:107
WebCore::PathTraversalState::TraversalNormalAngleAtLength
Definition: PathTraversalState.h:45
WebCore::PathTraversalState::cubicBezierTo
float cubicBezierTo(const FloatPoint &newControl1, const FloatPoint &newControl2, const FloatPoint &newEnd)
Definition: PathTraversalState.cpp:193
WebCore::FloatPoint::move
void move(float dx, float dy)
Definition: FloatPoint.h:74
khtml::Path::pointAtLength
FloatPoint pointAtLength(float length, bool &ok)
Definition: Path.cpp:97
khtml::PathElement
Definition: Path.h:61
khtml::Path::createLine
static Path createLine(const FloatPoint &, const FloatPoint &)
Definition: Path.cpp:268
WebCore::PathTraversalState::quadraticBezierTo
float quadraticBezierTo(const FloatPoint &newControl, const FloatPoint &newEnd)
Definition: PathTraversalState.cpp:180
WebCore::PathTraversalState::m_totalLength
float m_totalLength
Definition: PathTraversalState.h:65
WebCore::FloatPoint
Definition: FloatPoint.h:61
WebCore::PathTraversalState
Definition: PathTraversalState.h:39
WebCore::PathTraversalState::m_previous
FloatPoint m_previous
Definition: PathTraversalState.h:70
khtml::PathElement::points
FloatPoint * points
Definition: Path.h:63
WebCore::PathTraversalState::closeSubpath
float closeSubpath()
Definition: PathTraversalState.cpp:160
WebCore::FloatRect::y
float y() const
Definition: FloatRect.h:77
WebCore::PathTraversalState::m_normalAngle
float m_normalAngle
Definition: PathTraversalState.h:71
khtml::Path::moveTo
void moveTo(const FloatPoint &)
Definition: PathQt.cpp:92
FloatPoint.h
PathTraversalState.h
WebCore::FloatPoint::y
float y() const
Definition: FloatPoint.h:70
khtml::Path::closeSubpath
void closeSubpath()
Definition: PathQt.cpp:119
khtml::Path::apply
void apply(void *info, PathApplierFunction) const
Definition: PathQt.cpp:224
khtml::Path::normalAngleAtLength
float normalAngleAtLength(float length, bool &ok)
Definition: Path.cpp:106
WebCore::FloatPoint::x
float x() const
Definition: FloatPoint.h:69
FloatRect.h
Path.h
khtml::Path::length
float length()
Definition: Path.cpp:90
khtml::Path
Definition: Path.h:68
WebCore::PathTraversalState::lineTo
float lineTo(const FloatPoint &)
Definition: PathTraversalState.cpp:173
WebCore::PathTraversalState::m_action
PathTraversalAction m_action
Definition: PathTraversalState.h:57
QUARTER
const float QUARTER
Definition: Path.cpp:39
khtml::Path::createRectangle
static Path createRectangle(const FloatRect &)
Definition: Path.cpp:207
khtml::Path::createRoundedRectangle
static Path createRoundedRectangle(const FloatRect &, const FloatSize &roundingRadii)
Definition: Path.cpp:115
khtml::PathElement::type
PathElementType type
Definition: Path.h:62
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:51:22 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal