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