1 /* 2 * Copyright 2001-2015, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marc Flerackers (mflerackers@androme.be) 7 * Stefano Ceccherini (stefano.ceccherini@gmail.com) 8 * Marcus Overhagen <marcus@overhagen.de> 9 * Julian Harnath <julian.harnath@rwth-aachen.de> 10 */ 11 12 #include "PictureBoundingBoxPlayer.h" 13 14 #include <new> 15 #include <stdio.h> 16 17 #include "DrawState.h" 18 #include "GlobalFontManager.h" 19 #include "Layer.h" 20 #include "ServerApp.h" 21 #include "ServerBitmap.h" 22 #include "ServerFont.h" 23 #include "ServerPicture.h" 24 #include "ServerTokenSpace.h" 25 #include "View.h" 26 #include "Window.h" 27 28 #include <AutoDeleter.h> 29 #include <Bitmap.h> 30 #include <Debug.h> 31 #include <List.h> 32 #include <ObjectListPrivate.h> 33 #include <PicturePlayer.h> 34 #include <PictureProtocol.h> 35 #include <Shape.h> 36 37 38 //#define DEBUG_TRACE_BB 39 #ifdef DEBUG_TRACE_BB 40 # define TRACE_BB(text, ...) debug_printf("PBBP: " text, ##__VA_ARGS__) 41 #else 42 # define TRACE_BB(text, ...) 43 #endif 44 45 46 typedef PictureBoundingBoxPlayer::State BoundingBoxState; 47 48 49 // #pragma mark - PictureBoundingBoxPlayer::State 50 51 52 class PictureBoundingBoxPlayer::State { 53 public: 54 State(const DrawState* drawState, BRect* boundingBox) 55 : 56 fDrawState(drawState->Squash()), 57 fBoundingBox(boundingBox) 58 { 59 fBoundingBox->Set(INT_MAX, INT_MAX, INT_MIN, INT_MIN); 60 } 61 62 ~State() 63 { 64 } 65 66 DrawState* GetDrawState() 67 { 68 return fDrawState.Get(); 69 } 70 71 void PushDrawState() 72 { 73 DrawState* previousState = fDrawState.Detach(); 74 DrawState* newState = previousState->PushState(); 75 if (newState == NULL) 76 newState = previousState; 77 78 fDrawState.SetTo(newState); 79 } 80 81 void PopDrawState() 82 { 83 if (fDrawState->PreviousState() != NULL) 84 fDrawState.SetTo(fDrawState->PopState()); 85 } 86 87 SimpleTransform PenToLocalTransform() const 88 { 89 SimpleTransform transform; 90 fDrawState->Transform(transform); 91 return transform; 92 } 93 94 void IncludeRect(BRect& rect) 95 { 96 _AffineTransformRect(rect); 97 *fBoundingBox = (*fBoundingBox) | rect; 98 } 99 100 private: 101 void _AffineTransformRect(BRect& rect) 102 { 103 BAffineTransform transform = fDrawState->CombinedTransform(); 104 if (transform.IsIdentity()) 105 return; 106 107 BPoint transformedShape[4]; 108 transformedShape[0] = rect.LeftTop(); 109 transformedShape[1] = rect.LeftBottom(); 110 transformedShape[2] = rect.RightTop(); 111 transformedShape[3] = rect.RightBottom(); 112 113 transform.Apply(&transformedShape[0], 4); 114 115 float minX = INT_MAX; 116 float minY = INT_MAX; 117 float maxX = INT_MIN; 118 float maxY = INT_MIN; 119 120 for (uint32 i = 0; i < 4; i++) { 121 if (transformedShape[i].x < minX) 122 minX = transformedShape[i].x; 123 else if (transformedShape[i].x > maxX) 124 maxX = transformedShape[i].x; 125 if (transformedShape[i].y < minY) 126 minY = transformedShape[i].y; 127 else if (transformedShape[i].y > maxY) 128 maxY = transformedShape[i].y; 129 } 130 131 rect.Set(minX, minY, maxX, maxY); 132 } 133 134 135 private: 136 ObjectDeleter<DrawState> 137 fDrawState; 138 BRect* fBoundingBox; 139 }; 140 141 142 // #pragma mark - Picture playback hooks 143 144 145 static void 146 get_polygon_frame(const BPoint* points, int32 numPoints, BRect* frame) 147 { 148 ASSERT(numPoints > 0); 149 150 float left = points->x; 151 float top = points->y; 152 float right = left; 153 float bottom = top; 154 155 points++; 156 numPoints--; 157 158 while (numPoints--) { 159 if (points->x < left) 160 left = points->x; 161 if (points->x > right) 162 right = points->x; 163 if (points->y < top) 164 top = points->y; 165 if (points->y > bottom) 166 bottom = points->y; 167 points++; 168 } 169 170 frame->Set(left, top, right, bottom); 171 } 172 173 174 template<class RectType> 175 static void 176 expand_rect_for_pen_size(BoundingBoxState* state, RectType& rect) 177 { 178 float penInset = -((state->GetDrawState()->PenSize() / 2.0f) + 1.0f); 179 rect.InsetBy(penInset, penInset); 180 } 181 182 183 static void 184 move_pen_by(void* _state, const BPoint& delta) 185 { 186 TRACE_BB("%p move pen by %.2f %.2f\n", _state, delta.x, delta.y); 187 BoundingBoxState* const state = 188 reinterpret_cast<BoundingBoxState*>(_state); 189 190 state->GetDrawState()->SetPenLocation( 191 state->GetDrawState()->PenLocation() + delta); 192 } 193 194 195 static void 196 determine_bounds_stroke_line(void* _state, const BPoint& _start, 197 const BPoint& _end) 198 { 199 TRACE_BB("%p stroke line %.2f %.2f -> %.2f %.2f\n", _state, 200 _start.x, _start.y, _end.x, _end.y); 201 BoundingBoxState* const state = 202 reinterpret_cast<BoundingBoxState*>(_state); 203 204 BPoint start = _start; 205 BPoint end = _end; 206 207 const SimpleTransform transform = state->PenToLocalTransform(); 208 transform.Apply(&start); 209 transform.Apply(&end); 210 211 BRect rect; 212 if (start.x <= end.x) { 213 rect.left = start.x; 214 rect.right = end.x; 215 } else { 216 rect.left = end.x; 217 rect.right = start.x; 218 } 219 if (start.y <= end.y) { 220 rect.top = start.y; 221 rect.bottom = end.y; 222 } else { 223 rect.top = end.y; 224 rect.bottom = start.y; 225 } 226 227 expand_rect_for_pen_size(state, rect); 228 state->IncludeRect(rect); 229 230 state->GetDrawState()->SetPenLocation(_end); 231 } 232 233 234 static void 235 determine_bounds_draw_rect(void* _state, const BRect& _rect, bool fill) 236 { 237 TRACE_BB("%p draw rect fill=%d %.2f %.2f %.2f %.2f\n", _state, fill, 238 _rect.left, _rect.top, _rect.right, _rect.bottom); 239 BoundingBoxState* const state = 240 reinterpret_cast<BoundingBoxState*>(_state); 241 242 BRect rect = _rect; 243 state->PenToLocalTransform().Apply(&rect); 244 if (!fill) 245 expand_rect_for_pen_size(state, rect); 246 state->IncludeRect(rect); 247 } 248 249 250 static void 251 determine_bounds_draw_round_rect(void* _state, const BRect& _rect, 252 const BPoint&, bool fill) 253 { 254 determine_bounds_draw_rect(_state, _rect, fill); 255 } 256 257 258 static void 259 determine_bounds_bezier(BoundingBoxState* state, const BPoint* viewPoints, 260 BRect& outRect) 261 { 262 // Note: this is an approximation which results in a rectangle which 263 // encloses all four control points. That will always enclose the curve, 264 // although not necessarily tightly, but it's good enough for the purpose. 265 // The exact bounding box of a bezier curve is not trivial to determine, 266 // (need to calculate derivative of the curve) and we're going for 267 // performance here. 268 BPoint points[4]; 269 state->PenToLocalTransform().Apply(points, viewPoints, 4); 270 BPoint topLeft = points[0]; 271 BPoint bottomRight = points[0]; 272 for (uint32 index = 1; index < 4; index++) { 273 if (points[index].x < topLeft.x || points[index].y < topLeft.y) 274 topLeft = points[index]; 275 if (points[index].x > topLeft.x || points[index].y > topLeft.y) 276 bottomRight = points[index]; 277 } 278 outRect.SetLeftTop(topLeft); 279 outRect.SetRightBottom(bottomRight); 280 } 281 282 283 static void 284 determine_bounds_draw_bezier(void* _state, size_t numPoints, 285 const BPoint viewPoints[], bool fill) 286 { 287 TRACE_BB("%p draw bezier fill=%d (%.2f %.2f) (%.2f %.2f) " 288 "(%.2f %.2f) (%.2f %.2f)\n", 289 _state, 290 fill, 291 viewPoints[0].x, viewPoints[0].y, 292 viewPoints[1].x, viewPoints[1].y, 293 viewPoints[2].x, viewPoints[2].y, 294 viewPoints[3].x, viewPoints[3].y); 295 BoundingBoxState* const state = 296 reinterpret_cast<BoundingBoxState*>(_state); 297 298 const size_t kSupportedPoints = 4; 299 if (numPoints != kSupportedPoints) 300 return; 301 302 BRect rect; 303 determine_bounds_bezier(state, viewPoints, rect); 304 if (!fill) 305 expand_rect_for_pen_size(state, rect); 306 state->IncludeRect(rect); 307 } 308 309 310 static void 311 determine_bounds_draw_ellipse(void* _state, const BRect& _rect, bool fill) 312 { 313 TRACE_BB("%p draw ellipse fill=%d (%.2f %.2f) (%.2f %.2f)\n", _state, fill, 314 _rect.left, _rect.top, _rect.right, _rect.bottom); 315 BoundingBoxState* const state = 316 reinterpret_cast<BoundingBoxState*>(_state); 317 318 BRect rect = _rect; 319 state->PenToLocalTransform().Apply(&rect); 320 if (!fill) 321 expand_rect_for_pen_size(state, rect); 322 state->IncludeRect(rect); 323 } 324 325 326 static void 327 determine_bounds_draw_arc(void* _state, const BPoint& center, 328 const BPoint& radii, float, float, bool fill) 329 { 330 BRect rect(center.x - radii.x, center.y - radii.y, 331 center.x + radii.x - 1, center.y + radii.y - 1); 332 determine_bounds_draw_ellipse(_state, rect, fill); 333 } 334 335 336 static void 337 determine_bounds_polygon(BoundingBoxState* state, int32 numPoints, 338 const BPoint* viewPoints, BRect& outRect) 339 { 340 if (numPoints <= 0) 341 return; 342 343 if (numPoints <= 200) { 344 // fast path: no malloc/free, also avoid 345 // constructor/destructor calls 346 char data[200 * sizeof(BPoint)]; 347 BPoint* points = (BPoint*)data; 348 349 state->PenToLocalTransform().Apply(points, viewPoints, numPoints); 350 get_polygon_frame(points, numPoints, &outRect); 351 352 } else { 353 // avoid constructor/destructor calls by 354 // using malloc instead of new [] 355 BPoint* points = (BPoint*)malloc(numPoints * sizeof(BPoint)); 356 if (points == NULL) 357 return; 358 359 state->PenToLocalTransform().Apply(points, viewPoints, numPoints); 360 get_polygon_frame(points, numPoints, &outRect); 361 362 free(points); 363 } 364 } 365 366 367 void 368 determine_bounds_draw_polygon(void* _state, size_t numPoints, 369 const BPoint viewPoints[], bool, bool fill) 370 { 371 TRACE_BB("%p draw polygon fill=%d (%ld points)\n", _state, fill, numPoints); 372 BoundingBoxState* const state = 373 reinterpret_cast<BoundingBoxState*>(_state); 374 375 BRect rect; 376 determine_bounds_polygon(state, numPoints, viewPoints, rect); 377 if (!fill) 378 expand_rect_for_pen_size(state, rect); 379 state->IncludeRect(rect); 380 } 381 382 383 static void 384 determine_bounds_draw_shape(void* _state, const BShape& shape, bool fill) 385 { 386 BRect rect = shape.Bounds(); 387 388 TRACE_BB("%p stroke shape (bounds %.2f %.2f %.2f %.2f)\n", _state, 389 rect.left, rect.top, rect.right, rect.bottom); 390 BoundingBoxState* const state = 391 reinterpret_cast<BoundingBoxState*>(_state); 392 393 state->PenToLocalTransform().Apply(&rect); 394 if (!fill) 395 expand_rect_for_pen_size(state, rect); 396 state->IncludeRect(rect); 397 } 398 399 400 static void 401 determine_bounds_draw_string(void* _state, const char* string, size_t length, 402 float deltaSpace, float deltaNonSpace) 403 { 404 TRACE_BB("%p string '%s'\n", _state, string); 405 BoundingBoxState* const state = 406 reinterpret_cast<BoundingBoxState*>(_state); 407 408 ServerFont font = state->GetDrawState()->Font(); 409 410 escapement_delta delta = { deltaSpace, deltaNonSpace }; 411 BRect rect; 412 font.GetBoundingBoxesForStrings((char**)&string, &length, 1, &rect, 413 B_SCREEN_METRIC, &delta); 414 415 BPoint location = state->GetDrawState()->PenLocation(); 416 417 state->PenToLocalTransform().Apply(&location); 418 rect.OffsetBy(location); 419 state->IncludeRect(rect); 420 421 state->PenToLocalTransform().Apply(&location); 422 state->GetDrawState()->SetPenLocation(location); 423 } 424 425 426 static void 427 determine_bounds_draw_pixels(void* _state, const BRect&, const BRect& _dest, 428 uint32, uint32, size_t, color_space, uint32, const void*, size_t) 429 { 430 TRACE_BB("%p pixels (dest %.2f %.2f %.2f %.2f)\n", _state, 431 _dest.left, _dest.top, _dest.right, _dest.bottom); 432 BoundingBoxState* const state = 433 reinterpret_cast<BoundingBoxState*>(_state); 434 435 BRect dest = _dest; 436 state->PenToLocalTransform().Apply(&dest); 437 state->IncludeRect(dest); 438 } 439 440 441 static void 442 draw_picture(void* _state, const BPoint& where, int32 token) 443 { 444 TRACE_BB("%p picture (unimplemented)\n", _state); 445 446 // TODO 447 (void)_state; 448 (void)where; 449 (void)token; 450 } 451 452 453 static void 454 set_clipping_rects(void* _state, size_t numRects, const BRect rects[]) 455 { 456 TRACE_BB("%p cliping rects (%ld rects)\n", _state, numRects); 457 458 // TODO 459 (void)_state; 460 (void)rects; 461 (void)numRects; 462 } 463 464 465 static void 466 clip_to_picture(void* _state, int32 pictureToken, const BPoint& where, 467 bool clipToInverse) 468 { 469 TRACE_BB("%p clip to picture (unimplemented)\n", _state); 470 471 // TODO 472 } 473 474 475 static void 476 push_state(void* _state) 477 { 478 TRACE_BB("%p push state\n", _state); 479 BoundingBoxState* const state = 480 reinterpret_cast<BoundingBoxState*>(_state); 481 482 state->PushDrawState(); 483 } 484 485 486 static void 487 pop_state(void* _state) 488 { 489 TRACE_BB("%p pop state\n", _state); 490 BoundingBoxState* const state = 491 reinterpret_cast<BoundingBoxState*>(_state); 492 493 state->PopDrawState(); 494 } 495 496 497 static void 498 enter_state_change(void*) 499 { 500 } 501 502 503 static void 504 exit_state_change(void*) 505 { 506 } 507 508 509 static void 510 enter_font_state(void*) 511 { 512 } 513 514 515 static void 516 exit_font_state(void*) 517 { 518 } 519 520 521 static void 522 set_origin(void* _state, const BPoint& pt) 523 { 524 TRACE_BB("%p set origin %.2f %.2f\n", _state, pt.x, pt.y); 525 BoundingBoxState* const state = 526 reinterpret_cast<BoundingBoxState*>(_state); 527 state->GetDrawState()->SetOrigin(pt); 528 } 529 530 531 static void 532 set_pen_location(void* _state, const BPoint& pt) 533 { 534 TRACE_BB("%p set pen location %.2f %.2f\n", _state, pt.x, pt.y); 535 BoundingBoxState* const state = 536 reinterpret_cast<BoundingBoxState*>(_state); 537 state->GetDrawState()->SetPenLocation(pt); 538 } 539 540 541 static void 542 set_drawing_mode(void*, drawing_mode) 543 { 544 } 545 546 547 static void 548 set_line_mode(void* _state, cap_mode capMode, join_mode joinMode, 549 float miterLimit) 550 { 551 BoundingBoxState* const state = 552 reinterpret_cast<BoundingBoxState*>(_state); 553 554 DrawState* drawState = state->GetDrawState(); 555 drawState->SetLineCapMode(capMode); 556 drawState->SetLineJoinMode(joinMode); 557 drawState->SetMiterLimit(miterLimit); 558 } 559 560 561 static void 562 set_pen_size(void* _state, float size) 563 { 564 TRACE_BB("%p set pen size %.2f\n", _state, size); 565 BoundingBoxState* const state = 566 reinterpret_cast<BoundingBoxState*>(_state); 567 568 state->GetDrawState()->SetPenSize(size); 569 } 570 571 572 static void 573 set_fore_color(void* _state, const rgb_color& color) 574 { 575 BoundingBoxState* const state = 576 reinterpret_cast<BoundingBoxState*>(_state); 577 578 state->GetDrawState()->SetHighColor(color); 579 } 580 581 582 static void 583 set_back_color(void* _state, const rgb_color& color) 584 { 585 BoundingBoxState* const state = 586 reinterpret_cast<BoundingBoxState*>(_state); 587 588 state->GetDrawState()->SetLowColor(color); 589 } 590 591 592 static void 593 set_stipple_pattern(void* _state, const pattern& _pattern) 594 { 595 BoundingBoxState* const state = 596 reinterpret_cast<BoundingBoxState*>(_state); 597 598 state->GetDrawState()->SetPattern(Pattern(_pattern)); 599 } 600 601 602 static void 603 set_scale(void* _state, float scale) 604 { 605 BoundingBoxState* const state = 606 reinterpret_cast<BoundingBoxState*>(_state); 607 608 state->GetDrawState()->SetScale(scale); 609 } 610 611 612 static void 613 set_font_family(void* _state, const char* _family, size_t length) 614 { 615 BoundingBoxState* const state = 616 reinterpret_cast<BoundingBoxState*>(_state); 617 618 BString family(_family, length); 619 gFontManager->Lock(); 620 FontStyle* fontStyle = gFontManager->GetStyleByIndex(family, 0); 621 ServerFont font; 622 font.SetStyle(fontStyle); 623 gFontManager->Unlock(); 624 state->GetDrawState()->SetFont(font, B_FONT_FAMILY_AND_STYLE); 625 } 626 627 628 static void 629 set_font_style(void* _state, const char* _style, size_t length) 630 { 631 BoundingBoxState* const state = 632 reinterpret_cast<BoundingBoxState*>(_state); 633 634 BString style(_style, length); 635 ServerFont font(state->GetDrawState()->Font()); 636 gFontManager->Lock(); 637 FontStyle* fontStyle = gFontManager->GetStyle(font.Family(), style); 638 font.SetStyle(fontStyle); 639 gFontManager->Unlock(); 640 state->GetDrawState()->SetFont(font, B_FONT_FAMILY_AND_STYLE); 641 } 642 643 644 static void 645 set_font_spacing(void* _state, uint8 spacing) 646 { 647 BoundingBoxState* const state = 648 reinterpret_cast<BoundingBoxState*>(_state); 649 650 ServerFont font; 651 font.SetSpacing(spacing); 652 state->GetDrawState()->SetFont(font, B_FONT_SPACING); 653 } 654 655 656 static void 657 set_font_size(void* _state, float size) 658 { 659 BoundingBoxState* const state = 660 reinterpret_cast<BoundingBoxState*>(_state); 661 662 ServerFont font; 663 font.SetSize(size); 664 state->GetDrawState()->SetFont(font, B_FONT_SIZE); 665 } 666 667 668 static void 669 set_font_rotate(void* _state, float rotation) 670 { 671 BoundingBoxState* const state = 672 reinterpret_cast<BoundingBoxState*>(_state); 673 674 ServerFont font; 675 font.SetRotation(rotation); 676 state->GetDrawState()->SetFont(font, B_FONT_ROTATION); 677 } 678 679 680 static void 681 set_font_encoding(void* _state, uint8 encoding) 682 { 683 BoundingBoxState* const state = 684 reinterpret_cast<BoundingBoxState*>(_state); 685 686 ServerFont font; 687 font.SetEncoding(encoding); 688 state->GetDrawState()->SetFont(font, B_FONT_ENCODING); 689 } 690 691 692 static void 693 set_font_flags(void* _state, uint32 flags) 694 { 695 BoundingBoxState* const state = 696 reinterpret_cast<BoundingBoxState*>(_state); 697 698 ServerFont font; 699 font.SetFlags(flags); 700 state->GetDrawState()->SetFont(font, B_FONT_FLAGS); 701 } 702 703 704 static void 705 set_font_shear(void* _state, float shear) 706 { 707 BoundingBoxState* const state = 708 reinterpret_cast<BoundingBoxState*>(_state); 709 710 ServerFont font; 711 font.SetShear(shear); 712 state->GetDrawState()->SetFont(font, B_FONT_SHEAR); 713 } 714 715 716 static void 717 set_font_face(void* _state, uint16 face) 718 { 719 BoundingBoxState* const state = 720 reinterpret_cast<BoundingBoxState*>(_state); 721 722 ServerFont font; 723 font.SetFace(face); 724 state->GetDrawState()->SetFont(font, B_FONT_FACE); 725 } 726 727 728 static void 729 set_blending_mode(void*, source_alpha, alpha_function) 730 { 731 } 732 733 734 static void 735 set_transform(void* _state, const BAffineTransform& transform) 736 { 737 TRACE_BB("%p transform\n", _state); 738 BoundingBoxState* const state = 739 reinterpret_cast<BoundingBoxState*>(_state); 740 state->GetDrawState()->SetTransform(transform); 741 } 742 743 744 static void 745 translate_by(void* _state, double x, double y) 746 { 747 TRACE_BB("%p translate\n", _state); 748 BoundingBoxState* const state = 749 reinterpret_cast<BoundingBoxState*>(_state); 750 BAffineTransform transform = state->GetDrawState()->Transform(); 751 transform.PreTranslateBy(x, y); 752 state->GetDrawState()->SetTransform(transform); 753 } 754 755 756 static void 757 scale_by(void* _state, double x, double y) 758 { 759 TRACE_BB("%p scale\n", _state); 760 BoundingBoxState* const state = 761 reinterpret_cast<BoundingBoxState*>(_state); 762 BAffineTransform transform = state->GetDrawState()->Transform(); 763 transform.PreScaleBy(x, y); 764 state->GetDrawState()->SetTransform(transform); 765 } 766 767 768 static void 769 rotate_by(void* _state, double angleRadians) 770 { 771 TRACE_BB("%p rotate\n", _state); 772 BoundingBoxState* const state = 773 reinterpret_cast<BoundingBoxState*>(_state); 774 BAffineTransform transform = state->GetDrawState()->Transform(); 775 transform.PreRotateBy(angleRadians); 776 state->GetDrawState()->SetTransform(transform); 777 } 778 779 780 static void 781 determine_bounds_nested_layer(void* _state, Layer* layer) 782 { 783 TRACE_BB("%p nested layer\n", _state); 784 BoundingBoxState* const state = 785 reinterpret_cast<BoundingBoxState*>(_state); 786 787 BRect boundingBox; 788 PictureBoundingBoxPlayer::Play(layer, state->GetDrawState(), &boundingBox); 789 if (boundingBox.IsValid()) 790 state->IncludeRect(boundingBox); 791 } 792 793 794 static const BPrivate::picture_player_callbacks 795 kPictureBoundingBoxPlayerCallbacks = { 796 move_pen_by, 797 determine_bounds_stroke_line, 798 determine_bounds_draw_rect, 799 determine_bounds_draw_round_rect, 800 determine_bounds_draw_bezier, 801 determine_bounds_draw_arc, 802 determine_bounds_draw_ellipse, 803 determine_bounds_draw_polygon, 804 determine_bounds_draw_shape, 805 determine_bounds_draw_string, 806 determine_bounds_draw_pixels, 807 draw_picture, 808 set_clipping_rects, 809 clip_to_picture, 810 push_state, 811 pop_state, 812 enter_state_change, 813 exit_state_change, 814 enter_font_state, 815 exit_font_state, 816 set_origin, 817 set_pen_location, 818 set_drawing_mode, 819 set_line_mode, 820 set_pen_size, 821 set_fore_color, 822 set_back_color, 823 set_stipple_pattern, 824 set_scale, 825 set_font_family, 826 set_font_style, 827 set_font_spacing, 828 set_font_size, 829 set_font_rotate, 830 set_font_encoding, 831 set_font_flags, 832 set_font_shear, 833 set_font_face, 834 set_blending_mode, 835 set_transform, 836 translate_by, 837 scale_by, 838 rotate_by, 839 determine_bounds_nested_layer 840 }; 841 842 843 // #pragma mark - PictureBoundingBoxPlayer 844 845 846 /* static */ void 847 PictureBoundingBoxPlayer::Play(ServerPicture* picture, 848 const DrawState* drawState, BRect* outBoundingBox) 849 { 850 State state(drawState, outBoundingBox); 851 852 BMallocIO* mallocIO = dynamic_cast<BMallocIO*>(picture->fData.Get()); 853 if (mallocIO == NULL) 854 return; 855 856 BPrivate::PicturePlayer player(mallocIO->Buffer(), 857 mallocIO->BufferLength(), ServerPicture::PictureList::Private( 858 picture->fPictures.Get()).AsBList()); 859 player.Play(kPictureBoundingBoxPlayerCallbacks, 860 sizeof(kPictureBoundingBoxPlayerCallbacks), &state); 861 } 862