2 * Copyright (C) 2007 Kevin Ollivier <kevino@theolliviers.com>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "GraphicsContext.h"
29 #include "FloatRect.h"
32 #include "NotImplemented.h"
34 #include <wtf/MathExtras.h>
40 #include <wx/window.h>
41 #include <wx/dcclient.h>
42 #include <wx/dcgraph.h>
43 #include <wx/graphics.h>
46 #include <Carbon/Carbon.h>
53 int getWxCompositingOperation(CompositeOperator op, bool hasAlpha)
55 // FIXME: Add support for more operators.
56 if (op == CompositeSourceOver && !hasAlpha)
72 static int strokeStyleToWxPenStyle(int p)
76 if (p == DottedStroke)
78 if (p == DashedStroke)
86 class GraphicsContextPlatformPrivate {
88 GraphicsContextPlatformPrivate();
89 ~GraphicsContextPlatformPrivate();
98 wxRegion gtkCurrentClipRgn;
99 wxRegion gtkPaintClipRgn;
102 GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate() :
104 focusRect(IntRect()),
106 gtkCurrentClipRgn(wxRegion()),
107 gtkPaintClipRgn(wxRegion())
111 GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
116 GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
117 : m_common(createGraphicsContextPrivate())
118 , m_data(new GraphicsContextPlatformPrivate)
120 setPaintingDisabled(!context);
122 // Make sure the context starts in sync with our state.
123 setPlatformFillColor(fillColor());
124 setPlatformStrokeColor(strokeColor());
127 m_data->context = (wxGCDC*)context;
129 m_data->context = (wxWindowDC*)context;
133 GraphicsContext::~GraphicsContext()
135 destroyGraphicsContextPrivate(m_common);
139 PlatformGraphicsContext* GraphicsContext::platformContext() const
141 return (PlatformGraphicsContext*)m_data->context;
144 void GraphicsContext::savePlatformState()
149 wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
152 // when everything is working with USE_WXGC, we can remove this
154 CGContextRef context;
155 wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
157 context = (CGContextRef)gc->GetNativeContext();
159 CGContextSaveGState(context);
161 HDC dc = (HDC)m_data->context->GetHDC();
162 m_data->mswDCStateID = ::SaveDC(dc);
164 m_data->gtkCurrentClipRgn = m_data->context->m_currentClippingRegion;
165 m_data->gtkPaintClipRgn = m_data->context->m_paintClippingRegion;
171 void GraphicsContext::restorePlatformState()
176 wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
180 CGContextRef context;
181 wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
183 context = (CGContextRef)gc->GetNativeContext();
185 CGContextRestoreGState(context);
187 HDC dc = (HDC)m_data->context->GetHDC();
188 ::RestoreDC(dc, m_data->mswDCStateID);
190 m_data->context->m_currentClippingRegion = m_data->gtkCurrentClipRgn;
191 m_data->context->m_paintClippingRegion = m_data->gtkPaintClipRgn;
198 // Draws a filled rectangle with a stroked border.
199 void GraphicsContext::drawRect(const IntRect& rect)
201 if (paintingDisabled())
204 m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
205 m_data->context->DrawRectangle(rect.x(), rect.y(), rect.width(), rect.height());
208 // This is only used to draw borders.
209 void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
211 if (paintingDisabled())
214 FloatPoint p1 = point1;
215 FloatPoint p2 = point2;
217 m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
218 m_data->context->DrawLine(point1.x(), point1.y(), point2.x(), point2.y());
221 // This method is only used to draw the little circles used in lists.
222 void GraphicsContext::drawEllipse(const IntRect& rect)
224 if (paintingDisabled())
227 m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
228 m_data->context->DrawEllipse(rect.x(), rect.y(), rect.width(), rect.height());
231 void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
233 if (paintingDisabled())
236 m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
237 m_data->context->DrawEllipticArc(rect.x(), rect.y(), rect.width(), rect.height(), startAngle, angleSpan);
240 void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool shouldAntialias)
242 if (paintingDisabled())
248 wxPoint* polygon = new wxPoint[npoints];
249 for (size_t i = 0; i < npoints; i++)
250 polygon[i] = wxPoint(points[i].x(), points[i].y());
251 m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
252 m_data->context->DrawPolygon((int)npoints, polygon);
256 void GraphicsContext::fillRect(const IntRect& rect, const Color& color)
258 if (paintingDisabled())
261 m_data->context->SetPen(wxPen(color));
262 m_data->context->SetBrush(wxBrush(color));
263 m_data->context->DrawRectangle(rect.x(), rect.y(), rect.width(), rect.height());
266 void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
268 if (paintingDisabled())
271 m_data->context->SetPen(wxPen(color));
272 m_data->context->SetBrush(wxBrush(color));
273 m_data->context->DrawRectangle(rect.x(), rect.y(), rect.width(), rect.height());
276 void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
278 if (paintingDisabled())
284 void GraphicsContext::drawFocusRing(const Color& color)
286 if (paintingDisabled())
292 void GraphicsContext::clip(const IntRect& r)
294 wxWindowDC* windc = dynamic_cast<wxWindowDC*>(m_data->context);
299 wxWindow* window = windc->GetWindow();
301 wxWindow* window = windc->m_owner;
304 wxWindow* parent = window->GetParent();
305 // we need to convert from WebView "global" to WebFrame "local" coords.
306 // FIXME: We only want to go to the top WebView.
308 pos += window->GetPosition();
309 parent = parent->GetParent();
314 m_data->context->SetClippingRegion(r.x() - pos.x, r.y() - pos.y, r.width() + pos.x, r.height() + pos.y);
317 void GraphicsContext::clipOut(const Path&)
322 void GraphicsContext::clipOut(const IntRect&)
327 void GraphicsContext::clipOutEllipseInRect(const IntRect&)
332 void GraphicsContext::setFocusRingClip(const IntRect& r)
334 m_data->focusRect = r;
337 void GraphicsContext::clearFocusRingClip()
339 m_data->focusRect = IntRect();
342 void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing)
344 if (paintingDisabled())
347 IntPoint endPoint = origin + IntSize(width, 0);
348 m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
349 m_data->context->DrawLine(origin.x(), origin.y(), endPoint.x(), endPoint.y());
353 void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& origin, int width, bool grammar)
356 m_data->context->SetPen(wxPen(*wxGREEN, 2, wxLONG_DASH));
358 m_data->context->SetPen(wxPen(*wxRED, 2, wxLONG_DASH));
360 m_data->context->DrawLine(origin.x(), origin.y(), origin.x() + width, origin.y());
363 void GraphicsContext::clip(const Path&)
367 void GraphicsContext::translate(float tx, float ty)
370 if (m_data->context) {
371 wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
372 gc->Translate(tx, ty);
377 void GraphicsContext::rotate(float angle)
380 if (m_data->context) {
381 wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
387 void GraphicsContext::scale(const FloatSize& scale)
390 if (m_data->context) {
391 wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
392 gc->Scale(scale.width(), scale.height());
398 FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
402 wxCoord x = (wxCoord)frect.x();
403 wxCoord y = (wxCoord)frect.y();
405 x = m_data->context->LogicalToDeviceX(x);
406 y = m_data->context->LogicalToDeviceY(y);
407 result.setX((float)x);
408 result.setY((float)y);
409 x = (wxCoord)frect.width();
410 y = (wxCoord)frect.height();
411 x = m_data->context->LogicalToDeviceXRel(x);
412 y = m_data->context->LogicalToDeviceYRel(y);
413 result.setWidth((float)x);
414 result.setHeight((float)y);
418 void GraphicsContext::setURLForRect(const KURL&, const IntRect&)
423 void GraphicsContext::setCompositeOperation(CompositeOperator op)
426 m_data->context->SetLogicalFunction(getWxCompositingOperation(op, false));
429 void GraphicsContext::setPlatformStrokeColor(const Color& color)
431 if (paintingDisabled())
435 m_data->context->SetPen(wxPen(color, strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
438 void GraphicsContext::setPlatformStrokeThickness(float thickness)
440 if (paintingDisabled())
444 m_data->context->SetPen(wxPen(strokeColor(), thickness, strokeStyleToWxPenStyle(strokeStyle())));
448 void GraphicsContext::setPlatformFillColor(const Color& color)
450 if (paintingDisabled())
454 m_data->context->SetBrush(wxBrush(color));
457 void GraphicsContext::concatCTM(const AffineTransform& transform)
459 if (paintingDisabled())