1 /*
2 * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
3 *
4 * All rights reserved.
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 #include "config.h"
29 #include "GraphicsContext.h"
30
31 #include "AffineTransform.h"
32 #include "Color.h"
33 #include "Font.h"
34 #include "FontData.h"
35 #include "NotImplemented.h"
36 #include "Path.h"
37 #include <wtf/text/CString.h>
38 #include <GraphicsDefs.h>
39 #include <Region.h>
40 #include <View.h>
41 #include <Window.h>
42 #include <stdio.h>
43
44
45 namespace WebCore {
46
47 class GraphicsContextPlatformPrivate {
48 public:
49 GraphicsContextPlatformPrivate(BView* view);
50 ~GraphicsContextPlatformPrivate();
51
52 BView* m_view;
53 };
54
GraphicsContextPlatformPrivate(BView * view)55 GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(BView* view)
56 : m_view(view)
57 {
58 }
59
~GraphicsContextPlatformPrivate()60 GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
61 {
62 }
63
platformInit(PlatformGraphicsContext * context)64 void GraphicsContext::platformInit(PlatformGraphicsContext* context)
65 {
66 m_data = new GraphicsContextPlatformPrivate(context);
67 setPaintingDisabled(!context);
68 }
69
platformDestroy()70 void GraphicsContext::platformDestroy()
71 {
72 delete m_data;
73 }
74
platformContext() const75 PlatformGraphicsContext* GraphicsContext::platformContext() const
76 {
77 return m_data->m_view;
78 }
79
savePlatformState()80 void GraphicsContext::savePlatformState()
81 {
82 m_data->m_view->PushState();
83 }
84
restorePlatformState()85 void GraphicsContext::restorePlatformState()
86 {
87 m_data->m_view->PopState();
88 }
89
90 // Draws a filled rectangle with a stroked border.
drawRect(const IntRect & rect)91 void GraphicsContext::drawRect(const IntRect& rect)
92 {
93 if (paintingDisabled())
94 return;
95
96 m_data->m_view->FillRect(rect);
97 if (strokeStyle() != NoStroke)
98 m_data->m_view->StrokeRect(rect, getHaikuStrokeStyle());
99 }
100
101 // This is only used to draw borders.
drawLine(const IntPoint & point1,const IntPoint & point2)102 void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
103 {
104 if (paintingDisabled())
105 return;
106
107 if (strokeStyle() == NoStroke)
108 return;
109
110 m_data->m_view->StrokeLine(point1, point2, getHaikuStrokeStyle());
111 }
112
113 // This method is only used to draw the little circles used in lists.
drawEllipse(const IntRect & rect)114 void GraphicsContext::drawEllipse(const IntRect& rect)
115 {
116 if (paintingDisabled())
117 return;
118
119 m_data->m_view->FillEllipse(rect);
120 if (strokeStyle() != NoStroke)
121 m_data->m_view->StrokeEllipse(rect, getHaikuStrokeStyle());
122 }
123
strokeArc(const IntRect & rect,int startAngle,int angleSpan)124 void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
125 {
126 if (paintingDisabled())
127 return;
128
129 m_data->m_view->StrokeArc(rect, startAngle, angleSpan, getHaikuStrokeStyle());
130 }
131
strokePath(const Path &)132 void GraphicsContext::strokePath(const Path&)
133 {
134 notImplemented();
135 }
136
drawConvexPolygon(size_t pointsLength,const FloatPoint * points,bool shouldAntialias)137 void GraphicsContext::drawConvexPolygon(size_t pointsLength, const FloatPoint* points, bool shouldAntialias)
138 {
139 if (paintingDisabled())
140 return;
141
142 BPoint bPoints[pointsLength];
143 for (size_t i = 0; i < pointsLength; i++)
144 bPoints[i] = points[i];
145
146 m_data->m_view->FillPolygon(bPoints, pointsLength);
147 if (strokeStyle() != NoStroke)
148 // Stroke with low color
149 m_data->m_view->StrokePolygon(bPoints, pointsLength, true, getHaikuStrokeStyle());
150 }
151
clipConvexPolygon(size_t numPoints,const FloatPoint * points,bool antialiased)152 void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points, bool antialiased)
153 {
154 if (paintingDisabled())
155 return;
156
157 if (numPoints <= 1)
158 return;
159
160 // FIXME: IMPLEMENT!!
161 }
162
fillRect(const FloatRect & rect,const Color & color,ColorSpace colorSpace)163 void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
164 {
165 if (paintingDisabled())
166 return;
167
168 rgb_color oldColor = m_data->m_view->HighColor();
169 m_data->m_view->SetHighColor(color);
170 m_data->m_view->FillRect(rect);
171 m_data->m_view->SetHighColor(oldColor);
172 }
173
fillRect(const FloatRect & rect)174 void GraphicsContext::fillRect(const FloatRect& rect)
175 {
176 if (paintingDisabled())
177 return;
178 }
179
fillRoundedRect(const IntRect & rect,const IntSize & topLeft,const IntSize & topRight,const IntSize & bottomLeft,const IntSize & bottomRight,const Color & color,ColorSpace colorSpace)180 void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
181 {
182 if (paintingDisabled() || !color.alpha())
183 return;
184
185 notImplemented();
186 // FIXME: A simple implementation could just use FillRoundRect if all
187 // the sizes are the same, or even if they are not. Otherwise several
188 // FillRect and FillArc calls are needed.
189 }
190
fillPath(const Path &)191 void GraphicsContext::fillPath(const Path&)
192 {
193 notImplemented();
194 }
195
clip(const FloatRect & rect)196 void GraphicsContext::clip(const FloatRect& rect)
197 {
198 if (paintingDisabled())
199 return;
200
201 BRegion region(rect);
202 m_data->m_view->ConstrainClippingRegion(®ion);
203 }
204
drawFocusRing(const Path & path,int width,int offset,const Color & color)205 void GraphicsContext::drawFocusRing(const Path& path, int width, int offset, const Color& color)
206 {
207 // FIXME: implement
208 }
209
drawFocusRing(const Vector<IntRect> & rects,int,int,const Color & color)210 void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int /* width */, int /* offset */, const Color& color)
211 {
212 if (paintingDisabled())
213 return;
214
215 unsigned rectCount = rects.size();
216
217 // FIXME: maybe we should implement this with BShape?
218
219 if (rects.size() > 1) {
220 BRegion region;
221 for (int i = 0; i < rectCount; ++i)
222 region.Include(BRect(rects[i]));
223
224 m_data->m_view->SetHighColor(color);
225 m_data->m_view->StrokeRect(region.Frame(), B_MIXED_COLORS);
226 }
227 }
228
drawLineForText(const IntPoint & origin,int width,bool printing)229 void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing)
230 {
231 if (paintingDisabled())
232 return;
233
234 IntPoint endPoint = origin + IntSize(width, 0);
235 drawLine(origin, endPoint);
236 }
237
drawLineForTextChecking(const IntPoint &,int width,TextCheckingLineStyle)238 void GraphicsContext::drawLineForTextChecking(const IntPoint&, int width, TextCheckingLineStyle)
239 {
240 if (paintingDisabled())
241 return;
242
243 notImplemented();
244 }
245
roundToDevicePixels(const FloatRect & rect)246 FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
247 {
248 notImplemented();
249 return rect;
250 }
251
beginTransparencyLayer(float opacity)252 void GraphicsContext::beginTransparencyLayer(float opacity)
253 {
254 if (paintingDisabled())
255 return;
256
257 notImplemented();
258 }
259
endTransparencyLayer()260 void GraphicsContext::endTransparencyLayer()
261 {
262 if (paintingDisabled())
263 return;
264
265 notImplemented();
266 }
267
clearRect(const FloatRect & rect)268 void GraphicsContext::clearRect(const FloatRect& rect)
269 {
270 if (paintingDisabled())
271 return;
272
273 notImplemented();
274 }
275
strokeRect(const FloatRect & rect,float width)276 void GraphicsContext::strokeRect(const FloatRect& rect, float width)
277 {
278 if (paintingDisabled())
279 return;
280
281 float oldSize = m_data->m_view->PenSize();
282 m_data->m_view->SetPenSize(width);
283 m_data->m_view->StrokeRect(rect, getHaikuStrokeStyle());
284 m_data->m_view->SetPenSize(oldSize);
285 }
286
setLineCap(LineCap lineCap)287 void GraphicsContext::setLineCap(LineCap lineCap)
288 {
289 if (paintingDisabled())
290 return;
291
292 cap_mode mode = B_BUTT_CAP;
293 switch (lineCap) {
294 case RoundCap:
295 mode = B_ROUND_CAP;
296 break;
297 case SquareCap:
298 mode = B_SQUARE_CAP;
299 break;
300 case ButtCap:
301 default:
302 break;
303 }
304
305 m_data->m_view->SetLineMode(mode, m_data->m_view->LineJoinMode(), m_data->m_view->LineMiterLimit());
306 }
307
setLineJoin(LineJoin lineJoin)308 void GraphicsContext::setLineJoin(LineJoin lineJoin)
309 {
310 if (paintingDisabled())
311 return;
312
313 join_mode mode = B_MITER_JOIN;
314 switch (lineJoin) {
315 case RoundJoin:
316 mode = B_ROUND_JOIN;
317 break;
318 case BevelJoin:
319 mode = B_BEVEL_JOIN;
320 break;
321 case MiterJoin:
322 default:
323 break;
324 }
325
326 m_data->m_view->SetLineMode(m_data->m_view->LineCapMode(), mode, m_data->m_view->LineMiterLimit());
327 }
328
setMiterLimit(float limit)329 void GraphicsContext::setMiterLimit(float limit)
330 {
331 if (paintingDisabled())
332 return;
333
334 m_data->m_view->SetLineMode(m_data->m_view->LineCapMode(), m_data->m_view->LineJoinMode(), limit);
335 }
336
setAlpha(float opacity)337 void GraphicsContext::setAlpha(float opacity)
338 {
339 if (paintingDisabled())
340 return;
341
342 notImplemented();
343 }
344
setPlatformCompositeOperation(CompositeOperator op)345 void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op)
346 {
347 if (paintingDisabled())
348 return;
349
350 drawing_mode mode = B_OP_COPY;
351 switch (op) {
352 case CompositeClear:
353 case CompositeCopy:
354 // Use the default above
355 break;
356 case CompositeSourceOver:
357 mode = B_OP_OVER;
358 break;
359 default:
360 printf("GraphicsContext::setPlatformCompositeOperation: Unsupported composite operation %s\n",
361 compositeOperatorName(op).utf8().data());
362 }
363 m_data->m_view->SetDrawingMode(mode);
364 }
365
clip(const Path & path)366 void GraphicsContext::clip(const Path& path)
367 {
368 if (paintingDisabled())
369 return;
370
371 m_data->m_view->ConstrainClippingRegion(path.platformPath());
372 }
373
canvasClip(const Path & path)374 void GraphicsContext::canvasClip(const Path& path)
375 {
376 clip(path);
377 }
378
clipOut(const Path & path)379 void GraphicsContext::clipOut(const Path& path)
380 {
381 if (paintingDisabled())
382 return;
383
384 notImplemented();
385 }
386
clipToImageBuffer(const FloatRect &,const ImageBuffer *)387 void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*)
388 {
389 notImplemented();
390 }
391
getCTM() const392 AffineTransform GraphicsContext::getCTM() const
393 {
394 notImplemented();
395 return AffineTransform();
396 }
397
translate(float x,float y)398 void GraphicsContext::translate(float x, float y)
399 {
400 if (paintingDisabled())
401 return;
402
403 notImplemented();
404 }
405
rotate(float radians)406 void GraphicsContext::rotate(float radians)
407 {
408 if (paintingDisabled())
409 return;
410
411 notImplemented();
412 }
413
scale(const FloatSize & size)414 void GraphicsContext::scale(const FloatSize& size)
415 {
416 if (paintingDisabled())
417 return;
418
419 notImplemented();
420 }
421
clipOut(const IntRect & rect)422 void GraphicsContext::clipOut(const IntRect& rect)
423 {
424 if (paintingDisabled())
425 return;
426
427 notImplemented();
428 }
429
addInnerRoundedRectClip(const IntRect & rect,int thickness)430 void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
431 {
432 if (paintingDisabled())
433 return;
434
435 notImplemented();
436 }
437
concatCTM(const AffineTransform & transform)438 void GraphicsContext::concatCTM(const AffineTransform& transform)
439 {
440 if (paintingDisabled())
441 return;
442
443 notImplemented();
444 }
445
setCTM(const AffineTransform & transform)446 void GraphicsContext::setCTM(const AffineTransform& transform)
447 {
448 if (paintingDisabled())
449 return;
450
451 notImplemented();
452 }
453
setPlatformShouldAntialias(bool enable)454 void GraphicsContext::setPlatformShouldAntialias(bool enable)
455 {
456 if (paintingDisabled())
457 return;
458
459 notImplemented();
460 }
461
setImageInterpolationQuality(InterpolationQuality)462 void GraphicsContext::setImageInterpolationQuality(InterpolationQuality)
463 {
464 }
465
imageInterpolationQuality() const466 InterpolationQuality GraphicsContext::imageInterpolationQuality() const
467 {
468 notImplemented();
469 return InterpolationDefault;
470 }
471
setURLForRect(const KURL & link,const IntRect & destRect)472 void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
473 {
474 notImplemented();
475 }
476
setPlatformFont(const Font & font)477 void GraphicsContext::setPlatformFont(const Font& font)
478 {
479 m_data->m_view->SetFont(font.primaryFont()->platformData().font());
480 }
481
setPlatformStrokeColor(const Color & color,ColorSpace colorSpace)482 void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace)
483 {
484 if (paintingDisabled())
485 return;
486
487 m_data->m_view->SetHighColor(color);
488 }
489
getHaikuStrokeStyle()490 pattern GraphicsContext::getHaikuStrokeStyle()
491 {
492 switch (strokeStyle()) {
493 case SolidStroke:
494 return B_SOLID_HIGH;
495 break;
496 case DottedStroke:
497 return B_MIXED_COLORS;
498 break;
499 case DashedStroke:
500 // FIXME: use a better dashed stroke!
501 notImplemented();
502 return B_MIXED_COLORS;
503 break;
504 default:
505 return B_SOLID_LOW;
506 break;
507 }
508 }
509
setPlatformStrokeStyle(StrokeStyle strokeStyle)510 void GraphicsContext::setPlatformStrokeStyle(StrokeStyle strokeStyle)
511 {
512 // FIXME: see getHaikuStrokeStyle.
513 notImplemented();
514 }
515
setPlatformStrokeThickness(float thickness)516 void GraphicsContext::setPlatformStrokeThickness(float thickness)
517 {
518 if (paintingDisabled())
519 return;
520
521 m_data->m_view->SetPenSize(thickness);
522 }
523
setPlatformFillColor(const Color & color,ColorSpace colorSpace)524 void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace)
525 {
526 if (paintingDisabled())
527 return;
528
529 m_data->m_view->SetHighColor(color);
530 }
531
clearPlatformShadow()532 void GraphicsContext::clearPlatformShadow()
533 {
534 notImplemented();
535 }
536
setPlatformShadow(FloatSize const &,float,Color const &,ColorSpace)537 void GraphicsContext::setPlatformShadow(FloatSize const&, float, Color const&, ColorSpace)
538 {
539 notImplemented();
540 }
541
542 } // namespace WebCore
543
544