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