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