1 /* 2 * Copyright (C) 2007 Ryan Leavengood <leavengood (at) 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 55 GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(BView* view) 56 : m_view(view) 57 { 58 } 59 60 GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate() 61 { 62 } 63 64 void GraphicsContext::platformInit(PlatformGraphicsContext* context) 65 { 66 m_data = new GraphicsContextPlatformPrivate(context); 67 setPaintingDisabled(!context); 68 } 69 70 void GraphicsContext::platformDestroy() 71 { 72 delete m_data; 73 } 74 75 PlatformGraphicsContext* GraphicsContext::platformContext() const 76 { 77 return m_data->m_view; 78 } 79 80 void GraphicsContext::savePlatformState() 81 { 82 m_data->m_view->PushState(); 83 } 84 85 void GraphicsContext::restorePlatformState() 86 { 87 m_data->m_view->PopState(); 88 } 89 90 // Draws a filled rectangle with a stroked border. 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. 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. 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 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 132 void GraphicsContext::strokePath(const Path&) 133 { 134 notImplemented(); 135 } 136 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 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 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 174 void GraphicsContext::fillRect(const FloatRect& rect) 175 { 176 if (paintingDisabled()) 177 return; 178 } 179 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 191 void GraphicsContext::fillPath(const Path&) 192 { 193 notImplemented(); 194 } 195 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 205 void GraphicsContext::drawFocusRing(const Path& path, int width, int offset, const Color& color) 206 { 207 // FIXME: implement 208 } 209 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 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 238 void GraphicsContext::drawLineForTextChecking(const IntPoint&, int width, TextCheckingLineStyle) 239 { 240 if (paintingDisabled()) 241 return; 242 243 notImplemented(); 244 } 245 246 FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect) 247 { 248 notImplemented(); 249 return rect; 250 } 251 252 void GraphicsContext::beginTransparencyLayer(float opacity) 253 { 254 if (paintingDisabled()) 255 return; 256 257 notImplemented(); 258 } 259 260 void GraphicsContext::endTransparencyLayer() 261 { 262 if (paintingDisabled()) 263 return; 264 265 notImplemented(); 266 } 267 268 void GraphicsContext::clearRect(const FloatRect& rect) 269 { 270 if (paintingDisabled()) 271 return; 272 273 notImplemented(); 274 } 275 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 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 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 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 337 void GraphicsContext::setAlpha(float opacity) 338 { 339 if (paintingDisabled()) 340 return; 341 342 notImplemented(); 343 } 344 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 366 void GraphicsContext::clip(const Path& path) 367 { 368 if (paintingDisabled()) 369 return; 370 371 m_data->m_view->ConstrainClippingRegion(path.platformPath()); 372 } 373 374 void GraphicsContext::canvasClip(const Path& path) 375 { 376 clip(path); 377 } 378 379 void GraphicsContext::clipOut(const Path& path) 380 { 381 if (paintingDisabled()) 382 return; 383 384 notImplemented(); 385 } 386 387 void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*) 388 { 389 notImplemented(); 390 } 391 392 AffineTransform GraphicsContext::getCTM() const 393 { 394 notImplemented(); 395 return AffineTransform(); 396 } 397 398 void GraphicsContext::translate(float x, float y) 399 { 400 if (paintingDisabled()) 401 return; 402 403 notImplemented(); 404 } 405 406 void GraphicsContext::rotate(float radians) 407 { 408 if (paintingDisabled()) 409 return; 410 411 notImplemented(); 412 } 413 414 void GraphicsContext::scale(const FloatSize& size) 415 { 416 if (paintingDisabled()) 417 return; 418 419 notImplemented(); 420 } 421 422 void GraphicsContext::clipOut(const IntRect& rect) 423 { 424 if (paintingDisabled()) 425 return; 426 427 notImplemented(); 428 } 429 430 void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) 431 { 432 if (paintingDisabled()) 433 return; 434 435 notImplemented(); 436 } 437 438 void GraphicsContext::concatCTM(const AffineTransform& transform) 439 { 440 if (paintingDisabled()) 441 return; 442 443 notImplemented(); 444 } 445 446 void GraphicsContext::setCTM(const AffineTransform& transform) 447 { 448 if (paintingDisabled()) 449 return; 450 451 notImplemented(); 452 } 453 454 void GraphicsContext::setPlatformShouldAntialias(bool enable) 455 { 456 if (paintingDisabled()) 457 return; 458 459 notImplemented(); 460 } 461 462 void GraphicsContext::setImageInterpolationQuality(InterpolationQuality) 463 { 464 } 465 466 InterpolationQuality GraphicsContext::imageInterpolationQuality() const 467 { 468 notImplemented(); 469 return InterpolationDefault; 470 } 471 472 void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect) 473 { 474 notImplemented(); 475 } 476 477 void GraphicsContext::setPlatformFont(const Font& font) 478 { 479 m_data->m_view->SetFont(font.primaryFont()->platformData().font()); 480 } 481 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 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 510 void GraphicsContext::setPlatformStrokeStyle(StrokeStyle strokeStyle) 511 { 512 // FIXME: see getHaikuStrokeStyle. 513 notImplemented(); 514 } 515 516 void GraphicsContext::setPlatformStrokeThickness(float thickness) 517 { 518 if (paintingDisabled()) 519 return; 520 521 m_data->m_view->SetPenSize(thickness); 522 } 523 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 532 void GraphicsContext::clearPlatformShadow() 533 { 534 notImplemented(); 535 } 536 537 void GraphicsContext::setPlatformShadow(FloatSize const&, float, Color const&, ColorSpace) 538 { 539 notImplemented(); 540 } 541 542 } // namespace WebCore 543 544