1/*
2 * Copyright (C) 2007 Kevin Ollivier  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "Path.h"
28
29#include "AffineTransform.h"
30#include "FloatPoint.h"
31#include "FloatRect.h"
32#include "NotImplemented.h"
33#include "StrokeStyleApplier.h"
34
35#include <stdio.h>
36
37#include <wx/defs.h>
38#include <wx/graphics.h>
39
40namespace WebCore {
41
42int getWxWindRuleForWindRule(WindRule rule)
43{
44     if (rule == RULE_EVENODD)
45        return wxODDEVEN_RULE;
46
47    return wxWINDING_RULE;
48}
49
50Path::Path()
51{
52    m_path = 0;
53    // NB: This only supports the 'default' renderer as determined by wx on
54    // each platform. If an app uses a non-default renderer (e.g. Cairo on Win),
55    // there will be problems, but there's no way we can determine which
56    // renderer an app is using right now with wx API, so we will just handle
57    // the common case.
58#if USE(WXGC)
59    wxGraphicsRenderer* renderer = wxGraphicsRenderer::GetDefaultRenderer();
60    if (renderer) {
61        wxGraphicsPath path = renderer->CreatePath();
62        m_path = new wxGraphicsPath(path);
63    }
64#endif
65}
66
67Path::~Path()
68{
69    clear();
70}
71
72Path::Path(const Path& path)
73{
74    m_path = new wxGraphicsPath(*path.m_path);
75}
76
77bool Path::contains(const FloatPoint& point, const WindRule rule) const
78{
79#if USE(WXGC)
80    if (m_path) {
81#if wxCHECK_VERSION(2,9,0)
82        return m_path->Contains(point.x(), point.y(), static_cast<wxPolygonFillMode>(getWxWindRuleForWindRule(rule)));
83#else
84        return m_path->Contains(point.x(), point.y(), getWxWindRuleForWindRule(rule));
85#endif
86    }
87#endif
88    return false;
89}
90
91void Path::translate(const FloatSize&)
92{
93    notImplemented();
94}
95
96FloatRect Path::boundingRect() const
97{
98#if USE(WXGC)
99    if (m_path) {
100        return m_path->GetBox();
101    }
102#endif
103
104    return FloatRect();
105}
106
107FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
108{
109    notImplemented();
110    return FloatRect();
111}
112
113Path& Path::operator=(const Path&)
114{
115    notImplemented();
116    return*this;
117}
118
119void Path::clear()
120{
121    if (m_path)
122        delete m_path;
123
124#if USE(WXGC)
125    wxGraphicsRenderer* renderer = wxGraphicsRenderer::GetDefaultRenderer();
126    if (renderer) {
127        wxGraphicsPath path = renderer->CreatePath();
128        m_path = new wxGraphicsPath(path);
129    }
130#endif
131}
132
133void Path::moveTo(const FloatPoint& point)
134{
135#if USE(WXGC)
136    if (m_path)
137        m_path->MoveToPoint(point.x(), point.y());
138#endif
139}
140
141void Path::addLineTo(const FloatPoint& point)
142{
143#if USE(WXGC)
144    if (m_path)
145        m_path->AddLineToPoint(point.x(), point.y());
146#endif
147}
148
149void Path::addQuadCurveTo(const FloatPoint& control, const FloatPoint& end)
150{
151#if USE(WXGC)
152    if (m_path)
153        m_path->AddQuadCurveToPoint(control.x(), control.y(), end.x(), end.y());
154#endif
155}
156
157void Path::addBezierCurveTo(const FloatPoint& control1, const FloatPoint& control2, const FloatPoint& end)
158{
159#if USE(WXGC)
160    if (m_path)
161        m_path->AddCurveToPoint(control1.x(), control1.y(), control2.x(), control2.y(), end.x(), end.y());
162#endif
163}
164
165void Path::addArcTo(const FloatPoint& point1, const FloatPoint& point2, float radius)
166{
167#if USE(WXGC)
168    if (m_path)
169        m_path->AddArcToPoint(point1.x(), point1.y(), point2.x(), point2.y(), radius);
170#endif
171}
172
173void Path::closeSubpath()
174{
175#if USE(WXGC)
176    if (m_path)
177        m_path->CloseSubpath();
178#endif
179}
180
181void Path::addArc(const FloatPoint& point, float radius, float startAngle, float endAngle, bool clockwise)
182{
183#if USE(WXGC)
184    if (m_path)
185        m_path->AddArc(point.x(), point.y(), radius, startAngle, endAngle, clockwise);
186#endif
187}
188
189void Path::addRect(const FloatRect& rect)
190{
191#if USE(WXGC)
192    if (m_path)
193        m_path->AddRectangle(rect.x(), rect.y(), rect.width(), rect.height());
194#endif
195}
196
197void Path::addEllipse(const FloatRect& rect)
198{
199#if USE(WXGC)
200    if (m_path)
201        m_path->AddEllipse(rect.x(), rect.y(), rect.width(), rect.height());
202#endif
203}
204
205void Path::transform(const AffineTransform& transform)
206{
207#if USE(WXGC)
208    if (m_path)
209        m_path->Transform(transform);
210#endif
211}
212
213void Path::apply(void* info, PathApplierFunction function) const
214{
215    notImplemented();
216}
217
218bool Path::isEmpty() const
219{
220#if USE(WXGC)
221    if (m_path) {
222        wxDouble width, height;
223        m_path->GetBox(NULL, NULL, &width, &height);
224        return (width == 0 && height == 0);
225    }
226#endif
227    return true;
228}
229
230bool Path::hasCurrentPoint() const
231{
232    return !isEmpty();
233}
234
235}
236