1 /* 2 * Copyright 2001-2019, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marc Flerackers (mflerackers@androme.be) 7 * Stefano Ceccherini (stefano.ceccherini@gmail.com) 8 * Marcus Overhagen <marcus@overhagen.de> 9 * Julian Harnath <julian.harnath@rwth-aachen.de> 10 * Stephan Aßmus <superstippi@gmx.de> 11 */ 12 13 #include "ServerPicture.h" 14 15 #include <new> 16 #include <stdio.h> 17 #include <stack> 18 19 #include "AlphaMask.h" 20 #include "DrawingEngine.h" 21 #include "DrawState.h" 22 #include "GlobalFontManager.h" 23 #include "Layer.h" 24 #include "ServerApp.h" 25 #include "ServerBitmap.h" 26 #include "ServerFont.h" 27 #include "ServerTokenSpace.h" 28 #include "View.h" 29 #include "Window.h" 30 31 #include <LinkReceiver.h> 32 #include <OffsetFile.h> 33 #include <ObjectListPrivate.h> 34 #include <PicturePlayer.h> 35 #include <PictureProtocol.h> 36 #include <PortLink.h> 37 #include <ServerProtocol.h> 38 #include <ShapePrivate.h> 39 #include <StackOrHeapArray.h> 40 41 #include <Bitmap.h> 42 #include <Debug.h> 43 #include <List.h> 44 #include <Shape.h> 45 46 47 using std::stack; 48 49 50 class ShapePainter : public BShapeIterator { 51 public: 52 ShapePainter(Canvas* canvas, BGradient* gradient); 53 virtual ~ShapePainter(); 54 55 status_t Iterate(const BShape* shape); 56 57 virtual status_t IterateMoveTo(BPoint* point); 58 virtual status_t IterateLineTo(int32 lineCount, BPoint* linePts); 59 virtual status_t IterateBezierTo(int32 bezierCount, BPoint* bezierPts); 60 virtual status_t IterateClose(); 61 virtual status_t IterateArcTo(float& rx, float& ry, 62 float& angle, bool largeArc, bool counterClockWise, BPoint& point); 63 64 void Draw(BRect frame, bool filled); 65 66 private: 67 Canvas* fCanvas; 68 BGradient* fGradient; 69 stack<uint32> fOpStack; 70 stack<BPoint> fPtStack; 71 }; 72 73 74 ShapePainter::ShapePainter(Canvas* canvas, BGradient* gradient) 75 : 76 fCanvas(canvas), 77 fGradient(gradient) 78 { 79 } 80 81 82 ShapePainter::~ShapePainter() 83 { 84 } 85 86 87 status_t 88 ShapePainter::Iterate(const BShape* shape) 89 { 90 // this class doesn't modify the shape data 91 return BShapeIterator::Iterate(const_cast<BShape*>(shape)); 92 } 93 94 95 status_t 96 ShapePainter::IterateMoveTo(BPoint* point) 97 { 98 try { 99 fOpStack.push(OP_MOVETO); 100 fPtStack.push(*point); 101 } catch (std::bad_alloc&) { 102 return B_NO_MEMORY; 103 } 104 105 return B_OK; 106 } 107 108 109 status_t 110 ShapePainter::IterateLineTo(int32 lineCount, BPoint* linePts) 111 { 112 try { 113 fOpStack.push(OP_LINETO | lineCount); 114 for (int32 i = 0; i < lineCount; i++) 115 fPtStack.push(linePts[i]); 116 } catch (std::bad_alloc&) { 117 return B_NO_MEMORY; 118 } 119 120 return B_OK; 121 } 122 123 124 status_t 125 ShapePainter::IterateBezierTo(int32 bezierCount, BPoint* bezierPts) 126 { 127 bezierCount *= 3; 128 try { 129 fOpStack.push(OP_BEZIERTO | bezierCount); 130 for (int32 i = 0; i < bezierCount; i++) 131 fPtStack.push(bezierPts[i]); 132 } catch (std::bad_alloc&) { 133 return B_NO_MEMORY; 134 } 135 136 return B_OK; 137 } 138 139 140 status_t 141 ShapePainter::IterateArcTo(float& rx, float& ry, 142 float& angle, bool largeArc, bool counterClockWise, BPoint& point) 143 { 144 uint32 op; 145 if (largeArc) { 146 if (counterClockWise) 147 op = OP_LARGE_ARC_TO_CCW; 148 else 149 op = OP_LARGE_ARC_TO_CW; 150 } else { 151 if (counterClockWise) 152 op = OP_SMALL_ARC_TO_CCW; 153 else 154 op = OP_SMALL_ARC_TO_CW; 155 } 156 157 try { 158 fOpStack.push(op | 3); 159 fPtStack.push(BPoint(rx, ry)); 160 fPtStack.push(BPoint(angle, 0)); 161 fPtStack.push(point); 162 } catch (std::bad_alloc&) { 163 return B_NO_MEMORY; 164 } 165 166 return B_OK; 167 } 168 169 170 status_t 171 ShapePainter::IterateClose() 172 { 173 try { 174 fOpStack.push(OP_CLOSE); 175 } catch (std::bad_alloc&) { 176 return B_NO_MEMORY; 177 } 178 179 return B_OK; 180 } 181 182 183 void 184 ShapePainter::Draw(BRect frame, bool filled) 185 { 186 // We're going to draw the currently iterated shape. 187 // TODO: This can be more efficient by skipping the conversion. 188 int32 opCount = fOpStack.size(); 189 int32 ptCount = fPtStack.size(); 190 191 if (opCount > 0 && ptCount > 0) { 192 int32 i; 193 uint32* opList = new(std::nothrow) uint32[opCount]; 194 if (opList == NULL) 195 return; 196 197 BPoint* ptList = new(std::nothrow) BPoint[ptCount]; 198 if (ptList == NULL) { 199 delete[] opList; 200 return; 201 } 202 203 for (i = opCount - 1; i >= 0; i--) { 204 opList[i] = fOpStack.top(); 205 fOpStack.pop(); 206 } 207 208 for (i = ptCount - 1; i >= 0; i--) { 209 ptList[i] = fPtStack.top(); 210 fPtStack.pop(); 211 } 212 213 // this might seem a bit weird, but under R5, the shapes 214 // are always offset by the current pen location 215 BPoint screenOffset = fCanvas->CurrentState()->PenLocation(); 216 frame.OffsetBy(screenOffset); 217 218 const SimpleTransform transform = fCanvas->PenToScreenTransform(); 219 transform.Apply(&screenOffset); 220 transform.Apply(&frame); 221 222 /* stroked gradients are not yet supported */ 223 if (fGradient != NULL && filled) { 224 fCanvas->GetDrawingEngine()->FillShape(frame, opCount, opList, 225 ptCount, ptList, *fGradient, screenOffset, fCanvas->Scale()); 226 } else { 227 fCanvas->GetDrawingEngine()->DrawShape(frame, opCount, opList, 228 ptCount, ptList, filled, screenOffset, fCanvas->Scale()); 229 } 230 231 delete[] opList; 232 delete[] ptList; 233 } 234 } 235 236 237 // #pragma mark - drawing functions 238 239 240 static void 241 get_polygon_frame(const BPoint* points, uint32 numPoints, BRect* _frame) 242 { 243 ASSERT(numPoints > 0); 244 245 float left = points->x; 246 float top = points->y; 247 float right = left; 248 float bottom = top; 249 250 points++; 251 numPoints--; 252 253 while (numPoints--) { 254 if (points->x < left) 255 left = points->x; 256 if (points->x > right) 257 right = points->x; 258 if (points->y < top) 259 top = points->y; 260 if (points->y > bottom) 261 bottom = points->y; 262 points++; 263 } 264 265 _frame->Set(left, top, right, bottom); 266 } 267 268 269 static void 270 move_pen_by(void* _canvas, const BPoint& delta) 271 { 272 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 273 canvas->CurrentState()->SetPenLocation( 274 canvas->CurrentState()->PenLocation() + delta); 275 } 276 277 278 static void 279 stroke_line(void* _canvas, const BPoint& _start, const BPoint& _end) 280 { 281 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 282 BPoint start = _start; 283 BPoint end = _end; 284 285 const SimpleTransform transform = canvas->PenToScreenTransform(); 286 transform.Apply(&start); 287 transform.Apply(&end); 288 canvas->GetDrawingEngine()->StrokeLine(start, end); 289 290 canvas->CurrentState()->SetPenLocation(_end); 291 // the DrawingEngine/Painter does not need to be updated, since this 292 // effects only the view->screen coord conversion, which is handled 293 // by the view only 294 } 295 296 297 static void 298 draw_rect(void* _canvas, const BRect& _rect, bool fill) 299 { 300 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 301 BRect rect = _rect; 302 303 canvas->PenToScreenTransform().Apply(&rect); 304 if (fill) 305 canvas->GetDrawingEngine()->FillRect(rect); 306 else 307 canvas->GetDrawingEngine()->StrokeRect(rect); 308 } 309 310 311 static void 312 draw_round_rect(void* _canvas, const BRect& _rect, const BPoint& radii, 313 bool fill) 314 { 315 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 316 BRect rect = _rect; 317 318 canvas->PenToScreenTransform().Apply(&rect); 319 float scale = canvas->CurrentState()->CombinedScale(); 320 canvas->GetDrawingEngine()->DrawRoundRect(rect, radii.x * scale, 321 radii.y * scale, fill); 322 } 323 324 325 static void 326 draw_bezier(void* _canvas, size_t numPoints, const BPoint viewPoints[], 327 bool fill) 328 { 329 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 330 331 const size_t kSupportedPoints = 4; 332 if (numPoints != kSupportedPoints) 333 return; 334 335 BPoint points[kSupportedPoints]; 336 canvas->PenToScreenTransform().Apply(points, viewPoints, kSupportedPoints); 337 canvas->GetDrawingEngine()->DrawBezier(points, fill); 338 } 339 340 341 static void 342 draw_arc(void* _canvas, const BPoint& center, const BPoint& radii, 343 float startTheta, float arcTheta, bool fill) 344 { 345 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 346 347 BRect rect(center.x - radii.x, center.y - radii.y, 348 center.x + radii.x - 1, center.y + radii.y - 1); 349 canvas->PenToScreenTransform().Apply(&rect); 350 canvas->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, fill); 351 } 352 353 354 static void 355 draw_ellipse(void* _canvas, const BRect& _rect, bool fill) 356 { 357 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 358 359 BRect rect = _rect; 360 canvas->PenToScreenTransform().Apply(&rect); 361 canvas->GetDrawingEngine()->DrawEllipse(rect, fill); 362 } 363 364 365 static void 366 draw_polygon(void* _canvas, size_t numPoints, const BPoint viewPoints[], 367 bool isClosed, bool fill) 368 { 369 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 370 371 if (numPoints == 0) 372 return; 373 374 BStackOrHeapArray<BPoint, 200> points(numPoints); 375 if (!points.IsValid()) 376 return; 377 378 canvas->PenToScreenTransform().Apply(points, viewPoints, numPoints); 379 380 BRect polyFrame; 381 get_polygon_frame(points, numPoints, &polyFrame); 382 383 canvas->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame, 384 fill, isClosed && numPoints > 2); 385 } 386 387 388 static void 389 draw_shape(void* _canvas, const BShape& shape, bool fill) 390 { 391 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 392 ShapePainter drawShape(canvas, NULL); 393 394 drawShape.Iterate(&shape); 395 drawShape.Draw(shape.Bounds(), fill); 396 } 397 398 399 static void 400 draw_rect_gradient(void* _canvas, const BRect& _rect, BGradient& gradient, bool fill) 401 { 402 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 403 BRect rect = _rect; 404 405 const SimpleTransform transform = 406 canvas->PenToScreenTransform(); 407 transform.Apply(&rect); 408 transform.Apply(&gradient); 409 410 canvas->GetDrawingEngine()->FillRect(rect, gradient); 411 } 412 413 414 static void 415 draw_round_rect_gradient(void* _canvas, const BRect& _rect, const BPoint& radii, BGradient& gradient, 416 bool fill) 417 { 418 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 419 BRect rect = _rect; 420 421 const SimpleTransform transform = 422 canvas->PenToScreenTransform(); 423 transform.Apply(&rect); 424 transform.Apply(&gradient); 425 float scale = canvas->CurrentState()->CombinedScale(); 426 canvas->GetDrawingEngine()->FillRoundRect(rect, radii.x * scale, 427 radii.y * scale, gradient); 428 } 429 430 431 static void 432 draw_bezier_gradient(void* _canvas, size_t numPoints, const BPoint viewPoints[], BGradient& gradient, 433 bool fill) 434 { 435 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 436 437 const size_t kSupportedPoints = 4; 438 if (numPoints != kSupportedPoints) 439 return; 440 441 BPoint points[kSupportedPoints]; 442 const SimpleTransform transform = 443 canvas->PenToScreenTransform(); 444 transform.Apply(points, viewPoints, kSupportedPoints); 445 transform.Apply(&gradient); 446 canvas->GetDrawingEngine()->FillBezier(points, gradient); 447 } 448 449 450 static void 451 draw_arc_gradient(void* _canvas, const BPoint& center, const BPoint& radii, 452 float startTheta, float arcTheta, BGradient& gradient, bool fill) 453 { 454 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 455 456 BRect rect(center.x - radii.x, center.y - radii.y, 457 center.x + radii.x - 1, center.y + radii.y - 1); 458 const SimpleTransform transform = 459 canvas->PenToScreenTransform(); 460 transform.Apply(&rect); 461 transform.Apply(&gradient); 462 canvas->GetDrawingEngine()->FillArc(rect, startTheta, arcTheta, gradient); 463 } 464 465 466 static void 467 draw_ellipse_gradient(void* _canvas, const BRect& _rect, BGradient& gradient, bool fill) 468 { 469 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 470 BRect rect = _rect; 471 472 const SimpleTransform transform = 473 canvas->PenToScreenTransform(); 474 transform.Apply(&rect); 475 transform.Apply(&gradient); 476 canvas->GetDrawingEngine()->FillEllipse(rect, gradient); 477 } 478 479 480 static void 481 draw_polygon_gradient(void* _canvas, size_t numPoints, const BPoint viewPoints[], 482 bool isClosed, BGradient& gradient, bool fill) 483 { 484 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 485 486 if (numPoints == 0) 487 return; 488 489 BStackOrHeapArray<BPoint, 200> points(numPoints); 490 if (!points.IsValid()) 491 return; 492 493 const SimpleTransform transform = 494 canvas->PenToScreenTransform(); 495 transform.Apply(points, viewPoints, numPoints); 496 transform.Apply(&gradient); 497 498 BRect polyFrame; 499 get_polygon_frame(points, numPoints, &polyFrame); 500 501 canvas->GetDrawingEngine()->FillPolygon(points, numPoints, polyFrame, 502 gradient, isClosed && numPoints > 2); 503 } 504 505 506 static void 507 draw_shape_gradient(void* _canvas, const BShape& shape, BGradient& gradient, bool fill) 508 { 509 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 510 ShapePainter drawShape(canvas, &gradient); 511 512 drawShape.Iterate(&shape); 513 drawShape.Draw(shape.Bounds(), fill); 514 } 515 516 517 static void 518 draw_string(void* _canvas, const char* string, size_t length, float deltaSpace, 519 float deltaNonSpace) 520 { 521 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 522 523 // NOTE: the picture data was recorded with a "set pen location" 524 // command inserted before the "draw string" command, so we can 525 // use PenLocation() 526 BPoint location = canvas->CurrentState()->PenLocation(); 527 528 escapement_delta delta = { deltaSpace, deltaNonSpace }; 529 canvas->PenToScreenTransform().Apply(&location); 530 location = canvas->GetDrawingEngine()->DrawString(string, length, 531 location, &delta); 532 533 canvas->PenToScreenTransform().Apply(&location); 534 canvas->CurrentState()->SetPenLocation(location); 535 // the DrawingEngine/Painter does not need to be updated, since this 536 // effects only the view->screen coord conversion, which is handled 537 // by the view only 538 } 539 540 541 static void 542 draw_string_locations(void* _canvas, const char* string, size_t length, 543 const BPoint* _locations, size_t locationsCount) 544 { 545 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 546 BStackOrHeapArray<BPoint, 200> locations(locationsCount); 547 if (!locations.IsValid()) 548 return; 549 550 const SimpleTransform transform = canvas->PenToScreenTransform(); 551 for (size_t i = 0; i < locationsCount; i++) { 552 locations[i] = _locations[i]; 553 transform.Apply(&locations[i]); 554 } 555 556 BPoint location = canvas->GetDrawingEngine()->DrawString(string, length, 557 locations); 558 559 canvas->PenToScreenTransform().Apply(&location); 560 canvas->CurrentState()->SetPenLocation(location); 561 // the DrawingEngine/Painter does not need to be updated, since this 562 // effects only the view->screen coord conversion, which is handled 563 // by the view only 564 } 565 566 567 static void 568 draw_pixels(void* _canvas, const BRect& src, const BRect& _dest, uint32 width, 569 uint32 height, size_t bytesPerRow, color_space pixelFormat, uint32 options, 570 const void* data, size_t length) 571 { 572 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 573 574 UtilityBitmap bitmap(BRect(0, 0, width - 1, height - 1), 575 (color_space)pixelFormat, 0, bytesPerRow); 576 577 if (!bitmap.IsValid()) 578 return; 579 580 memcpy(bitmap.Bits(), data, std::min(height * bytesPerRow, length)); 581 582 BRect dest = _dest; 583 canvas->PenToScreenTransform().Apply(&dest); 584 canvas->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest, options); 585 } 586 587 588 static void 589 draw_picture(void* _canvas, const BPoint& where, int32 token) 590 { 591 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 592 593 BReference<ServerPicture> picture(canvas->GetPicture(token), true); 594 if (picture != NULL) { 595 canvas->PushState(); 596 canvas->SetDrawingOrigin(where); 597 598 canvas->PushState(); 599 picture->Play(canvas); 600 canvas->PopState(); 601 602 canvas->PopState(); 603 } 604 } 605 606 607 static void 608 set_clipping_rects(void* _canvas, size_t numRects, const BRect rects[]) 609 { 610 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 611 612 if (numRects == 0) 613 canvas->SetUserClipping(NULL); 614 else { 615 // TODO: This might be too slow, we should copy the rects 616 // directly to BRegion's internal data 617 BRegion region; 618 for (uint32 c = 0; c < numRects; c++) 619 region.Include(rects[c]); 620 canvas->SetUserClipping(®ion); 621 } 622 canvas->UpdateCurrentDrawingRegion(); 623 } 624 625 626 static void 627 clip_to_picture(void* _canvas, int32 pictureToken, const BPoint& where, 628 bool clipToInverse) 629 { 630 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 631 632 BReference<ServerPicture> picture(canvas->GetPicture(pictureToken), true); 633 if (picture == NULL) 634 return; 635 BReference<AlphaMask> mask(new(std::nothrow) PictureAlphaMask(canvas->GetAlphaMask(), 636 picture, *canvas->CurrentState(), where, clipToInverse), true); 637 canvas->SetAlphaMask(mask); 638 canvas->CurrentState()->GetAlphaMask()->SetCanvasGeometry(BPoint(0, 0), 639 canvas->Bounds()); 640 canvas->ResyncDrawState(); 641 } 642 643 644 static void 645 push_state(void* _canvas) 646 { 647 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 648 canvas->PushState(); 649 } 650 651 652 static void 653 pop_state(void* _canvas) 654 { 655 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 656 canvas->PopState(); 657 658 BPoint p(0, 0); 659 canvas->PenToScreenTransform().Apply(&p); 660 canvas->GetDrawingEngine()->SetDrawState(canvas->CurrentState(), 661 (int32)p.x, (int32)p.y); 662 } 663 664 665 // TODO: Be smart and actually take advantage of these methods: 666 // only apply state changes when they are called 667 static void 668 enter_state_change(void* _canvas) 669 { 670 } 671 672 673 static void 674 exit_state_change(void* _canvas) 675 { 676 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 677 canvas->ResyncDrawState(); 678 } 679 680 681 static void 682 enter_font_state(void* _canvas) 683 { 684 } 685 686 687 static void 688 exit_font_state(void* _canvas) 689 { 690 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 691 canvas->GetDrawingEngine()->SetFont(canvas->CurrentState()->Font()); 692 } 693 694 695 static void 696 set_origin(void* _canvas, const BPoint& pt) 697 { 698 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 699 canvas->CurrentState()->SetOrigin(pt); 700 } 701 702 703 static void 704 set_pen_location(void* _canvas, const BPoint& pt) 705 { 706 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 707 canvas->CurrentState()->SetPenLocation(pt); 708 // the DrawingEngine/Painter does not need to be updated, since this 709 // effects only the view->screen coord conversion, which is handled 710 // by the view only 711 } 712 713 714 static void 715 set_drawing_mode(void* _canvas, drawing_mode mode) 716 { 717 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 718 if (canvas->CurrentState()->SetDrawingMode(mode)) 719 canvas->GetDrawingEngine()->SetDrawingMode(mode); 720 } 721 722 723 static void 724 set_line_mode(void* _canvas, cap_mode capMode, join_mode joinMode, 725 float miterLimit) 726 { 727 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 728 DrawState* state = canvas->CurrentState(); 729 state->SetLineCapMode(capMode); 730 state->SetLineJoinMode(joinMode); 731 state->SetMiterLimit(miterLimit); 732 canvas->GetDrawingEngine()->SetStrokeMode(capMode, joinMode, miterLimit); 733 } 734 735 736 static void 737 set_pen_size(void* _canvas, float size) 738 { 739 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 740 canvas->CurrentState()->SetPenSize(size); 741 canvas->GetDrawingEngine()->SetPenSize( 742 canvas->CurrentState()->PenSize()); 743 // DrawState::PenSize() returns the scaled pen size, so we 744 // need to use that value to set the drawing engine pen size. 745 } 746 747 748 static void 749 set_fore_color(void* _canvas, const rgb_color& color) 750 { 751 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 752 canvas->CurrentState()->SetHighColor(color); 753 canvas->GetDrawingEngine()->SetHighColor(color); 754 } 755 756 757 static void 758 set_back_color(void* _canvas, const rgb_color& color) 759 { 760 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 761 canvas->CurrentState()->SetLowColor(color); 762 canvas->GetDrawingEngine()->SetLowColor(color); 763 } 764 765 766 static void 767 set_stipple_pattern(void* _canvas, const pattern& pattern) 768 { 769 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 770 canvas->CurrentState()->SetPattern(Pattern(pattern)); 771 canvas->GetDrawingEngine()->SetPattern(pattern); 772 } 773 774 775 static void 776 set_scale(void* _canvas, float scale) 777 { 778 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 779 canvas->CurrentState()->SetScale(scale); 780 canvas->ResyncDrawState(); 781 782 // Update the drawing engine draw state, since some stuff 783 // (for example the pen size) needs to be recalculated. 784 } 785 786 787 static void 788 set_font_family(void* _canvas, const char* _family, size_t length) 789 { 790 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 791 BString family(_family, length); 792 793 gFontManager->Lock(); 794 FontStyle* fontStyle = gFontManager->GetStyleByIndex(family, 0); 795 ServerFont font; 796 font.SetStyle(fontStyle); 797 gFontManager->Unlock(); 798 canvas->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE); 799 } 800 801 802 static void 803 set_font_style(void* _canvas, const char* _style, size_t length) 804 { 805 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 806 BString style(_style, length); 807 808 ServerFont font(canvas->CurrentState()->Font()); 809 810 gFontManager->Lock(); 811 FontStyle* fontStyle = gFontManager->GetStyle(font.Family(), style); 812 813 font.SetStyle(fontStyle); 814 gFontManager->Unlock(); 815 canvas->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE); 816 } 817 818 819 static void 820 set_font_spacing(void* _canvas, uint8 spacing) 821 { 822 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 823 ServerFont font; 824 font.SetSpacing(spacing); 825 canvas->CurrentState()->SetFont(font, B_FONT_SPACING); 826 } 827 828 829 static void 830 set_font_size(void* _canvas, float size) 831 { 832 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 833 ServerFont font; 834 font.SetSize(size); 835 canvas->CurrentState()->SetFont(font, B_FONT_SIZE); 836 } 837 838 839 static void 840 set_font_rotation(void* _canvas, float rotation) 841 { 842 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 843 ServerFont font; 844 font.SetRotation(rotation); 845 canvas->CurrentState()->SetFont(font, B_FONT_ROTATION); 846 } 847 848 849 static void 850 set_font_encoding(void* _canvas, uint8 encoding) 851 { 852 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 853 ServerFont font; 854 font.SetEncoding(encoding); 855 canvas->CurrentState()->SetFont(font, B_FONT_ENCODING); 856 } 857 858 859 static void 860 set_font_flags(void* _canvas, uint32 flags) 861 { 862 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 863 ServerFont font; 864 font.SetFlags(flags); 865 canvas->CurrentState()->SetFont(font, B_FONT_FLAGS); 866 } 867 868 869 static void 870 set_font_shear(void* _canvas, float shear) 871 { 872 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 873 ServerFont font; 874 font.SetShear(shear); 875 canvas->CurrentState()->SetFont(font, B_FONT_SHEAR); 876 } 877 878 879 static void 880 set_font_face(void* _canvas, uint16 face) 881 { 882 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 883 ServerFont font; 884 font.SetFace(face); 885 canvas->CurrentState()->SetFont(font, B_FONT_FACE); 886 } 887 888 889 static void 890 set_blending_mode(void* _canvas, source_alpha alphaSrcMode, 891 alpha_function alphaFncMode) 892 { 893 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 894 canvas->CurrentState()->SetBlendingMode(alphaSrcMode, alphaFncMode); 895 } 896 897 898 static void 899 set_fill_rule(void* _canvas, int32 fillRule) 900 { 901 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 902 canvas->CurrentState()->SetFillRule(fillRule); 903 canvas->GetDrawingEngine()->SetFillRule(fillRule); 904 } 905 906 907 static void 908 set_transform(void* _canvas, const BAffineTransform& transform) 909 { 910 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 911 912 BPoint leftTop(0, 0); 913 canvas->PenToScreenTransform().Apply(&leftTop); 914 915 canvas->CurrentState()->SetTransform(transform); 916 canvas->GetDrawingEngine()->SetTransform( 917 canvas->CurrentState()->CombinedTransform(), leftTop.x, leftTop.y); 918 } 919 920 921 static void 922 translate_by(void* _canvas, double x, double y) 923 { 924 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 925 926 BPoint leftTop(0, 0); 927 canvas->PenToScreenTransform().Apply(&leftTop); 928 929 BAffineTransform transform = canvas->CurrentState()->Transform(); 930 transform.PreTranslateBy(x, y); 931 canvas->CurrentState()->SetTransform(transform); 932 canvas->GetDrawingEngine()->SetTransform( 933 canvas->CurrentState()->CombinedTransform(), leftTop.x, leftTop.y); 934 } 935 936 937 static void 938 scale_by(void* _canvas, double x, double y) 939 { 940 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 941 942 BPoint leftTop(0, 0); 943 canvas->PenToScreenTransform().Apply(&leftTop); 944 945 BAffineTransform transform = canvas->CurrentState()->Transform(); 946 transform.PreScaleBy(x, y); 947 canvas->CurrentState()->SetTransform(transform); 948 canvas->GetDrawingEngine()->SetTransform( 949 canvas->CurrentState()->CombinedTransform(), leftTop.x, leftTop.y); 950 } 951 952 953 static void 954 rotate_by(void* _canvas, double angleRadians) 955 { 956 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 957 958 BPoint leftTop(0, 0); 959 canvas->PenToScreenTransform().Apply(&leftTop); 960 961 BAffineTransform transform = canvas->CurrentState()->Transform(); 962 transform.PreRotateBy(angleRadians); 963 canvas->CurrentState()->SetTransform(transform); 964 canvas->GetDrawingEngine()->SetTransform( 965 canvas->CurrentState()->CombinedTransform(), leftTop.x, leftTop.y); 966 } 967 968 969 static void 970 blend_layer(void* _canvas, Layer* layer) 971 { 972 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 973 canvas->BlendLayer(layer); 974 } 975 976 977 static void 978 clip_to_rect(void* _canvas, const BRect& rect, bool inverse) 979 { 980 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 981 bool needDrawStateUpdate = canvas->ClipToRect(rect, inverse); 982 if (needDrawStateUpdate) { 983 canvas->CurrentState()->GetAlphaMask()->SetCanvasGeometry(BPoint(0, 0), 984 canvas->Bounds()); 985 canvas->ResyncDrawState(); 986 } 987 canvas->UpdateCurrentDrawingRegion(); 988 } 989 990 991 static void 992 clip_to_shape(void* _canvas, int32 opCount, const uint32 opList[], 993 int32 ptCount, const BPoint ptList[], bool inverse) 994 { 995 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas); 996 shape_data shapeData; 997 998 // TODO: avoid copies 999 shapeData.opList = (uint32*)malloc(opCount * sizeof(uint32)); 1000 memcpy(shapeData.opList, opList, opCount * sizeof(uint32)); 1001 shapeData.ptList = (BPoint*)malloc(ptCount * sizeof(BPoint)); 1002 memcpy((void*)shapeData.ptList, ptList, ptCount * sizeof(BPoint)); 1003 1004 shapeData.opCount = opCount; 1005 shapeData.opSize = opCount * sizeof(uint32); 1006 shapeData.ptCount = ptCount; 1007 shapeData.ptSize = ptCount * sizeof(BPoint); 1008 1009 canvas->ClipToShape(&shapeData, inverse); 1010 canvas->CurrentState()->GetAlphaMask()->SetCanvasGeometry(BPoint(0, 0), 1011 canvas->Bounds()); 1012 canvas->ResyncDrawState(); 1013 1014 free(shapeData.opList); 1015 free(shapeData.ptList); 1016 } 1017 1018 1019 static const BPrivate::picture_player_callbacks kPicturePlayerCallbacks = { 1020 move_pen_by, 1021 stroke_line, 1022 draw_rect, 1023 draw_round_rect, 1024 draw_bezier, 1025 draw_arc, 1026 draw_ellipse, 1027 draw_polygon, 1028 draw_shape, 1029 draw_string, 1030 draw_pixels, 1031 draw_picture, 1032 set_clipping_rects, 1033 clip_to_picture, 1034 push_state, 1035 pop_state, 1036 enter_state_change, 1037 exit_state_change, 1038 enter_font_state, 1039 exit_font_state, 1040 set_origin, 1041 set_pen_location, 1042 set_drawing_mode, 1043 set_line_mode, 1044 set_pen_size, 1045 set_fore_color, 1046 set_back_color, 1047 set_stipple_pattern, 1048 set_scale, 1049 set_font_family, 1050 set_font_style, 1051 set_font_spacing, 1052 set_font_size, 1053 set_font_rotation, 1054 set_font_encoding, 1055 set_font_flags, 1056 set_font_shear, 1057 set_font_face, 1058 set_blending_mode, 1059 set_transform, 1060 translate_by, 1061 scale_by, 1062 rotate_by, 1063 blend_layer, 1064 clip_to_rect, 1065 clip_to_shape, 1066 draw_string_locations, 1067 draw_rect_gradient, 1068 draw_round_rect_gradient, 1069 draw_bezier_gradient, 1070 draw_arc_gradient, 1071 draw_ellipse_gradient, 1072 draw_polygon_gradient, 1073 draw_shape_gradient, 1074 set_fill_rule 1075 }; 1076 1077 1078 // #pragma mark - ServerPicture 1079 1080 1081 ServerPicture::ServerPicture() 1082 : 1083 fFile(NULL), 1084 fOwner(NULL) 1085 { 1086 fToken = gTokenSpace.NewToken(kPictureToken, this); 1087 fData.SetTo(new(std::nothrow) BMallocIO()); 1088 1089 PictureDataWriter::SetTo(fData.Get()); 1090 } 1091 1092 1093 ServerPicture::ServerPicture(const ServerPicture& picture) 1094 : 1095 fFile(NULL), 1096 fData(NULL), 1097 fOwner(NULL) 1098 { 1099 fToken = gTokenSpace.NewToken(kPictureToken, this); 1100 1101 BMallocIO* mallocIO = new(std::nothrow) BMallocIO(); 1102 if (mallocIO == NULL) 1103 return; 1104 1105 fData.SetTo(mallocIO); 1106 1107 const off_t size = picture.DataLength(); 1108 if (mallocIO->SetSize(size) < B_OK) 1109 return; 1110 1111 picture.fData->ReadAt(0, const_cast<void*>(mallocIO->Buffer()), 1112 size); 1113 1114 PictureDataWriter::SetTo(fData.Get()); 1115 } 1116 1117 1118 ServerPicture::ServerPicture(const char* fileName, int32 offset) 1119 : 1120 fFile(NULL), 1121 fData(NULL), 1122 fOwner(NULL) 1123 { 1124 fToken = gTokenSpace.NewToken(kPictureToken, this); 1125 1126 fFile.SetTo(new(std::nothrow) BFile(fileName, B_READ_WRITE)); 1127 if (!fFile.IsSet()) 1128 return; 1129 1130 BPrivate::Storage::OffsetFile* offsetFile 1131 = new(std::nothrow) BPrivate::Storage::OffsetFile(fFile.Get(), offset); 1132 if (offsetFile == NULL || offsetFile->InitCheck() != B_OK) { 1133 delete offsetFile; 1134 return; 1135 } 1136 1137 fData.SetTo(offsetFile); 1138 1139 PictureDataWriter::SetTo(fData.Get()); 1140 } 1141 1142 1143 ServerPicture::~ServerPicture() 1144 { 1145 ASSERT(fOwner == NULL); 1146 1147 gTokenSpace.RemoveToken(fToken); 1148 1149 if (fPictures.IsSet()) { 1150 for (int32 i = fPictures->CountItems(); i-- > 0;) { 1151 ServerPicture* picture = fPictures->ItemAt(i); 1152 picture->SetOwner(NULL); 1153 picture->ReleaseReference(); 1154 } 1155 } 1156 1157 if (fPushed != NULL) 1158 fPushed->SetOwner(NULL); 1159 } 1160 1161 1162 bool 1163 ServerPicture::SetOwner(ServerApp* owner) 1164 { 1165 if (owner == fOwner) 1166 return true; 1167 1168 // Acquire an extra reference, since calling RemovePicture() 1169 // May remove the last reference and then we will self-destruct right then. 1170 // Setting fOwner to NULL would access free'd memory. If owner is another 1171 // ServerApp, it's expected to already have a reference of course. 1172 BReference<ServerPicture> _(this); 1173 1174 if (fOwner != NULL) 1175 fOwner->RemovePicture(this); 1176 1177 fOwner = NULL; 1178 if (owner == NULL) 1179 return true; 1180 1181 if (!owner->AddPicture(this)) 1182 return false; 1183 1184 fOwner = owner; 1185 return true; 1186 } 1187 1188 1189 void 1190 ServerPicture::EnterStateChange() 1191 { 1192 BeginOp(B_PIC_ENTER_STATE_CHANGE); 1193 } 1194 1195 1196 void 1197 ServerPicture::ExitStateChange() 1198 { 1199 EndOp(); 1200 } 1201 1202 1203 void 1204 ServerPicture::SyncState(Canvas* canvas) 1205 { 1206 // TODO: Finish this 1207 EnterStateChange(); 1208 1209 WriteSetOrigin(canvas->CurrentState()->Origin()); 1210 WriteSetPenLocation(canvas->CurrentState()->PenLocation()); 1211 WriteSetPenSize(canvas->CurrentState()->UnscaledPenSize()); 1212 WriteSetScale(canvas->CurrentState()->Scale()); 1213 WriteSetLineMode(canvas->CurrentState()->LineCapMode(), 1214 canvas->CurrentState()->LineJoinMode(), 1215 canvas->CurrentState()->MiterLimit()); 1216 //WriteSetPattern(*canvas->CurrentState()->GetPattern().GetInt8()); 1217 WriteSetDrawingMode(canvas->CurrentState()->GetDrawingMode()); 1218 1219 WriteSetHighColor(canvas->CurrentState()->HighColor()); 1220 WriteSetLowColor(canvas->CurrentState()->LowColor()); 1221 1222 ExitStateChange(); 1223 } 1224 1225 1226 void 1227 ServerPicture::WriteFontState(const ServerFont& font, uint16 mask) 1228 { 1229 BeginOp(B_PIC_ENTER_FONT_STATE); 1230 1231 if (mask & B_FONT_FAMILY_AND_STYLE) { 1232 WriteSetFontFamily(font.Family()); 1233 WriteSetFontStyle(font.Style()); 1234 } 1235 1236 if (mask & B_FONT_SIZE) { 1237 WriteSetFontSize(font.Size()); 1238 } 1239 1240 if (mask & B_FONT_SHEAR) { 1241 WriteSetFontShear(font.Shear()); 1242 } 1243 1244 if (mask & B_FONT_ROTATION) { 1245 WriteSetFontRotation(font.Rotation()); 1246 } 1247 1248 if (mask & B_FONT_FALSE_BOLD_WIDTH) { 1249 // TODO: Implement 1250 // WriteSetFalseBoldWidth(font.FalseBoldWidth()); 1251 } 1252 1253 if (mask & B_FONT_SPACING) { 1254 WriteSetFontSpacing(font.Spacing()); 1255 } 1256 1257 if (mask & B_FONT_ENCODING) { 1258 WriteSetFontEncoding(font.Encoding()); 1259 } 1260 1261 if (mask & B_FONT_FACE) { 1262 WriteSetFontFace(font.Face()); 1263 } 1264 1265 if (mask & B_FONT_FLAGS) { 1266 WriteSetFontFlags(font.Flags()); 1267 } 1268 1269 EndOp(); 1270 } 1271 1272 1273 void 1274 ServerPicture::Play(Canvas* target) 1275 { 1276 // TODO: for now: then change PicturePlayer 1277 // to accept a BPositionIO object 1278 BMallocIO* mallocIO = dynamic_cast<BMallocIO*>(fData.Get()); 1279 if (mallocIO == NULL) 1280 return; 1281 1282 BPrivate::PicturePlayer player(mallocIO->Buffer(), 1283 mallocIO->BufferLength(), PictureList::Private(fPictures.Get()).AsBList()); 1284 player.Play(kPicturePlayerCallbacks, sizeof(kPicturePlayerCallbacks), 1285 target); 1286 } 1287 1288 1289 /*! Acquires a reference to the pushed picture. 1290 */ 1291 void 1292 ServerPicture::PushPicture(ServerPicture* picture) 1293 { 1294 if (fPushed != NULL) 1295 debugger("already pushed a picture"); 1296 1297 fPushed.SetTo(picture, false); 1298 } 1299 1300 1301 /*! Returns a reference with the popped picture. 1302 */ 1303 ServerPicture* 1304 ServerPicture::PopPicture() 1305 { 1306 return fPushed.Detach(); 1307 } 1308 1309 1310 void 1311 ServerPicture::AppendPicture(ServerPicture* picture) 1312 { 1313 // A pushed picture is the same as an appended one 1314 PushPicture(picture); 1315 } 1316 1317 1318 bool 1319 ServerPicture::NestPicture(ServerPicture* picture) 1320 { 1321 if (!fPictures.IsSet()) 1322 fPictures.SetTo(new(std::nothrow) PictureList); 1323 1324 if (!fPictures.IsSet() || !fPictures->AddItem(picture)) 1325 return false; 1326 1327 picture->AcquireReference(); 1328 return true; 1329 } 1330 1331 1332 off_t 1333 ServerPicture::DataLength() const 1334 { 1335 if (!fData.IsSet()) 1336 return 0; 1337 off_t size; 1338 fData->GetSize(&size); 1339 return size; 1340 } 1341 1342 1343 status_t 1344 ServerPicture::ImportData(BPrivate::LinkReceiver& link) 1345 { 1346 int32 size = 0; 1347 link.Read<int32>(&size); 1348 1349 off_t oldPosition = fData->Position(); 1350 fData->Seek(0, SEEK_SET); 1351 1352 status_t status = B_NO_MEMORY; 1353 char* buffer = new(std::nothrow) char[size]; 1354 if (buffer) { 1355 status = B_OK; 1356 ssize_t read = link.Read(buffer, size); 1357 if (read < B_OK || fData->Write(buffer, size) < B_OK) 1358 status = B_ERROR; 1359 delete [] buffer; 1360 } 1361 1362 fData->Seek(oldPosition, SEEK_SET); 1363 return status; 1364 } 1365 1366 1367 status_t 1368 ServerPicture::ExportData(BPrivate::PortLink& link) 1369 { 1370 link.StartMessage(B_OK); 1371 1372 off_t oldPosition = fData->Position(); 1373 fData->Seek(0, SEEK_SET); 1374 1375 int32 subPicturesCount = 0; 1376 if (fPictures.IsSet()) 1377 subPicturesCount = fPictures->CountItems(); 1378 link.Attach<int32>(subPicturesCount); 1379 if (subPicturesCount > 0) { 1380 for (int32 i = 0; i < subPicturesCount; i++) { 1381 ServerPicture* subPicture = fPictures->ItemAt(i); 1382 link.Attach<int32>(subPicture->Token()); 1383 } 1384 } 1385 1386 off_t size = 0; 1387 fData->GetSize(&size); 1388 link.Attach<int32>((int32)size); 1389 1390 status_t status = B_NO_MEMORY; 1391 char* buffer = new(std::nothrow) char[size]; 1392 if (buffer) { 1393 status = B_OK; 1394 ssize_t read = fData->Read(buffer, size); 1395 if (read < B_OK || link.Attach(buffer, read) < B_OK) 1396 status = B_ERROR; 1397 delete [] buffer; 1398 } 1399 1400 if (status != B_OK) { 1401 link.CancelMessage(); 1402 link.StartMessage(B_ERROR); 1403 } 1404 1405 fData->Seek(oldPosition, SEEK_SET); 1406 return status; 1407 } 1408