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 <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(View *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(View *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(View *view, BPoint delta) 181 { 182 view->CurrentState()->SetPenLocation(view->CurrentState()->PenLocation() + delta); 183 } 184 185 186 static void 187 stroke_line(View *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(View *view, BRect rect) 204 { 205 view->ConvertToScreenForDrawing(&rect); 206 view->Window()->GetDrawingEngine()->StrokeRect(rect); 207 } 208 209 210 static void 211 fill_rect(View *view, BRect rect) 212 { 213 view->ConvertToScreenForDrawing(&rect); 214 view->Window()->GetDrawingEngine()->FillRect(rect); 215 } 216 217 218 static void 219 stroke_round_rect(View *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(View *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(View *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(View *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(View *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(View *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(View *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(View *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(View *view, int32 numPoints, const BPoint *viewPoints, 300 bool isClosed) 301 { 302 if (numPoints <= 0) 303 return; 304 305 if (numPoints <= 200) { 306 // fast path: no malloc/free, also avoid constructor/destructor calls 307 char data[200 * sizeof(BPoint)]; 308 BPoint *points = (BPoint *)data; 309 310 view->ConvertToScreenForDrawing(points, viewPoints, numPoints); 311 312 BRect polyFrame; 313 get_polygon_frame(points, numPoints, &polyFrame); 314 315 view->Window()->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame, 316 false, isClosed && numPoints > 2); 317 } else { 318 // avoid constructor/destructor calls by using malloc instead of new [] 319 BPoint *points = (BPoint *)malloc(numPoints * sizeof(BPoint)); 320 if (!points) 321 return; 322 323 view->ConvertToScreenForDrawing(points, viewPoints, numPoints); 324 325 BRect polyFrame; 326 get_polygon_frame(points, numPoints, &polyFrame); 327 328 view->Window()->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame, 329 false, isClosed && numPoints > 2); 330 free(points); 331 } 332 } 333 334 335 static void 336 fill_polygon(View *view, int32 numPoints, const BPoint *viewPoints) 337 { 338 if (numPoints <= 0) 339 return; 340 341 if (numPoints <= 200) { 342 // fast path: no malloc/free, also avoid constructor/destructor calls 343 char data[200 * sizeof(BPoint)]; 344 BPoint *points = (BPoint *)data; 345 346 view->ConvertToScreenForDrawing(points, viewPoints, numPoints); 347 348 BRect polyFrame; 349 get_polygon_frame(points, numPoints, &polyFrame); 350 351 view->Window()->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame, 352 true, true); 353 } else { 354 // avoid constructor/destructor calls by using malloc instead of new [] 355 BPoint *points = (BPoint *)malloc(numPoints * sizeof(BPoint)); 356 if (!points) 357 return; 358 359 view->ConvertToScreenForDrawing(points, viewPoints, numPoints); 360 361 BRect polyFrame; 362 get_polygon_frame(points, numPoints, &polyFrame); 363 364 view->Window()->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame, 365 true, true); 366 free(points); 367 } 368 } 369 370 371 static void 372 stroke_shape(View *view, const BShape *shape) 373 { 374 ShapePainter drawShape; 375 376 drawShape.Iterate(shape); 377 drawShape.Draw(view, shape->Bounds(), false); 378 } 379 380 381 static void 382 fill_shape(View *view, const BShape *shape) 383 { 384 ShapePainter drawShape; 385 386 drawShape.Iterate(shape); 387 drawShape.Draw(view, shape->Bounds(), true); 388 } 389 390 391 static void 392 draw_string(View *view, const char *string, float deltaSpace, 393 float deltaNonSpace) 394 { 395 // NOTE: the picture data was recorded with a "set pen location" command 396 // inserted before the "draw string" command, so we can use PenLocation() 397 BPoint location = view->CurrentState()->PenLocation(); 398 399 escapement_delta delta = {deltaSpace, deltaNonSpace }; 400 view->ConvertToScreenForDrawing(&location); 401 view->Window()->GetDrawingEngine()->DrawString(string, strlen(string), 402 location, &delta); 403 404 view->ConvertFromScreenForDrawing(&location); 405 view->CurrentState()->SetPenLocation(location); 406 // the DrawingEngine/Painter does not need to be updated, since this 407 // effects only the view->screen coord conversion, which is handled 408 // by the view only 409 } 410 411 412 static void 413 draw_pixels(View *view, BRect src, BRect dest, int32 width, int32 height, 414 int32 bytesPerRow, int32 pixelFormat, int32 flags, const void *data) 415 { 416 UtilityBitmap bitmap(BRect(0, 0, width - 1, height - 1), 417 (color_space)pixelFormat, flags, bytesPerRow); 418 419 if (!bitmap.IsValid()) 420 return; 421 422 memcpy(bitmap.Bits(), data, height * bytesPerRow); 423 424 view->ConvertToScreenForDrawing(&dest); 425 426 view->Window()->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest); 427 } 428 429 430 static void 431 draw_picture(View *view, BPoint where, int32 token) 432 { 433 ServerPicture *picture = view->Window()->ServerWindow()->App()->FindPicture(token); 434 if (picture != NULL) { 435 view->CurrentState()->SetOrigin(where); 436 picture->Play(view); 437 } 438 } 439 440 441 static void 442 set_clipping_rects(View *view, const BRect *rects, uint32 numRects) 443 { 444 // TODO: This might be too slow, we should copy the rects 445 // directly to BRegion's internal data 446 BRegion region; 447 for (uint32 c = 0; c < numRects; c++) 448 region.Include(rects[c]); 449 view->SetUserClipping(®ion); 450 } 451 452 453 static void 454 clip_to_picture(View *view, BPicture *picture, BPoint pt, 455 bool clip_to_inverse_picture) 456 { 457 printf("ClipToPicture(picture, BPoint(%.2f, %.2f), %s)\n", pt.x, pt.y, 458 clip_to_inverse_picture ? "inverse" : ""); 459 } 460 461 462 static void 463 push_state(View *view) 464 { 465 view->PushState(); 466 } 467 468 469 static void 470 pop_state(View *view) 471 { 472 view->PopState(); 473 474 BPoint p(0, 0); 475 view->ConvertToScreenForDrawing(&p); 476 view->Window()->GetDrawingEngine()->SetDrawState( 477 view->CurrentState(), p.x, p.y); 478 } 479 480 481 // TODO: Be smart and actually take advantage of these methods: 482 // only apply state changes when they are called 483 static void 484 enter_state_change(View *view) 485 { 486 } 487 488 489 static void 490 exit_state_change(View *view) 491 { 492 view->Window()->ServerWindow()->ResyncDrawState(); 493 } 494 495 496 static void 497 enter_font_state(View *view) 498 { 499 } 500 501 502 static void 503 exit_font_state(View *view) 504 { 505 view->Window()->GetDrawingEngine()->SetFont(view->CurrentState()->Font()); 506 } 507 508 509 static void 510 set_origin(View *view, BPoint pt) 511 { 512 view->CurrentState()->SetOrigin(pt); 513 } 514 515 516 static void 517 set_pen_location(View *view, BPoint pt) 518 { 519 view->CurrentState()->SetPenLocation(pt); 520 // the DrawingEngine/Painter does not need to be updated, since this 521 // effects only the view->screen coord conversion, which is handled 522 // by the view only 523 } 524 525 526 static void 527 set_drawing_mode(View *view, drawing_mode mode) 528 { 529 view->CurrentState()->SetDrawingMode(mode); 530 view->Window()->GetDrawingEngine()->SetDrawingMode(mode); 531 } 532 533 534 static void 535 set_line_mode(View *view, cap_mode capMode, join_mode joinMode, float miterLimit) 536 { 537 DrawState *state = view->CurrentState(); 538 state->SetLineCapMode(capMode); 539 state->SetLineJoinMode(joinMode); 540 state->SetMiterLimit(miterLimit); 541 view->Window()->GetDrawingEngine()->SetStrokeMode(capMode, joinMode, miterLimit); 542 } 543 544 545 static void 546 set_pen_size(View *view, float size) 547 { 548 view->CurrentState()->SetPenSize(size); 549 view->Window()->GetDrawingEngine()->SetPenSize(view->CurrentState()->PenSize()); 550 // DrawState::PenSize() returns the scaled pen size, so we need to 551 // use that value to set the drawing engine pen size. 552 } 553 554 555 static void 556 set_fore_color(View *view, rgb_color color) 557 { 558 view->CurrentState()->SetHighColor(color); 559 view->Window()->GetDrawingEngine()->SetHighColor(color); 560 } 561 562 563 static void 564 set_back_color(View *view, rgb_color color) 565 { 566 view->CurrentState()->SetLowColor(color); 567 view->Window()->GetDrawingEngine()->SetLowColor(color); 568 } 569 570 571 static void 572 set_stipple_pattern(View *view, pattern p) 573 { 574 view->CurrentState()->SetPattern(Pattern(p)); 575 view->Window()->GetDrawingEngine()->SetPattern(p); 576 } 577 578 579 static void 580 set_scale(View *view, float scale) 581 { 582 view->CurrentState()->SetScale(scale); 583 view->Window()->ServerWindow()->ResyncDrawState(); 584 585 // Update the drawing engine draw state, since some stuff (for example 586 // the pen size) needs to be recalculated. 587 } 588 589 590 static void 591 set_font_family(View *view, const char *family) 592 { 593 // TODO: Implement 594 // Can we have a ServerFont::SetFamily() which accepts a string ? 595 } 596 597 598 static void 599 set_font_style(View *view, const char *style) 600 { 601 // TODO: Implement 602 // Can we have a ServerFont::SetStyle() which accepts a string ? 603 } 604 605 606 static void 607 set_font_spacing(View *view, int32 spacing) 608 { 609 ServerFont font; 610 font.SetSpacing(spacing); 611 view->CurrentState()->SetFont(font, B_FONT_SPACING); 612 } 613 614 615 static void 616 set_font_size(View *view, float size) 617 { 618 ServerFont font; 619 font.SetSize(size); 620 view->CurrentState()->SetFont(font, B_FONT_SIZE); 621 } 622 623 624 static void 625 set_font_rotate(View *view, float rotation) 626 { 627 ServerFont font; 628 font.SetRotation(rotation); 629 view->CurrentState()->SetFont(font, B_FONT_ROTATION); 630 } 631 632 633 static void 634 set_font_encoding(View *view, int32 encoding) 635 { 636 ServerFont font; 637 font.SetEncoding(encoding); 638 view->CurrentState()->SetFont(font, B_FONT_ENCODING); 639 } 640 641 642 static void 643 set_font_flags(View *view, int32 flags) 644 { 645 ServerFont font; 646 font.SetFlags(flags); 647 view->CurrentState()->SetFont(font, B_FONT_FLAGS); 648 } 649 650 651 static void 652 set_font_shear(View *view, float shear) 653 { 654 ServerFont font; 655 font.SetShear(shear); 656 view->CurrentState()->SetFont(font, B_FONT_SHEAR); 657 } 658 659 660 static void 661 set_font_face(View *view, int32 face) 662 { 663 ServerFont font; 664 font.SetFace(face); 665 view->CurrentState()->SetFont(font, B_FONT_FACE); 666 } 667 668 669 static void 670 set_blending_mode(View *view, int16 alphaSrcMode, int16 alphaFncMode) 671 { 672 view->CurrentState()->SetBlendingMode((source_alpha)alphaSrcMode, (alpha_function)alphaFncMode); 673 } 674 675 676 static void 677 reserved() 678 { 679 } 680 681 682 const static void *kTableEntries[] = { 683 (const void *)nop, 684 (const void *)move_pen_by, 685 (const void *)stroke_line, 686 (const void *)stroke_rect, 687 (const void *)fill_rect, 688 (const void *)stroke_round_rect, 689 (const void *)fill_round_rect, 690 (const void *)stroke_bezier, 691 (const void *)fill_bezier, 692 (const void *)stroke_arc, 693 (const void *)fill_arc, 694 (const void *)stroke_ellipse, 695 (const void *)fill_ellipse, 696 (const void *)stroke_polygon, 697 (const void *)fill_polygon, 698 (const void *)stroke_shape, 699 (const void *)fill_shape, 700 (const void *)draw_string, 701 (const void *)draw_pixels, 702 (const void *)draw_picture, 703 (const void *)set_clipping_rects, 704 (const void *)clip_to_picture, 705 (const void *)push_state, 706 (const void *)pop_state, 707 (const void *)enter_state_change, 708 (const void *)exit_state_change, 709 (const void *)enter_font_state, 710 (const void *)exit_font_state, 711 (const void *)set_origin, 712 (const void *)set_pen_location, 713 (const void *)set_drawing_mode, 714 (const void *)set_line_mode, 715 (const void *)set_pen_size, 716 (const void *)set_fore_color, 717 (const void *)set_back_color, 718 (const void *)set_stipple_pattern, 719 (const void *)set_scale, 720 (const void *)set_font_family, 721 (const void *)set_font_style, 722 (const void *)set_font_spacing, 723 (const void *)set_font_size, 724 (const void *)set_font_rotate, 725 (const void *)set_font_encoding, 726 (const void *)set_font_flags, 727 (const void *)set_font_shear, 728 (const void *)reserved, // TODO: Marc Flerackers calls this "set_font_bpp". Investigate 729 (const void *)set_font_face, 730 (const void *)set_blending_mode 731 }; 732 733 734 // ServerPicture 735 ServerPicture::ServerPicture() 736 : 737 PictureDataWriter(), 738 fData(NULL), 739 fPictures(NULL), 740 fUsurped(NULL) 741 { 742 fToken = gTokenSpace.NewToken(kPictureToken, this); 743 fData = new (std::nothrow) BMallocIO(); 744 745 PictureDataWriter::SetTo(fData); 746 } 747 748 749 ServerPicture::ServerPicture(const ServerPicture &picture) 750 : 751 PictureDataWriter(), 752 fData(NULL), 753 fPictures(NULL), 754 fUsurped(NULL) 755 { 756 BMallocIO *mallocIO = new (std::nothrow) BMallocIO(); 757 if (mallocIO == NULL) 758 return; 759 760 fData = mallocIO; 761 762 const off_t size = picture.DataLength(); 763 if (mallocIO->SetSize(size) < B_OK) 764 return; 765 766 fToken = gTokenSpace.NewToken(kPictureToken, this); 767 768 picture.fData->ReadAt(0, const_cast<void *>(mallocIO->Buffer()), size); 769 770 PictureDataWriter::SetTo(fData); 771 } 772 773 774 ServerPicture::ServerPicture(const char *fileName, const int32 &offset) 775 : 776 PictureDataWriter(), 777 fData(NULL), 778 fPictures(NULL), 779 fUsurped(NULL) 780 { 781 BPrivate::Storage::OffsetFile *file = 782 new BPrivate::Storage::OffsetFile(new BFile(fileName, B_READ_WRITE), (off_t)offset); 783 784 if (file == NULL || file->InitCheck() != B_OK) 785 return; 786 787 fData = file; 788 fToken = gTokenSpace.NewToken(kPictureToken, this); 789 790 PictureDataWriter::SetTo(fData); 791 } 792 793 794 ServerPicture::~ServerPicture() 795 { 796 delete fData; 797 gTokenSpace.RemoveToken(fToken); 798 799 // We only delete the subpictures list, not the subpictures themselves, 800 // since the ServerApp keeps them in a list and will delete them on quit. 801 delete fPictures; 802 } 803 804 805 void 806 ServerPicture::EnterStateChange() 807 { 808 BeginOp(B_PIC_ENTER_STATE_CHANGE); 809 } 810 811 812 void 813 ServerPicture::ExitStateChange() 814 { 815 EndOp(); 816 } 817 818 819 void 820 ServerPicture::SyncState(View *view) 821 { 822 // TODO: Finish this 823 EnterStateChange(); 824 825 WriteSetOrigin(view->CurrentState()->Origin()); 826 WriteSetPenLocation(view->CurrentState()->PenLocation()); 827 WriteSetPenSize(view->CurrentState()->PenSize()); 828 WriteSetScale(view->CurrentState()->Scale()); 829 WriteSetLineMode(view->CurrentState()->LineCapMode(), view->CurrentState()->LineJoinMode(), 830 view->CurrentState()->MiterLimit()); 831 //WriteSetPattern(*view->CurrentState()->GetPattern().GetInt8()); 832 WriteSetDrawingMode(view->CurrentState()->GetDrawingMode()); 833 834 WriteSetHighColor(view->CurrentState()->HighColor()); 835 WriteSetLowColor(view->CurrentState()->LowColor()); 836 837 ExitStateChange(); 838 } 839 840 void 841 ServerPicture::SetFontFromLink(BPrivate::LinkReceiver& link) 842 { 843 BeginOp(B_PIC_ENTER_FONT_STATE); 844 845 uint16 mask; 846 link.Read<uint16>(&mask); 847 848 if (mask & B_FONT_FAMILY_AND_STYLE) { 849 uint32 fontID; 850 link.Read<uint32>(&fontID); 851 ServerFont font; 852 font.SetFamilyAndStyle(fontID); 853 WriteSetFontFamily(font.Family()); 854 WriteSetFontStyle(font.Style()); 855 } 856 857 if (mask & B_FONT_SIZE) { 858 float size; 859 link.Read<float>(&size); 860 WriteSetFontSize(size); 861 } 862 863 if (mask & B_FONT_SHEAR) { 864 float shear; 865 link.Read<float>(&shear); 866 WriteSetFontShear(shear); 867 } 868 869 if (mask & B_FONT_ROTATION) { 870 float rotation; 871 link.Read<float>(&rotation); 872 WriteSetFontRotation(rotation); 873 } 874 875 if (mask & B_FONT_FALSE_BOLD_WIDTH) { 876 float falseBoldWidth; 877 link.Read<float>(&falseBoldWidth); 878 //SetFalseBoldWidth(falseBoldWidth); 879 } 880 881 if (mask & B_FONT_SPACING) { 882 uint8 spacing; 883 link.Read<uint8>(&spacing); 884 WriteSetFontSpacing(spacing); 885 } 886 887 if (mask & B_FONT_ENCODING) { 888 uint8 encoding; 889 link.Read<uint8>((uint8*)&encoding); 890 WriteSetFontEncoding(encoding); 891 } 892 893 if (mask & B_FONT_FACE) { 894 uint16 face; 895 link.Read<uint16>(&face); 896 WriteSetFontFace(face); 897 } 898 899 if (mask & B_FONT_FLAGS) { 900 uint32 flags; 901 link.Read<uint32>(&flags); 902 WriteSetFontFlags(flags); 903 } 904 905 EndOp(); 906 } 907 908 909 void 910 ServerPicture::Play(View *view) 911 { 912 // TODO: for now: then change PicturePlayer to accept a BPositionIO object 913 BMallocIO *mallocIO = dynamic_cast<BMallocIO *>(fData); 914 if (mallocIO == NULL) 915 return; 916 917 BPrivate::PicturePlayer player(mallocIO->Buffer(), mallocIO->BufferLength(), fPictures); 918 player.Play(const_cast<void **>(kTableEntries), sizeof(kTableEntries) / sizeof(void *), view); 919 } 920 921 922 void 923 ServerPicture::Usurp(ServerPicture *picture) 924 { 925 fUsurped = picture; 926 } 927 928 929 ServerPicture * 930 ServerPicture::StepDown() 931 { 932 ServerPicture *old = fUsurped; 933 fUsurped = NULL; 934 return old; 935 } 936 937 938 bool 939 ServerPicture::NestPicture(ServerPicture *picture) 940 { 941 if (fPictures == NULL) 942 fPictures = new (std::nothrow) BList; 943 944 if (fPictures == NULL 945 || !fPictures->AddItem(picture)) 946 return false; 947 948 return true; 949 } 950 951 952 off_t 953 ServerPicture::DataLength() const 954 { 955 if (fData == NULL) 956 return 0; 957 off_t size; 958 fData->GetSize(&size); 959 return size; 960 } 961 962 963 #define BUFFER_SIZE 4096 964 965 966 status_t 967 ServerPicture::ImportData(BPrivate::LinkReceiver &link) 968 { 969 int32 size = 0; 970 link.Read<int32>(&size); 971 972 if (size >= 65536) { 973 //TODO: Pass via an area. 974 // Ideally the Link** api would allow to write partial messages, 975 // so that a big picture could be written in chunks of 4096 bytes 976 // or so 977 return B_ERROR; 978 } 979 980 off_t oldPosition = fData->Position(); 981 fData->Seek(0, SEEK_SET); 982 983 // TODO: Oh yeah... 65kb on the stack... 984 char buffer[size]; 985 status_t read = link.Read(buffer, size); 986 if (read < B_OK) 987 return (status_t)read; 988 989 fData->Write(buffer, size); 990 991 fData->Seek(oldPosition, SEEK_SET); 992 993 return B_OK; 994 } 995 996 997 status_t 998 ServerPicture::ExportData(BPrivate::PortLink &link) 999 { 1000 link.StartMessage(B_OK); 1001 1002 off_t oldPosition = fData->Position(); 1003 fData->Seek(0, SEEK_SET); 1004 1005 int32 subPicturesCount = 0; 1006 if (fPictures != NULL) 1007 subPicturesCount = fPictures->CountItems(); 1008 link.Attach<int32>(subPicturesCount); 1009 if (subPicturesCount > 0) { 1010 for (int32 i = 0; i < subPicturesCount; i++) { 1011 ServerPicture *subPic = static_cast<ServerPicture *>(fPictures->ItemAtFast(i)); 1012 link.Attach<int32>(subPic->Token()); 1013 } 1014 } 1015 1016 off_t size = 0; 1017 fData->GetSize(&size); 1018 link.Attach<int32>((int32)size); 1019 if (size >= 65536) { 1020 //TODO: Pass via an area 1021 link.CancelMessage(); 1022 link.StartMessage(B_ERROR); 1023 return B_ERROR; 1024 } 1025 // TODO: Oh yeah... 65kb on the stack... 1026 char buffer[size]; 1027 ssize_t read = fData->Read(buffer, size); 1028 if (read < B_OK) 1029 return (status_t)read; 1030 if (link.Attach(buffer, read) < B_OK) { 1031 // 1032 link.CancelMessage(); 1033 link.StartMessage(B_ERROR); 1034 }; 1035 1036 1037 fData->Seek(oldPosition, SEEK_SET); 1038 1039 return B_OK; 1040 } 1041 1042 1043