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