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 (burton666@libero.it) 8 * Marcus Overhagen <marcus@overhagen.de> 9 */ 10 11 12 #include "ServerPicture.h" 13 14 #include "DrawingEngine.h" 15 #include "ServerApp.h" 16 #include "ServerBitmap.h" 17 #include "ServerFont.h" 18 #include "ServerTokenSpace.h" 19 #include "View.h" 20 #include "Window.h" 21 22 #include <LinkReceiver.h> 23 #include <OffsetFile.h> 24 #include <PicturePlayer.h> 25 #include <PictureProtocol.h> 26 #include <PortLink.h> 27 #include <ServerProtocol.h> 28 #include <ShapePrivate.h> 29 30 #include <Bitmap.h> 31 #include <Debug.h> 32 #include <List.h> 33 #include <Shape.h> 34 35 #include <new> 36 #include <stdio.h> 37 #include <stack> 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->SetDrawingOrigin(where); 519 view->PushState(); 520 picture->Play(view); 521 view->PopState(); 522 523 picture->ReleaseReference(); 524 } 525 } 526 527 528 static void 529 set_clipping_rects(View* view, const BRect* rects, uint32 numRects) 530 { 531 // TODO: This might be too slow, we should copy the rects 532 // directly to BRegion's internal data 533 BRegion region; 534 for (uint32 c = 0; c < numRects; c++) 535 region.Include(rects[c]); 536 view->SetUserClipping(®ion); 537 view->Window()->ServerWindow()->UpdateCurrentDrawingRegion(); 538 } 539 540 541 static void 542 clip_to_picture(View* view, BPicture* picture, BPoint pt, bool clipToInverse) 543 { 544 printf("ClipToPicture(picture, BPoint(%.2f, %.2f), %s)\n", 545 pt.x, pt.y, clipToInverse ? "inverse" : ""); 546 } 547 548 549 static void 550 push_state(View* view) 551 { 552 view->PushState(); 553 } 554 555 556 static void 557 pop_state(View* view) 558 { 559 view->PopState(); 560 561 BPoint p(0, 0); 562 view->ConvertToScreenForDrawing(&p); 563 view->Window()->GetDrawingEngine()->SetDrawState( 564 view->CurrentState(), (int32)p.x, (int32)p.y); 565 } 566 567 568 // TODO: Be smart and actually take advantage of these methods: 569 // only apply state changes when they are called 570 static void 571 enter_state_change(View* view) 572 { 573 } 574 575 576 static void 577 exit_state_change(View* view) 578 { 579 view->Window()->ServerWindow()->ResyncDrawState(); 580 } 581 582 583 static void 584 enter_font_state(View* view) 585 { 586 } 587 588 589 static void 590 exit_font_state(View* view) 591 { 592 view->Window()->GetDrawingEngine()->SetFont( 593 view->CurrentState()->Font()); 594 } 595 596 597 static void 598 set_origin(View* view, BPoint pt) 599 { 600 view->CurrentState()->SetOrigin(pt); 601 } 602 603 604 static void 605 set_pen_location(View* view, BPoint pt) 606 { 607 view->CurrentState()->SetPenLocation(pt); 608 // the DrawingEngine/Painter does not need to be updated, since this 609 // effects only the view->screen coord conversion, which is handled 610 // by the view only 611 } 612 613 614 static void 615 set_drawing_mode(View* view, drawing_mode mode) 616 { 617 view->CurrentState()->SetDrawingMode(mode); 618 view->Window()->GetDrawingEngine()->SetDrawingMode(mode); 619 } 620 621 622 static void 623 set_line_mode(View* view, cap_mode capMode, join_mode joinMode, 624 float miterLimit) 625 { 626 DrawState* state = view->CurrentState(); 627 state->SetLineCapMode(capMode); 628 state->SetLineJoinMode(joinMode); 629 state->SetMiterLimit(miterLimit); 630 view->Window()->GetDrawingEngine()->SetStrokeMode(capMode, joinMode, 631 miterLimit); 632 } 633 634 635 static void 636 set_pen_size(View* view, float size) 637 { 638 view->CurrentState()->SetPenSize(size); 639 view->Window()->GetDrawingEngine()->SetPenSize( 640 view->CurrentState()->PenSize()); 641 // DrawState::PenSize() returns the scaled pen size, so we 642 // need to use that value to set the drawing engine pen size. 643 } 644 645 646 static void 647 set_fore_color(View* view, rgb_color color) 648 { 649 view->CurrentState()->SetHighColor(color); 650 view->Window()->GetDrawingEngine()->SetHighColor(color); 651 } 652 653 654 static void 655 set_back_color(View* view, rgb_color color) 656 { 657 view->CurrentState()->SetLowColor(color); 658 view->Window()->GetDrawingEngine()->SetLowColor(color); 659 } 660 661 662 static void 663 set_stipple_pattern(View* view, pattern p) 664 { 665 view->CurrentState()->SetPattern(Pattern(p)); 666 view->Window()->GetDrawingEngine()->SetPattern(p); 667 } 668 669 670 static void 671 set_scale(View* view, float scale) 672 { 673 view->CurrentState()->SetScale(scale); 674 view->Window()->ServerWindow()->ResyncDrawState(); 675 676 // Update the drawing engine draw state, since some stuff 677 // (for example the pen size) needs to be recalculated. 678 } 679 680 681 static void 682 set_font_family(View* view, const char* family) 683 { 684 FontStyle* fontStyle = gFontManager->GetStyleByIndex(family, 0); 685 ServerFont font; 686 font.SetStyle(fontStyle); 687 view->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE); 688 } 689 690 691 static void 692 set_font_style(View* view, const char* style) 693 { 694 ServerFont font(view->CurrentState()->Font()); 695 696 FontStyle* fontStyle = gFontManager->GetStyle(font.Family(), style); 697 698 font.SetStyle(fontStyle); 699 view->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE); 700 } 701 702 703 static void 704 set_font_spacing(View* view, int32 spacing) 705 { 706 ServerFont font; 707 font.SetSpacing(spacing); 708 view->CurrentState()->SetFont(font, B_FONT_SPACING); 709 } 710 711 712 static void 713 set_font_size(View* view, float size) 714 { 715 ServerFont font; 716 font.SetSize(size); 717 view->CurrentState()->SetFont(font, B_FONT_SIZE); 718 } 719 720 721 static void 722 set_font_rotate(View* view, float rotation) 723 { 724 ServerFont font; 725 font.SetRotation(rotation); 726 view->CurrentState()->SetFont(font, B_FONT_ROTATION); 727 } 728 729 730 static void 731 set_font_encoding(View* view, int32 encoding) 732 { 733 ServerFont font; 734 font.SetEncoding(encoding); 735 view->CurrentState()->SetFont(font, B_FONT_ENCODING); 736 } 737 738 739 static void 740 set_font_flags(View* view, int32 flags) 741 { 742 ServerFont font; 743 font.SetFlags(flags); 744 view->CurrentState()->SetFont(font, B_FONT_FLAGS); 745 } 746 747 748 static void 749 set_font_shear(View* view, float shear) 750 { 751 ServerFont font; 752 font.SetShear(shear); 753 view->CurrentState()->SetFont(font, B_FONT_SHEAR); 754 } 755 756 757 static void 758 set_font_face(View* view, int32 face) 759 { 760 ServerFont font; 761 font.SetFace(face); 762 view->CurrentState()->SetFont(font, B_FONT_FACE); 763 } 764 765 766 static void 767 set_blending_mode(View* view, int16 alphaSrcMode, int16 alphaFncMode) 768 { 769 view->CurrentState()->SetBlendingMode((source_alpha)alphaSrcMode, 770 (alpha_function)alphaFncMode); 771 } 772 773 774 static void 775 reserved() 776 { 777 } 778 779 780 const static void* kTableEntries[] = { 781 (const void*)nop, // 0 782 (const void*)move_pen_by, 783 (const void*)stroke_line, 784 (const void*)stroke_rect, 785 (const void*)fill_rect, 786 (const void*)stroke_round_rect, // 5 787 (const void*)fill_round_rect, 788 (const void*)stroke_bezier, 789 (const void*)fill_bezier, 790 (const void*)stroke_arc, 791 (const void*)fill_arc, // 10 792 (const void*)stroke_ellipse, 793 (const void*)fill_ellipse, 794 (const void*)stroke_polygon, 795 (const void*)fill_polygon, 796 (const void*)stroke_shape, // 15 797 (const void*)fill_shape, 798 (const void*)draw_string, 799 (const void*)draw_pixels, 800 (const void*)draw_picture, 801 (const void*)set_clipping_rects, // 20 802 (const void*)clip_to_picture, 803 (const void*)push_state, 804 (const void*)pop_state, 805 (const void*)enter_state_change, 806 (const void*)exit_state_change, // 25 807 (const void*)enter_font_state, 808 (const void*)exit_font_state, 809 (const void*)set_origin, 810 (const void*)set_pen_location, 811 (const void*)set_drawing_mode, // 30 812 (const void*)set_line_mode, 813 (const void*)set_pen_size, 814 (const void*)set_fore_color, 815 (const void*)set_back_color, 816 (const void*)set_stipple_pattern, // 35 817 (const void*)set_scale, 818 (const void*)set_font_family, 819 (const void*)set_font_style, 820 (const void*)set_font_spacing, 821 (const void*)set_font_size, // 40 822 (const void*)set_font_rotate, 823 (const void*)set_font_encoding, 824 (const void*)set_font_flags, 825 (const void*)set_font_shear, 826 (const void*)reserved, // 45 827 (const void*)set_font_face, 828 (const void*)set_blending_mode // 47 829 }; 830 831 832 // #pragma mark - ServerPicture 833 834 835 ServerPicture::ServerPicture() 836 : 837 fFile(NULL), 838 fPictures(NULL), 839 fPushed(NULL), 840 fOwner(NULL) 841 { 842 fToken = gTokenSpace.NewToken(kPictureToken, this); 843 fData = new(std::nothrow) BMallocIO(); 844 845 PictureDataWriter::SetTo(fData); 846 } 847 848 849 ServerPicture::ServerPicture(const ServerPicture& picture) 850 : 851 fFile(NULL), 852 fData(NULL), 853 fPictures(NULL), 854 fPushed(NULL), 855 fOwner(NULL) 856 { 857 fToken = gTokenSpace.NewToken(kPictureToken, this); 858 859 BMallocIO* mallocIO = new(std::nothrow) BMallocIO(); 860 if (mallocIO == NULL) 861 return; 862 863 fData = mallocIO; 864 865 const off_t size = picture.DataLength(); 866 if (mallocIO->SetSize(size) < B_OK) 867 return; 868 869 picture.fData->ReadAt(0, const_cast<void*>(mallocIO->Buffer()), 870 size); 871 872 PictureDataWriter::SetTo(fData); 873 } 874 875 876 ServerPicture::ServerPicture(const char* fileName, int32 offset) 877 : 878 fFile(NULL), 879 fData(NULL), 880 fPictures(NULL), 881 fPushed(NULL), 882 fOwner(NULL) 883 { 884 fToken = gTokenSpace.NewToken(kPictureToken, this); 885 886 fFile = new(std::nothrow) BFile(fileName, B_READ_WRITE); 887 if (fFile == NULL) 888 return; 889 890 BPrivate::Storage::OffsetFile* offsetFile 891 = new(std::nothrow) BPrivate::Storage::OffsetFile(fFile, offset); 892 if (offsetFile == NULL || offsetFile->InitCheck() != B_OK) { 893 delete offsetFile; 894 return; 895 } 896 897 fData = offsetFile; 898 899 PictureDataWriter::SetTo(fData); 900 } 901 902 903 ServerPicture::~ServerPicture() 904 { 905 ASSERT(fOwner == NULL); 906 907 delete fData; 908 delete fFile; 909 gTokenSpace.RemoveToken(fToken); 910 911 if (fPictures != NULL) { 912 for (int32 i = fPictures->CountItems(); i-- > 0;) { 913 ServerPicture* picture = fPictures->ItemAt(i); 914 picture->SetOwner(NULL); 915 picture->ReleaseReference(); 916 } 917 918 delete fPictures; 919 } 920 921 if (fPushed != NULL) { 922 fPushed->SetOwner(NULL); 923 fPushed->ReleaseReference(); 924 } 925 } 926 927 928 bool 929 ServerPicture::SetOwner(ServerApp* owner) 930 { 931 if (fOwner != NULL) 932 fOwner->RemovePicture(this); 933 934 if (owner != NULL && owner->AddPicture(this)) { 935 fOwner = owner; 936 return true; 937 } 938 939 fOwner = NULL; 940 return false; 941 } 942 943 944 void 945 ServerPicture::EnterStateChange() 946 { 947 BeginOp(B_PIC_ENTER_STATE_CHANGE); 948 } 949 950 951 void 952 ServerPicture::ExitStateChange() 953 { 954 EndOp(); 955 } 956 957 958 void 959 ServerPicture::SyncState(View* view) 960 { 961 // TODO: Finish this 962 EnterStateChange(); 963 964 WriteSetOrigin(view->CurrentState()->Origin()); 965 WriteSetPenLocation(view->CurrentState()->PenLocation()); 966 WriteSetPenSize(view->CurrentState()->PenSize()); 967 WriteSetScale(view->CurrentState()->Scale()); 968 WriteSetLineMode(view->CurrentState()->LineCapMode(), 969 view->CurrentState()->LineJoinMode(), 970 view->CurrentState()->MiterLimit()); 971 //WriteSetPattern(*view->CurrentState()->GetPattern().GetInt8()); 972 WriteSetDrawingMode(view->CurrentState()->GetDrawingMode()); 973 974 WriteSetHighColor(view->CurrentState()->HighColor()); 975 WriteSetLowColor(view->CurrentState()->LowColor()); 976 977 ExitStateChange(); 978 } 979 980 981 void 982 ServerPicture::SetFontFromLink(BPrivate::LinkReceiver& link) 983 { 984 BeginOp(B_PIC_ENTER_FONT_STATE); 985 986 uint16 mask; 987 link.Read<uint16>(&mask); 988 989 if (mask & B_FONT_FAMILY_AND_STYLE) { 990 uint32 fontID; 991 link.Read<uint32>(&fontID); 992 ServerFont font; 993 font.SetFamilyAndStyle(fontID); 994 WriteSetFontFamily(font.Family()); 995 WriteSetFontStyle(font.Style()); 996 } 997 998 if (mask & B_FONT_SIZE) { 999 float size; 1000 link.Read<float>(&size); 1001 WriteSetFontSize(size); 1002 } 1003 1004 if (mask & B_FONT_SHEAR) { 1005 float shear; 1006 link.Read<float>(&shear); 1007 WriteSetFontShear(shear); 1008 } 1009 1010 if (mask & B_FONT_ROTATION) { 1011 float rotation; 1012 link.Read<float>(&rotation); 1013 WriteSetFontRotation(rotation); 1014 } 1015 1016 if (mask & B_FONT_FALSE_BOLD_WIDTH) { 1017 float falseBoldWidth; 1018 link.Read<float>(&falseBoldWidth); 1019 //SetFalseBoldWidth(falseBoldWidth); 1020 } 1021 1022 if (mask & B_FONT_SPACING) { 1023 uint8 spacing; 1024 link.Read<uint8>(&spacing); 1025 WriteSetFontSpacing(spacing); 1026 } 1027 1028 if (mask & B_FONT_ENCODING) { 1029 uint8 encoding; 1030 link.Read<uint8>((uint8*)&encoding); 1031 WriteSetFontEncoding(encoding); 1032 } 1033 1034 if (mask & B_FONT_FACE) { 1035 uint16 face; 1036 link.Read<uint16>(&face); 1037 WriteSetFontFace(face); 1038 } 1039 1040 if (mask & B_FONT_FLAGS) { 1041 uint32 flags; 1042 link.Read<uint32>(&flags); 1043 WriteSetFontFlags(flags); 1044 } 1045 1046 EndOp(); 1047 } 1048 1049 1050 void 1051 ServerPicture::Play(View* view) 1052 { 1053 // TODO: for now: then change PicturePlayer 1054 // to accept a BPositionIO object 1055 BMallocIO* mallocIO = dynamic_cast<BMallocIO*>(fData); 1056 if (mallocIO == NULL) 1057 return; 1058 1059 BPrivate::PicturePlayer player(mallocIO->Buffer(), 1060 mallocIO->BufferLength(), fPictures->AsBList()); 1061 player.Play(const_cast<void**>(kTableEntries), 1062 sizeof(kTableEntries) / sizeof(void*), view); 1063 } 1064 1065 1066 /*! Acquires a reference to the pushed picture. 1067 */ 1068 void 1069 ServerPicture::PushPicture(ServerPicture* picture) 1070 { 1071 if (fPushed != NULL) 1072 debugger("already pushed a picture"); 1073 1074 fPushed = picture; 1075 fPushed->AcquireReference(); 1076 } 1077 1078 1079 /*! Returns a reference with the popped picture. 1080 */ 1081 ServerPicture* 1082 ServerPicture::PopPicture() 1083 { 1084 ServerPicture* old = fPushed; 1085 fPushed = NULL; 1086 return old; 1087 } 1088 1089 1090 void 1091 ServerPicture::AppendPicture(ServerPicture* picture) 1092 { 1093 // A pushed picture is the same as an appended one 1094 PushPicture(picture); 1095 } 1096 1097 1098 bool 1099 ServerPicture::NestPicture(ServerPicture* picture) 1100 { 1101 if (fPictures == NULL) 1102 fPictures = new(std::nothrow) PictureList; 1103 1104 if (fPictures == NULL || !fPictures->AddItem(picture)) 1105 return false; 1106 1107 return true; 1108 } 1109 1110 1111 off_t 1112 ServerPicture::DataLength() const 1113 { 1114 if (fData == NULL) 1115 return 0; 1116 off_t size; 1117 fData->GetSize(&size); 1118 return size; 1119 } 1120 1121 1122 status_t 1123 ServerPicture::ImportData(BPrivate::LinkReceiver& link) 1124 { 1125 int32 size = 0; 1126 link.Read<int32>(&size); 1127 1128 off_t oldPosition = fData->Position(); 1129 fData->Seek(0, SEEK_SET); 1130 1131 status_t status = B_NO_MEMORY; 1132 char* buffer = new(std::nothrow) char[size]; 1133 if (buffer) { 1134 status = B_OK; 1135 ssize_t read = link.Read(buffer, size); 1136 if (read < B_OK || fData->Write(buffer, size) < B_OK) 1137 status = B_ERROR; 1138 delete [] buffer; 1139 } 1140 1141 fData->Seek(oldPosition, SEEK_SET); 1142 return status; 1143 } 1144 1145 1146 status_t 1147 ServerPicture::ExportData(BPrivate::PortLink& link) 1148 { 1149 link.StartMessage(B_OK); 1150 1151 off_t oldPosition = fData->Position(); 1152 fData->Seek(0, SEEK_SET); 1153 1154 int32 subPicturesCount = 0; 1155 if (fPictures != NULL) 1156 subPicturesCount = fPictures->CountItems(); 1157 link.Attach<int32>(subPicturesCount); 1158 if (subPicturesCount > 0) { 1159 for (int32 i = 0; i < subPicturesCount; i++) { 1160 ServerPicture* subPicture = fPictures->ItemAt(i); 1161 link.Attach<int32>(subPicture->Token()); 1162 } 1163 } 1164 1165 off_t size = 0; 1166 fData->GetSize(&size); 1167 link.Attach<int32>((int32)size); 1168 1169 status_t status = B_NO_MEMORY; 1170 char* buffer = new(std::nothrow) char[size]; 1171 if (buffer) { 1172 status = B_OK; 1173 ssize_t read = fData->Read(buffer, size); 1174 if (read < B_OK || link.Attach(buffer, read) < B_OK) 1175 status = B_ERROR; 1176 delete [] buffer; 1177 } 1178 1179 if (status != B_OK) { 1180 link.CancelMessage(); 1181 link.StartMessage(B_ERROR); 1182 } 1183 1184 fData->Seek(oldPosition, SEEK_SET); 1185 return status; 1186 } 1187