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