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