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 <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 FontStyle* fontStyle = gFontManager->GetStyleByIndex(family, 0); 620 ServerFont font; 621 font.SetStyle(fontStyle); 622 state->GetDrawState()->SetFont(font, B_FONT_FAMILY_AND_STYLE); 623 } 624 625 626 static void 627 set_font_style(void* _state, const char* _style, size_t length) 628 { 629 BoundingBoxState* const state = 630 reinterpret_cast<BoundingBoxState*>(_state); 631 632 BString style(_style, length); 633 ServerFont font(state->GetDrawState()->Font()); 634 FontStyle* fontStyle = gFontManager->GetStyle(font.Family(), style); 635 font.SetStyle(fontStyle); 636 state->GetDrawState()->SetFont(font, B_FONT_FAMILY_AND_STYLE); 637 } 638 639 640 static void 641 set_font_spacing(void* _state, uint8 spacing) 642 { 643 BoundingBoxState* const state = 644 reinterpret_cast<BoundingBoxState*>(_state); 645 646 ServerFont font; 647 font.SetSpacing(spacing); 648 state->GetDrawState()->SetFont(font, B_FONT_SPACING); 649 } 650 651 652 static void 653 set_font_size(void* _state, float size) 654 { 655 BoundingBoxState* const state = 656 reinterpret_cast<BoundingBoxState*>(_state); 657 658 ServerFont font; 659 font.SetSize(size); 660 state->GetDrawState()->SetFont(font, B_FONT_SIZE); 661 } 662 663 664 static void 665 set_font_rotate(void* _state, float rotation) 666 { 667 BoundingBoxState* const state = 668 reinterpret_cast<BoundingBoxState*>(_state); 669 670 ServerFont font; 671 font.SetRotation(rotation); 672 state->GetDrawState()->SetFont(font, B_FONT_ROTATION); 673 } 674 675 676 static void 677 set_font_encoding(void* _state, uint8 encoding) 678 { 679 BoundingBoxState* const state = 680 reinterpret_cast<BoundingBoxState*>(_state); 681 682 ServerFont font; 683 font.SetEncoding(encoding); 684 state->GetDrawState()->SetFont(font, B_FONT_ENCODING); 685 } 686 687 688 static void 689 set_font_flags(void* _state, uint32 flags) 690 { 691 BoundingBoxState* const state = 692 reinterpret_cast<BoundingBoxState*>(_state); 693 694 ServerFont font; 695 font.SetFlags(flags); 696 state->GetDrawState()->SetFont(font, B_FONT_FLAGS); 697 } 698 699 700 static void 701 set_font_shear(void* _state, float shear) 702 { 703 BoundingBoxState* const state = 704 reinterpret_cast<BoundingBoxState*>(_state); 705 706 ServerFont font; 707 font.SetShear(shear); 708 state->GetDrawState()->SetFont(font, B_FONT_SHEAR); 709 } 710 711 712 static void 713 set_font_face(void* _state, uint16 face) 714 { 715 BoundingBoxState* const state = 716 reinterpret_cast<BoundingBoxState*>(_state); 717 718 ServerFont font; 719 font.SetFace(face); 720 state->GetDrawState()->SetFont(font, B_FONT_FACE); 721 } 722 723 724 static void 725 set_blending_mode(void*, source_alpha, alpha_function) 726 { 727 } 728 729 730 static void 731 set_transform(void* _state, const BAffineTransform& transform) 732 { 733 TRACE_BB("%p transform\n", _state); 734 BoundingBoxState* const state = 735 reinterpret_cast<BoundingBoxState*>(_state); 736 state->GetDrawState()->SetTransform(transform); 737 } 738 739 740 static void 741 translate_by(void* _state, double x, double y) 742 { 743 TRACE_BB("%p translate\n", _state); 744 BoundingBoxState* const state = 745 reinterpret_cast<BoundingBoxState*>(_state); 746 BAffineTransform transform = state->GetDrawState()->Transform(); 747 transform.PreTranslateBy(x, y); 748 state->GetDrawState()->SetTransform(transform); 749 } 750 751 752 static void 753 scale_by(void* _state, double x, double y) 754 { 755 TRACE_BB("%p scale\n", _state); 756 BoundingBoxState* const state = 757 reinterpret_cast<BoundingBoxState*>(_state); 758 BAffineTransform transform = state->GetDrawState()->Transform(); 759 transform.PreScaleBy(x, y); 760 state->GetDrawState()->SetTransform(transform); 761 } 762 763 764 static void 765 rotate_by(void* _state, double angleRadians) 766 { 767 TRACE_BB("%p rotate\n", _state); 768 BoundingBoxState* const state = 769 reinterpret_cast<BoundingBoxState*>(_state); 770 BAffineTransform transform = state->GetDrawState()->Transform(); 771 transform.PreRotateBy(angleRadians); 772 state->GetDrawState()->SetTransform(transform); 773 } 774 775 776 static void 777 determine_bounds_nested_layer(void* _state, Layer* layer) 778 { 779 TRACE_BB("%p nested layer\n", _state); 780 BoundingBoxState* const state = 781 reinterpret_cast<BoundingBoxState*>(_state); 782 783 BRect boundingBox; 784 PictureBoundingBoxPlayer::Play(layer, state->GetDrawState(), &boundingBox); 785 if (boundingBox.IsValid()) 786 state->IncludeRect(boundingBox); 787 } 788 789 790 static const BPrivate::picture_player_callbacks 791 kPictureBoundingBoxPlayerCallbacks = { 792 move_pen_by, 793 determine_bounds_stroke_line, 794 determine_bounds_draw_rect, 795 determine_bounds_draw_round_rect, 796 determine_bounds_draw_bezier, 797 determine_bounds_draw_arc, 798 determine_bounds_draw_ellipse, 799 determine_bounds_draw_polygon, 800 determine_bounds_draw_shape, 801 determine_bounds_draw_string, 802 determine_bounds_draw_pixels, 803 draw_picture, 804 set_clipping_rects, 805 clip_to_picture, 806 push_state, 807 pop_state, 808 enter_state_change, 809 exit_state_change, 810 enter_font_state, 811 exit_font_state, 812 set_origin, 813 set_pen_location, 814 set_drawing_mode, 815 set_line_mode, 816 set_pen_size, 817 set_fore_color, 818 set_back_color, 819 set_stipple_pattern, 820 set_scale, 821 set_font_family, 822 set_font_style, 823 set_font_spacing, 824 set_font_size, 825 set_font_rotate, 826 set_font_encoding, 827 set_font_flags, 828 set_font_shear, 829 set_font_face, 830 set_blending_mode, 831 set_transform, 832 translate_by, 833 scale_by, 834 rotate_by, 835 determine_bounds_nested_layer 836 }; 837 838 839 // #pragma mark - PictureBoundingBoxPlayer 840 841 842 /* static */ void 843 PictureBoundingBoxPlayer::Play(ServerPicture* picture, 844 const DrawState* drawState, BRect* outBoundingBox) 845 { 846 State state(drawState, outBoundingBox); 847 848 BMallocIO* mallocIO = dynamic_cast<BMallocIO*>(picture->fData.Get()); 849 if (mallocIO == NULL) 850 return; 851 852 BPrivate::PicturePlayer player(mallocIO->Buffer(), 853 mallocIO->BufferLength(), ServerPicture::PictureList::Private( 854 picture->fPictures.Get()).AsBList()); 855 player.Play(kPictureBoundingBoxPlayerCallbacks, 856 sizeof(kPictureBoundingBoxPlayerCallbacks), &state); 857 } 858