a1be8cb227a83aac855d3650d797a528d43673ac
[WebKit-https.git] / WebCore / platform / GraphicsContext.cpp
1 /*
2  * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.  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 "GraphicsContext.h"
28
29 #include "DeprecatedString.h"
30 #include "Font.h"
31
32 using namespace std;
33
34 namespace WebCore {
35
36 struct GraphicsContextState {
37     GraphicsContextState() : fillColor(Color::black), paintingDisabled(false) { }
38     Font font;
39     Pen pen;
40     Color fillColor;
41     bool paintingDisabled;
42 };
43         
44 class GraphicsContextPrivate {
45 public:
46     GraphicsContextPrivate();
47     
48     GraphicsContextState state;
49     Vector<GraphicsContextState> stack;
50     Vector<IntRect> m_focusRingRects;
51     int m_focusRingWidth;
52     int m_focusRingOffset;
53     bool m_usesInactiveTextBackgroundColor;
54     bool m_updatingControlTints;
55 };
56
57 GraphicsContextPrivate::GraphicsContextPrivate()
58     : m_focusRingWidth(0)
59     , m_focusRingOffset(0)
60     , m_usesInactiveTextBackgroundColor(false)
61     , m_updatingControlTints(false)
62 {
63 }
64
65 GraphicsContextPrivate* GraphicsContext::createGraphicsContextPrivate()
66 {
67     return new GraphicsContextPrivate;
68 }
69
70 void GraphicsContext::destroyGraphicsContextPrivate(GraphicsContextPrivate* deleteMe)
71 {
72     delete deleteMe;
73 }
74
75 void GraphicsContext::save()
76 {
77     if (paintingDisabled())
78         return;
79
80     m_common->stack.append(m_common->state);
81     
82     savePlatformState();
83 }
84
85 void GraphicsContext::restore()
86 {
87     if (paintingDisabled())
88         return;
89
90     if (m_common->stack.isEmpty()) {
91         LOG_ERROR("ERROR void GraphicsContext::restore() stack is empty");
92         return;
93     }
94     m_common->state = m_common->stack.last();
95     m_common->stack.removeLast();
96     
97     restorePlatformState();
98 }
99
100 const Font& GraphicsContext::font() const
101 {
102     return m_common->state.font;
103 }
104
105 void GraphicsContext::setFont(const Font& aFont)
106 {
107     m_common->state.font = aFont;
108 }
109
110 const Pen& GraphicsContext::pen() const
111 {
112     return m_common->state.pen;
113 }
114
115 void GraphicsContext::setPen(const Pen& pen)
116 {
117     m_common->state.pen = pen;
118 }
119
120 void GraphicsContext::setPen(Pen::PenStyle style)
121 {
122     m_common->state.pen.setStyle(style);
123     m_common->state.pen.setColor(Color::black);
124     m_common->state.pen.setWidth(0);
125 }
126
127 void GraphicsContext::setPen(RGBA32 rgb)
128 {
129     m_common->state.pen.setStyle(Pen::SolidLine);
130     m_common->state.pen.setColor(rgb);
131     m_common->state.pen.setWidth(0);
132 }
133
134 void GraphicsContext::setFillColor(const Color& color)
135 {
136     m_common->state.fillColor = color;
137 }
138
139 Color GraphicsContext::fillColor() const
140 {
141     return m_common->state.fillColor;
142 }
143
144 void GraphicsContext::setUsesInactiveTextBackgroundColor(bool u)
145 {
146     m_common->m_usesInactiveTextBackgroundColor = u;
147 }
148
149 bool GraphicsContext::usesInactiveTextBackgroundColor() const
150 {
151     return m_common->m_usesInactiveTextBackgroundColor;
152 }
153
154 bool GraphicsContext::updatingControlTints() const
155 {
156     return m_common->m_updatingControlTints;
157 }
158
159 void GraphicsContext::setUpdatingControlTints(bool b)
160 {
161     setPaintingDisabled(b);
162     m_common->m_updatingControlTints = b;
163 }
164
165 void GraphicsContext::setPaintingDisabled(bool f)
166 {
167     m_common->state.paintingDisabled = f;
168 }
169
170 bool GraphicsContext::paintingDisabled() const
171 {
172     return m_common->state.paintingDisabled;
173 }
174
175 void GraphicsContext::drawImage(Image* image, const IntPoint& p, CompositeOperator op)
176 {        
177     drawImage(image, p, IntRect(0, 0, -1, -1), op);
178 }
179
180 void GraphicsContext::drawImage(Image* image, const IntRect& r, CompositeOperator op)
181 {
182     drawImage(image, r, IntRect(0, 0, -1, -1), op);
183 }
184
185 void GraphicsContext::drawImage(Image* image, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op)
186 {
187     drawImage(image, IntRect(dest, srcRect.size()), srcRect, op);
188 }
189
190 void GraphicsContext::drawImage(Image* image, const IntRect& dest, const IntRect& srcRect, CompositeOperator op)
191 {
192     drawImage(image, FloatRect(dest), srcRect, op);
193 }
194
195 void GraphicsContext::drawText(const TextRun& run, const IntPoint& point, int tabWidth, int xpos, int toAdd,
196                                TextDirection d, bool visuallyOrdered)
197 {
198     if (paintingDisabled())
199         return;
200     
201     font().drawText(this, run, point, tabWidth, xpos, toAdd, d, visuallyOrdered);
202 }
203
204 void GraphicsContext::drawHighlightForText(const TextRun& run, const IntPoint& point, int h, int tabWidth, int xpos, int toAdd,
205                                            TextDirection d, bool visuallyOrdered, const Color& backgroundColor)
206 {
207     if (paintingDisabled())
208         return;
209
210     fillRect(font().selectionRectForText(run, point, h, tabWidth, xpos, toAdd, d == RTL, visuallyOrdered), backgroundColor);
211 }
212
213 void GraphicsContext::drawLineForMisspelling(const IntPoint& point, int width)
214 {
215     if (paintingDisabled())
216         return;
217
218     return font().drawLineForMisspelling(this, point, width);
219 }
220
221 int GraphicsContext::misspellingLineThickness()
222 {
223     return font().misspellingLineThickness(this);
224 }
225
226 void GraphicsContext::initFocusRing(int width, int offset)
227 {
228     if (paintingDisabled())
229         return;
230     clearFocusRing();
231     
232     m_common->m_focusRingWidth = width;
233     m_common->m_focusRingOffset = offset;
234 }
235
236 void GraphicsContext::clearFocusRing()
237 {
238     m_common->m_focusRingRects.clear();
239 }
240
241 void GraphicsContext::addFocusRingRect(const IntRect& rect)
242 {
243     if (paintingDisabled() || rect.isEmpty())
244         return;
245     m_common->m_focusRingRects.append(rect);
246 }
247
248 int GraphicsContext::focusRingWidth() const
249 {
250     return m_common->m_focusRingWidth;
251 }
252
253 int GraphicsContext::focusRingOffset() const
254 {
255     return m_common->m_focusRingOffset;
256 }
257
258 const Vector<IntRect>& GraphicsContext::focusRingRects() const
259 {
260     return m_common->m_focusRingRects;
261 }
262
263 void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op)
264 {
265     if (paintingDisabled())
266         return;
267
268     float tsw = src.width();
269     float tsh = src.height();
270     float tw = dest.width();
271     float th = dest.height();
272         
273     if (tsw == -1)
274         tsw = image->width();
275     if (tsh == -1)
276         tsh = image->height();
277
278     if (tw == -1)
279         tw = image->width();
280     if (th == -1)
281         th = image->height();
282
283     image->draw(this, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), op);
284 }
285
286 void GraphicsContext::drawTiledImage(Image* image, const IntRect& rect, const IntPoint& srcPoint, const IntSize& tileSize)
287 {
288     if (paintingDisabled())
289         return;
290
291     image->drawTiled(this, rect, srcPoint, tileSize);
292 }
293
294 void GraphicsContext::drawTiledImage(Image* image, const IntRect& dest, const IntRect& srcRect, Image::TileRule hRule, Image::TileRule vRule)
295 {
296     if (paintingDisabled())
297         return;
298
299     if (hRule == Image::StretchTile && vRule == Image::StretchTile)
300         // Just do a scale.
301         return drawImage(image, dest, srcRect);
302
303     image->drawTiled(this, dest, srcRect, hRule, vRule);
304 }
305
306 }