1 /* 2 * Copyright 2001-2018, Haiku Inc. 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 * Stephan Aßmus <superstippi@gmx.de> 10 */ 11 12 /** PicturePlayer is used to play picture data. */ 13 14 #include <PicturePlayer.h> 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 20 #include <AffineTransform.h> 21 #include <DataIO.h> 22 #include <Gradient.h> 23 #include <PictureProtocol.h> 24 #include <Shape.h> 25 26 #include <AutoDeleter.h> 27 #include <StackOrHeapArray.h> 28 29 30 using BPrivate::PicturePlayer; 31 32 33 struct adapter_context { 34 void* user_data; 35 void** function_table; 36 }; 37 38 39 static void 40 nop() 41 { 42 } 43 44 45 static void 46 move_pen_by(void* _context, const BPoint& delta) 47 { 48 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 49 ((void (*)(void*, BPoint))context->function_table[1])(context->user_data, 50 delta); 51 } 52 53 54 static void 55 stroke_line(void* _context, const BPoint& start, const BPoint& end) 56 { 57 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 58 ((void (*)(void*, BPoint, BPoint))context->function_table[2])( 59 context->user_data, start, end); 60 } 61 62 63 static void 64 draw_rect(void* _context, const BRect& rect, bool fill) 65 { 66 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 67 ((void (*)(void*, BRect))context->function_table[fill ? 4 : 3])( 68 context->user_data, rect); 69 } 70 71 72 static void 73 draw_round_rect(void* _context, const BRect& rect, const BPoint& radii, 74 bool fill) 75 { 76 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 77 ((void (*)(void*, BRect, BPoint))context->function_table[fill ? 6 : 5])( 78 context->user_data, rect, radii); 79 } 80 81 82 static void 83 draw_bezier(void* _context, size_t numPoints, const BPoint _points[], bool fill) 84 { 85 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 86 if (numPoints != 4) 87 return; 88 89 BPoint points[4] = { _points[0], _points[1], _points[2], _points[3] }; 90 ((void (*)(void*, BPoint*))context->function_table[fill ? 8 : 7])( 91 context->user_data, points); 92 } 93 94 95 static void 96 draw_arc(void* _context, const BPoint& center, const BPoint& radii, 97 float startTheta, float arcTheta, bool fill) 98 { 99 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 100 ((void (*)(void*, BPoint, BPoint, float, float)) 101 context->function_table[fill ? 10 : 9])(context->user_data, center, 102 radii, startTheta, arcTheta); 103 } 104 105 106 static void 107 draw_ellipse(void* _context, const BRect& rect, bool fill) 108 { 109 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 110 BPoint radii((rect.Width() + 1) / 2.0f, (rect.Height() + 1) / 2.0f); 111 BPoint center = rect.LeftTop() + radii; 112 ((void (*)(void*, BPoint, BPoint)) 113 context->function_table[fill ? 12 : 11])(context->user_data, center, 114 radii); 115 } 116 117 118 static void 119 draw_polygon(void* _context, size_t numPoints, const BPoint _points[], 120 bool isClosed, bool fill) 121 { 122 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 123 124 BStackOrHeapArray<BPoint, 200> points(numPoints); 125 if (!points.IsValid()) 126 return; 127 128 memcpy((void*)points, _points, numPoints * sizeof(BPoint)); 129 130 ((void (*)(void*, int32, BPoint*, bool)) 131 context->function_table[fill ? 14 : 13])(context->user_data, numPoints, 132 points, isClosed); 133 } 134 135 136 static void 137 draw_shape(void* _context, const BShape& shape, bool fill) 138 { 139 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 140 ((void (*)(void*, BShape))context->function_table[fill ? 16 : 15])( 141 context->user_data, shape); 142 } 143 144 145 static void 146 draw_string(void* _context, const char* _string, size_t length, 147 float deltaSpace, float deltaNonSpace) 148 { 149 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 150 char* string = strndup(_string, length); 151 152 ((void (*)(void*, char*, float, float)) 153 context->function_table[17])(context->user_data, string, deltaSpace, 154 deltaNonSpace); 155 156 free(string); 157 } 158 159 160 static void 161 draw_pixels(void* _context, const BRect& src, const BRect& dest, uint32 width, 162 uint32 height, size_t bytesPerRow, color_space pixelFormat, uint32 options, 163 const void* _data, size_t length) 164 { 165 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 166 void* data = malloc(length); 167 if (data == NULL) 168 return; 169 170 memcpy(data, _data, length); 171 172 ((void (*)(void*, BRect, BRect, int32, int32, int32, int32, int32, void*)) 173 context->function_table[18])(context->user_data, src, dest, width, 174 height, bytesPerRow, pixelFormat, options, data); 175 176 free(data); 177 } 178 179 180 static void 181 draw_picture(void* _context, const BPoint& where, int32 token) 182 { 183 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 184 ((void (*)(void*, BPoint, int32))context->function_table[19])( 185 context->user_data, where, token); 186 } 187 188 189 static void 190 set_clipping_rects(void* _context, size_t numRects, const BRect _rects[]) 191 { 192 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 193 194 // This is rather ugly but works for such a trivial class. 195 BStackOrHeapArray<BRect, 100> rects(numRects); 196 if (!rects.IsValid()) 197 return; 198 199 memcpy((void*)rects, _rects, numRects * sizeof(BRect)); 200 201 ((void (*)(void*, BRect*, uint32))context->function_table[20])( 202 context->user_data, rects, numRects); 203 } 204 205 206 static void 207 clip_to_picture(void* _context, int32 token, const BPoint& origin, 208 bool clipToInverse) 209 { 210 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 211 ((void (*)(void*, int32, BPoint, bool))context->function_table[21])( 212 context->user_data, token, origin, clipToInverse); 213 } 214 215 216 static void 217 push_state(void* _context) 218 { 219 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 220 ((void (*)(void*))context->function_table[22])(context->user_data); 221 } 222 223 224 static void 225 pop_state(void* _context) 226 { 227 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 228 ((void (*)(void*))context->function_table[23])(context->user_data); 229 } 230 231 232 static void 233 enter_state_change(void* _context) 234 { 235 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 236 ((void (*)(void*))context->function_table[24])(context->user_data); 237 } 238 239 240 static void 241 exit_state_change(void* _context) 242 { 243 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 244 ((void (*)(void*))context->function_table[25])(context->user_data); 245 } 246 247 248 static void 249 enter_font_state(void* _context) 250 { 251 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 252 ((void (*)(void*))context->function_table[26])(context->user_data); 253 } 254 255 256 static void 257 exit_font_state(void* _context) 258 { 259 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 260 ((void (*)(void*))context->function_table[27])(context->user_data); 261 } 262 263 264 static void 265 set_origin(void* _context, const BPoint& origin) 266 { 267 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 268 ((void (*)(void*, BPoint))context->function_table[28])(context->user_data, 269 origin); 270 } 271 272 273 static void 274 set_pen_location(void* _context, const BPoint& penLocation) 275 { 276 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 277 ((void (*)(void*, BPoint))context->function_table[29])(context->user_data, 278 penLocation); 279 } 280 281 282 static void 283 set_drawing_mode(void* _context, drawing_mode mode) 284 { 285 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 286 ((void (*)(void*, drawing_mode))context->function_table[30])( 287 context->user_data, mode); 288 } 289 290 291 static void 292 set_line_mode(void* _context, cap_mode capMode, join_mode joinMode, 293 float miterLimit) 294 { 295 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 296 ((void (*)(void*, cap_mode, join_mode, float))context->function_table[31])( 297 context->user_data, capMode, joinMode, miterLimit); 298 } 299 300 301 static void 302 set_pen_size(void* _context, float size) 303 { 304 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 305 ((void (*)(void*, float))context->function_table[32])(context->user_data, 306 size); 307 } 308 309 310 static void 311 set_fore_color(void* _context, const rgb_color& color) 312 { 313 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 314 ((void (*)(void*, rgb_color))context->function_table[33])( 315 context->user_data, color); 316 } 317 318 319 static void 320 set_back_color(void* _context, const rgb_color& color) 321 { 322 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 323 ((void (*)(void*, rgb_color))context->function_table[34])( 324 context->user_data, color); 325 } 326 327 328 static void 329 set_stipple_pattern(void* _context, const pattern& stipplePattern) 330 { 331 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 332 ((void (*)(void*, pattern))context->function_table[35])(context->user_data, 333 stipplePattern); 334 } 335 336 337 static void 338 set_scale(void* _context, float scale) 339 { 340 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 341 ((void (*)(void*, float))context->function_table[36])(context->user_data, 342 scale); 343 } 344 345 346 static void 347 set_font_family(void* _context, const char* _family, size_t length) 348 { 349 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 350 char* family = strndup(_family, length); 351 352 ((void (*)(void*, char*))context->function_table[37])(context->user_data, 353 family); 354 355 free(family); 356 } 357 358 359 static void 360 set_font_style(void* _context, const char* _style, size_t length) 361 { 362 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 363 char* style = strndup(_style, length); 364 365 ((void (*)(void*, char*))context->function_table[38])(context->user_data, 366 style); 367 368 free(style); 369 } 370 371 372 static void 373 set_font_spacing(void* _context, uint8 spacing) 374 { 375 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 376 ((void (*)(void*, int32))context->function_table[39])(context->user_data, 377 spacing); 378 } 379 380 381 static void 382 set_font_size(void* _context, float size) 383 { 384 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 385 ((void (*)(void*, float))context->function_table[40])(context->user_data, 386 size); 387 } 388 389 390 static void 391 set_font_rotation(void* _context, float rotation) 392 { 393 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 394 ((void (*)(void*, float))context->function_table[41])(context->user_data, 395 rotation); 396 } 397 398 399 static void 400 set_font_encoding(void* _context, uint8 encoding) 401 { 402 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 403 ((void (*)(void*, int32))context->function_table[42])(context->user_data, 404 encoding); 405 } 406 407 408 static void 409 set_font_flags(void* _context, uint32 flags) 410 { 411 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 412 ((void (*)(void*, int32))context->function_table[43])(context->user_data, 413 flags); 414 } 415 416 417 static void 418 set_font_shear(void* _context, float shear) 419 { 420 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 421 ((void (*)(void*, float))context->function_table[44])(context->user_data, 422 shear); 423 } 424 425 426 static void 427 set_font_face(void* _context, uint16 face) 428 { 429 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 430 ((void (*)(void*, int32))context->function_table[46])(context->user_data, 431 face); 432 } 433 434 435 static void 436 set_blending_mode(void* _context, source_alpha alphaSrcMode, 437 alpha_function alphaFncMode) 438 { 439 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 440 ((void (*)(void*, source_alpha, alpha_function)) 441 context->function_table[47])(context->user_data, alphaSrcMode, 442 alphaFncMode); 443 } 444 445 446 static void 447 set_transform(void* _context, const BAffineTransform& transform) 448 { 449 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 450 ((void (*)(void*, const BAffineTransform&)) 451 context->function_table[48])(context->user_data, transform); 452 } 453 454 455 static void 456 translate_by(void* _context, double x, double y) 457 { 458 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 459 ((void (*)(void*, double, double)) 460 context->function_table[49])(context->user_data, x, y); 461 } 462 463 464 static void 465 scale_by(void* _context, double x, double y) 466 { 467 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 468 ((void (*)(void*, double, double)) 469 context->function_table[50])(context->user_data, x, y); 470 } 471 472 473 static void 474 rotate_by(void* _context, double angleRadians) 475 { 476 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 477 ((void (*)(void*, double)) 478 context->function_table[51])(context->user_data, angleRadians); 479 } 480 481 482 static void 483 blend_layer(void* _context, Layer* layer) 484 { 485 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 486 ((void (*)(void*, Layer*)) 487 context->function_table[52])(context->user_data, layer); 488 } 489 490 491 static void 492 clip_to_rect(void* _context, const BRect& rect, bool inverse) 493 { 494 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 495 ((void (*)(void*, const BRect&, bool)) 496 context->function_table[53])(context->user_data, rect, inverse); 497 } 498 499 500 static void 501 clip_to_shape(void* _context, int32 opCount, const uint32 opList[], 502 int32 ptCount, const BPoint ptList[], bool inverse) 503 { 504 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 505 ((void (*)(void*, int32, const uint32*, int32, const BPoint*, bool)) 506 context->function_table[54])(context->user_data, opCount, opList, 507 ptCount, ptList, inverse); 508 } 509 510 511 static void 512 draw_string_locations(void* _context, const char* _string, size_t length, 513 const BPoint* locations, size_t locationCount) 514 { 515 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 516 char* string = strndup(_string, length); 517 518 ((void (*)(void*, char*, const BPoint*, size_t)) 519 context->function_table[55])(context->user_data, string, locations, 520 locationCount); 521 522 free(string); 523 } 524 525 526 static void 527 draw_rect_gradient(void* _context, const BRect& rect, BGradient& gradient, bool fill) 528 { 529 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 530 ((void (*)(void*, BRect, BGradient&))context->function_table[fill ? 56 : 57])( 531 context->user_data, rect, gradient); 532 } 533 534 535 static void 536 draw_round_rect_gradient(void* _context, const BRect& rect, const BPoint& radii, BGradient& gradient, 537 bool fill) 538 { 539 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 540 ((void (*)(void*, BRect, BPoint, BGradient&))context->function_table[fill ? 58 : 59])( 541 context->user_data, rect, radii, gradient); 542 } 543 544 545 static void 546 draw_bezier_gradient(void* _context, size_t numPoints, const BPoint _points[], BGradient& gradient, bool fill) 547 { 548 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 549 if (numPoints != 4) 550 return; 551 552 BPoint points[4] = { _points[0], _points[1], _points[2], _points[3] }; 553 ((void (*)(void*, BPoint*, BGradient&))context->function_table[fill ? 60 : 61])( 554 context->user_data, points, gradient); 555 } 556 557 558 static void 559 draw_arc_gradient(void* _context, const BPoint& center, const BPoint& radii, 560 float startTheta, float arcTheta, BGradient& gradient, bool fill) 561 { 562 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 563 ((void (*)(void*, BPoint, BPoint, float, float, BGradient&)) 564 context->function_table[fill ? 62 : 63])(context->user_data, center, 565 radii, startTheta, arcTheta, gradient); 566 } 567 568 569 static void 570 draw_ellipse_gradient(void* _context, const BRect& rect, BGradient& gradient, bool fill) 571 { 572 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 573 BPoint radii((rect.Width() + 1) / 2.0f, (rect.Height() + 1) / 2.0f); 574 BPoint center = rect.LeftTop() + radii; 575 ((void (*)(void*, BPoint, BPoint, BGradient&)) 576 context->function_table[fill ? 64 : 65])(context->user_data, center, 577 radii, gradient); 578 } 579 580 581 static void 582 draw_polygon_gradient(void* _context, size_t numPoints, const BPoint _points[], 583 bool isClosed, BGradient& gradient, bool fill) 584 { 585 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 586 587 BStackOrHeapArray<BPoint, 200> points(numPoints); 588 if (!points.IsValid()) 589 return; 590 591 memcpy((void*)points, _points, numPoints * sizeof(BPoint)); 592 593 ((void (*)(void*, int32, BPoint*, bool, BGradient&)) 594 context->function_table[fill ? 66 : 67])(context->user_data, numPoints, 595 points, isClosed, gradient); 596 } 597 598 599 static void 600 draw_shape_gradient(void* _context, const BShape& shape, BGradient& gradient, bool fill) 601 { 602 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 603 ((void (*)(void*, BShape, BGradient&))context->function_table[fill ? 68 : 69])( 604 context->user_data, shape, gradient); 605 } 606 607 608 static void 609 set_fill_rule(void* _context, int32 fillRule) 610 { 611 adapter_context* context = reinterpret_cast<adapter_context*>(_context); 612 ((void (*)(void*, int32))context->function_table[70])( 613 context->user_data, fillRule); 614 } 615 616 617 618 #if DEBUG > 1 619 static const char * 620 PictureOpToString(int op) 621 { 622 #define RETURN_STRING(x) case x: return #x 623 624 switch(op) { 625 RETURN_STRING(B_PIC_MOVE_PEN_BY); 626 RETURN_STRING(B_PIC_STROKE_LINE); 627 RETURN_STRING(B_PIC_STROKE_RECT); 628 RETURN_STRING(B_PIC_FILL_RECT); 629 RETURN_STRING(B_PIC_STROKE_ROUND_RECT); 630 RETURN_STRING(B_PIC_FILL_ROUND_RECT); 631 RETURN_STRING(B_PIC_STROKE_BEZIER); 632 RETURN_STRING(B_PIC_FILL_BEZIER); 633 RETURN_STRING(B_PIC_STROKE_POLYGON); 634 RETURN_STRING(B_PIC_FILL_POLYGON); 635 RETURN_STRING(B_PIC_STROKE_SHAPE); 636 RETURN_STRING(B_PIC_FILL_SHAPE); 637 RETURN_STRING(B_PIC_DRAW_STRING); 638 RETURN_STRING(B_PIC_DRAW_STRING_LOCATIONS); 639 RETURN_STRING(B_PIC_DRAW_PIXELS); 640 RETURN_STRING(B_PIC_DRAW_PICTURE); 641 RETURN_STRING(B_PIC_STROKE_ARC); 642 RETURN_STRING(B_PIC_FILL_ARC); 643 RETURN_STRING(B_PIC_STROKE_ELLIPSE); 644 RETURN_STRING(B_PIC_FILL_ELLIPSE); 645 646 RETURN_STRING(B_PIC_ENTER_STATE_CHANGE); 647 RETURN_STRING(B_PIC_SET_CLIPPING_RECTS); 648 RETURN_STRING(B_PIC_CLIP_TO_PICTURE); 649 RETURN_STRING(B_PIC_PUSH_STATE); 650 RETURN_STRING(B_PIC_POP_STATE); 651 RETURN_STRING(B_PIC_CLEAR_CLIPPING_RECTS); 652 653 RETURN_STRING(B_PIC_SET_ORIGIN); 654 RETURN_STRING(B_PIC_SET_PEN_LOCATION); 655 RETURN_STRING(B_PIC_SET_DRAWING_MODE); 656 RETURN_STRING(B_PIC_SET_LINE_MODE); 657 RETURN_STRING(B_PIC_SET_PEN_SIZE); 658 RETURN_STRING(B_PIC_SET_SCALE); 659 RETURN_STRING(B_PIC_SET_TRANSFORM); 660 RETURN_STRING(B_PIC_SET_FORE_COLOR); 661 RETURN_STRING(B_PIC_SET_BACK_COLOR); 662 RETURN_STRING(B_PIC_SET_STIPLE_PATTERN); 663 RETURN_STRING(B_PIC_ENTER_FONT_STATE); 664 RETURN_STRING(B_PIC_SET_BLENDING_MODE); 665 RETURN_STRING(B_PIC_SET_FONT_FAMILY); 666 RETURN_STRING(B_PIC_SET_FONT_STYLE); 667 RETURN_STRING(B_PIC_SET_FONT_SPACING); 668 RETURN_STRING(B_PIC_SET_FONT_ENCODING); 669 RETURN_STRING(B_PIC_SET_FONT_FLAGS); 670 RETURN_STRING(B_PIC_SET_FONT_SIZE); 671 RETURN_STRING(B_PIC_SET_FONT_ROTATE); 672 RETURN_STRING(B_PIC_SET_FONT_SHEAR); 673 RETURN_STRING(B_PIC_SET_FONT_BPP); 674 RETURN_STRING(B_PIC_SET_FONT_FACE); 675 676 RETURN_STRING(B_PIC_AFFINE_TRANSLATE); 677 RETURN_STRING(B_PIC_AFFINE_SCALE); 678 RETURN_STRING(B_PIC_AFFINE_ROTATE); 679 680 RETURN_STRING(B_PIC_BLEND_LAYER); 681 682 default: return "Unknown op"; 683 } 684 #undef RETURN_STRING 685 } 686 #endif 687 688 689 PicturePlayer::PicturePlayer(const void *data, size_t size, BList *pictures) 690 : fData(data), 691 fSize(size), 692 fPictures(pictures) 693 { 694 } 695 696 697 PicturePlayer::~PicturePlayer() 698 { 699 } 700 701 702 status_t 703 PicturePlayer::Play(void** callBackTable, int32 tableEntries, void* userData) 704 { 705 const BPrivate::picture_player_callbacks kAdapterCallbacks = { 706 move_pen_by, 707 stroke_line, 708 draw_rect, 709 draw_round_rect, 710 draw_bezier, 711 draw_arc, 712 draw_ellipse, 713 draw_polygon, 714 draw_shape, 715 draw_string, 716 draw_pixels, 717 draw_picture, 718 set_clipping_rects, 719 clip_to_picture, 720 push_state, 721 pop_state, 722 enter_state_change, 723 exit_state_change, 724 enter_font_state, 725 exit_font_state, 726 set_origin, 727 set_pen_location, 728 set_drawing_mode, 729 set_line_mode, 730 set_pen_size, 731 set_fore_color, 732 set_back_color, 733 set_stipple_pattern, 734 set_scale, 735 set_font_family, 736 set_font_style, 737 set_font_spacing, 738 set_font_size, 739 set_font_rotation, 740 set_font_encoding, 741 set_font_flags, 742 set_font_shear, 743 set_font_face, 744 set_blending_mode, 745 set_transform, 746 translate_by, 747 scale_by, 748 rotate_by, 749 blend_layer, 750 clip_to_rect, 751 clip_to_shape, 752 draw_string_locations, 753 draw_rect_gradient, 754 draw_round_rect_gradient, 755 draw_bezier_gradient, 756 draw_arc_gradient, 757 draw_ellipse_gradient, 758 draw_polygon_gradient, 759 draw_shape_gradient, 760 set_fill_rule 761 }; 762 763 // We don't check if the functions in the table are NULL, but we 764 // check the tableEntries to see if the table is big enough. 765 // If an application supplies the wrong size or an invalid pointer, 766 // it's its own fault. 767 768 // If the caller supplied a function table smaller than needed, 769 // we use our dummy table, and copy the supported ops from the supplied one. 770 void *dummyTable[kOpsTableSize]; 771 772 adapter_context adapterContext; 773 adapterContext.user_data = userData; 774 adapterContext.function_table = callBackTable; 775 776 if ((size_t)tableEntries < kOpsTableSize) { 777 memcpy(dummyTable, callBackTable, tableEntries * sizeof(void*)); 778 for (size_t i = (size_t)tableEntries; i < kOpsTableSize; i++) 779 dummyTable[i] = (void*)nop; 780 781 adapterContext.function_table = dummyTable; 782 } 783 784 return _Play(kAdapterCallbacks, &adapterContext, fData, fSize, 0); 785 } 786 787 788 status_t 789 PicturePlayer::Play(const picture_player_callbacks& callbacks, 790 size_t callbacksSize, void* userData) 791 { 792 return _Play(callbacks, userData, fData, fSize, 0); 793 } 794 795 796 class DataReader { 797 public: 798 DataReader(const void* buffer, size_t length) 799 : 800 fBuffer((const uint8*)buffer), 801 fRemaining(length) 802 { 803 } 804 805 size_t 806 Remaining() const 807 { 808 return fRemaining; 809 } 810 811 template<typename T> 812 bool 813 Get(const T*& typed, size_t count = 1) 814 { 815 if (fRemaining < sizeof(T) * count) 816 return false; 817 818 typed = reinterpret_cast<const T *>(fBuffer); 819 fRemaining -= sizeof(T) * count; 820 fBuffer += sizeof(T) * count; 821 return true; 822 } 823 824 bool GetGradient(BGradient*& gradient) 825 { 826 BMemoryIO stream(fBuffer, fRemaining); 827 printf("fRemaining: %ld\n", fRemaining); 828 if (BGradient::Unflatten(gradient, &stream) != B_OK) { 829 printf("BGradient::Unflatten(_gradient, &stream) != B_OK\n"); 830 return false; 831 } 832 833 fRemaining -= stream.Position(); 834 fBuffer += stream.Position(); 835 return true; 836 } 837 838 template<typename T> 839 bool 840 GetRemaining(const T*& buffer, size_t& size) 841 { 842 if (fRemaining == 0) 843 return false; 844 845 buffer = reinterpret_cast<const T*>(fBuffer); 846 size = fRemaining; 847 fRemaining = 0; 848 return true; 849 } 850 851 private: 852 const uint8* fBuffer; 853 size_t fRemaining; 854 }; 855 856 857 struct picture_data_entry_header { 858 uint16 op; 859 uint32 size; 860 } _PACKED; 861 862 863 status_t 864 PicturePlayer::_Play(const picture_player_callbacks& callbacks, void* userData, 865 const void* buffer, size_t length, uint16 parentOp) 866 { 867 #if DEBUG 868 printf("Start rendering %sBPicture...\n", parentOp != 0 ? "sub " : ""); 869 bigtime_t startTime = system_time(); 870 int32 numOps = 0; 871 #endif 872 873 DataReader pictureReader(buffer, length); 874 875 while (pictureReader.Remaining() > 0) { 876 const picture_data_entry_header* header; 877 const uint8* opData = NULL; 878 if (!pictureReader.Get(header) 879 || !pictureReader.Get(opData, header->size)) { 880 return B_BAD_DATA; 881 } 882 883 DataReader reader(opData, header->size); 884 885 // Disallow ops that don't fit the parent. 886 switch (parentOp) { 887 case 0: 888 // No parent op, no restrictions. 889 break; 890 891 case B_PIC_ENTER_STATE_CHANGE: 892 if (header->op <= B_PIC_ENTER_STATE_CHANGE 893 || header->op > B_PIC_SET_TRANSFORM) { 894 return B_BAD_DATA; 895 } 896 break; 897 898 case B_PIC_ENTER_FONT_STATE: 899 if (header->op < B_PIC_SET_FONT_FAMILY 900 || header->op > B_PIC_SET_FONT_FACE) { 901 return B_BAD_DATA; 902 } 903 break; 904 905 default: 906 return B_BAD_DATA; 907 } 908 909 #if DEBUG > 1 910 bigtime_t startOpTime = system_time(); 911 printf("Op %s ", PictureOpToString(header->op)); 912 #endif 913 switch (header->op) { 914 case B_PIC_MOVE_PEN_BY: 915 { 916 const BPoint* where; 917 if (callbacks.move_pen_by == NULL || !reader.Get(where)) 918 break; 919 920 callbacks.move_pen_by(userData, *where); 921 break; 922 } 923 924 case B_PIC_STROKE_LINE: 925 { 926 const BPoint* start; 927 const BPoint* end; 928 if (callbacks.stroke_line == NULL || !reader.Get(start) 929 || !reader.Get(end)) { 930 break; 931 } 932 933 callbacks.stroke_line(userData, *start, *end); 934 break; 935 } 936 937 case B_PIC_STROKE_RECT: 938 case B_PIC_FILL_RECT: 939 { 940 const BRect* rect; 941 if (callbacks.draw_rect == NULL || !reader.Get(rect)) 942 break; 943 944 callbacks.draw_rect(userData, *rect, 945 header->op == B_PIC_FILL_RECT); 946 break; 947 } 948 949 case B_PIC_STROKE_ROUND_RECT: 950 case B_PIC_FILL_ROUND_RECT: 951 { 952 const BRect* rect; 953 const BPoint* radii; 954 if (callbacks.draw_round_rect == NULL || !reader.Get(rect) 955 || !reader.Get(radii)) { 956 break; 957 } 958 959 callbacks.draw_round_rect(userData, *rect, *radii, 960 header->op == B_PIC_FILL_ROUND_RECT); 961 break; 962 } 963 964 case B_PIC_STROKE_BEZIER: 965 case B_PIC_FILL_BEZIER: 966 { 967 const size_t kNumControlPoints = 4; 968 const BPoint* controlPoints; 969 if (callbacks.draw_bezier == NULL 970 || !reader.Get(controlPoints, kNumControlPoints)) { 971 break; 972 } 973 974 callbacks.draw_bezier(userData, kNumControlPoints, 975 controlPoints, header->op == B_PIC_FILL_BEZIER); 976 break; 977 } 978 979 case B_PIC_STROKE_ARC: 980 case B_PIC_FILL_ARC: 981 { 982 const BPoint* center; 983 const BPoint* radii; 984 const float* startTheta; 985 const float* arcTheta; 986 if (callbacks.draw_arc == NULL || !reader.Get(center) 987 || !reader.Get(radii) || !reader.Get(startTheta) 988 || !reader.Get(arcTheta)) { 989 break; 990 } 991 992 callbacks.draw_arc(userData, *center, *radii, *startTheta, 993 *arcTheta, header->op == B_PIC_FILL_ARC); 994 break; 995 } 996 997 case B_PIC_STROKE_ELLIPSE: 998 case B_PIC_FILL_ELLIPSE: 999 { 1000 const BRect* rect; 1001 if (callbacks.draw_ellipse == NULL || !reader.Get(rect)) 1002 break; 1003 1004 callbacks.draw_ellipse(userData, *rect, 1005 header->op == B_PIC_FILL_ELLIPSE); 1006 break; 1007 } 1008 1009 case B_PIC_STROKE_POLYGON: 1010 case B_PIC_FILL_POLYGON: 1011 { 1012 const uint32* numPoints; 1013 const BPoint* points; 1014 if (callbacks.draw_polygon == NULL || !reader.Get(numPoints) 1015 || !reader.Get(points, *numPoints)) { 1016 break; 1017 } 1018 1019 bool isClosed = true; 1020 const bool* closedPointer; 1021 if (header->op != B_PIC_FILL_POLYGON) { 1022 if (!reader.Get(closedPointer)) 1023 break; 1024 1025 isClosed = *closedPointer; 1026 } 1027 1028 callbacks.draw_polygon(userData, *numPoints, points, isClosed, 1029 header->op == B_PIC_FILL_POLYGON); 1030 break; 1031 } 1032 1033 case B_PIC_STROKE_SHAPE: 1034 case B_PIC_FILL_SHAPE: 1035 { 1036 const uint32* opCount; 1037 const uint32* pointCount; 1038 const uint32* opList; 1039 const BPoint* pointList; 1040 if (callbacks.draw_shape == NULL || !reader.Get(opCount) 1041 || !reader.Get(pointCount) || !reader.Get(opList, *opCount) 1042 || !reader.Get(pointList, *pointCount)) { 1043 break; 1044 } 1045 1046 // TODO: remove BShape data copying 1047 BShape shape; 1048 shape.SetData(*opCount, *pointCount, opList, pointList); 1049 1050 callbacks.draw_shape(userData, shape, 1051 header->op == B_PIC_FILL_SHAPE); 1052 break; 1053 } 1054 1055 case B_PIC_STROKE_RECT_GRADIENT: 1056 case B_PIC_FILL_RECT_GRADIENT: 1057 { 1058 const BRect* rect; 1059 BGradient* gradient; 1060 if (callbacks.draw_rect_gradient == NULL || !reader.Get(rect) || !reader.GetGradient(gradient)) 1061 break; 1062 ObjectDeleter<BGradient> gradientDeleter(gradient); 1063 1064 callbacks.draw_rect_gradient(userData, *rect, *gradient, 1065 header->op == B_PIC_FILL_RECT_GRADIENT); 1066 break; 1067 } 1068 1069 case B_PIC_STROKE_ROUND_RECT_GRADIENT: 1070 case B_PIC_FILL_ROUND_RECT_GRADIENT: 1071 { 1072 const BRect* rect; 1073 const BPoint* radii; 1074 BGradient* gradient; 1075 if (callbacks.draw_round_rect_gradient == NULL || !reader.Get(rect) 1076 || !reader.Get(radii) || !reader.GetGradient(gradient)) { 1077 break; 1078 } 1079 ObjectDeleter<BGradient> gradientDeleter(gradient); 1080 1081 callbacks.draw_round_rect_gradient(userData, *rect, *radii, *gradient, 1082 header->op == B_PIC_FILL_ROUND_RECT_GRADIENT); 1083 break; 1084 } 1085 1086 case B_PIC_STROKE_BEZIER_GRADIENT: 1087 case B_PIC_FILL_BEZIER_GRADIENT: 1088 { 1089 const size_t kNumControlPoints = 4; 1090 const BPoint* controlPoints; 1091 BGradient* gradient; 1092 if (callbacks.draw_bezier_gradient == NULL 1093 || !reader.Get(controlPoints, kNumControlPoints) || !reader.GetGradient(gradient)) { 1094 break; 1095 } 1096 ObjectDeleter<BGradient> gradientDeleter(gradient); 1097 1098 callbacks.draw_bezier_gradient(userData, kNumControlPoints, 1099 controlPoints, *gradient, header->op == B_PIC_FILL_BEZIER_GRADIENT); 1100 break; 1101 } 1102 1103 case B_PIC_STROKE_POLYGON_GRADIENT: 1104 case B_PIC_FILL_POLYGON_GRADIENT: 1105 { 1106 const uint32* numPoints; 1107 const BPoint* points; 1108 BGradient* gradient; 1109 if (callbacks.draw_polygon_gradient == NULL || !reader.Get(numPoints) 1110 || !reader.Get(points, *numPoints)) { 1111 break; 1112 } 1113 1114 bool isClosed = true; 1115 const bool* closedPointer; 1116 if (header->op != B_PIC_FILL_POLYGON_GRADIENT) { 1117 if (!reader.Get(closedPointer)) 1118 break; 1119 1120 isClosed = *closedPointer; 1121 } 1122 1123 if (!reader.GetGradient(gradient)) 1124 break; 1125 ObjectDeleter<BGradient> gradientDeleter(gradient); 1126 1127 callbacks.draw_polygon_gradient(userData, *numPoints, points, isClosed, *gradient, 1128 header->op == B_PIC_FILL_POLYGON_GRADIENT); 1129 break; 1130 } 1131 1132 case B_PIC_STROKE_SHAPE_GRADIENT: 1133 case B_PIC_FILL_SHAPE_GRADIENT: 1134 { 1135 const uint32* opCount; 1136 const uint32* pointCount; 1137 const uint32* opList; 1138 const BPoint* pointList; 1139 BGradient* gradient; 1140 if (callbacks.draw_shape_gradient == NULL || !reader.Get(opCount) 1141 || !reader.Get(pointCount) || !reader.Get(opList, *opCount) 1142 || !reader.Get(pointList, *pointCount) || !reader.GetGradient(gradient)) { 1143 break; 1144 } 1145 ObjectDeleter<BGradient> gradientDeleter(gradient); 1146 1147 // TODO: remove BShape data copying 1148 BShape shape; 1149 shape.SetData(*opCount, *pointCount, opList, pointList); 1150 1151 callbacks.draw_shape_gradient(userData, shape, *gradient, 1152 header->op == B_PIC_FILL_SHAPE_GRADIENT); 1153 break; 1154 } 1155 1156 case B_PIC_STROKE_ARC_GRADIENT: 1157 case B_PIC_FILL_ARC_GRADIENT: 1158 { 1159 const BPoint* center; 1160 const BPoint* radii; 1161 const float* startTheta; 1162 const float* arcTheta; 1163 BGradient* gradient; 1164 if (callbacks.draw_arc_gradient == NULL || !reader.Get(center) 1165 || !reader.Get(radii) || !reader.Get(startTheta) 1166 || !reader.Get(arcTheta) || !reader.GetGradient(gradient)) { 1167 break; 1168 } 1169 ObjectDeleter<BGradient> gradientDeleter(gradient); 1170 1171 callbacks.draw_arc_gradient(userData, *center, *radii, *startTheta, 1172 *arcTheta, *gradient, header->op == B_PIC_FILL_ARC_GRADIENT); 1173 break; 1174 } 1175 1176 case B_PIC_STROKE_ELLIPSE_GRADIENT: 1177 case B_PIC_FILL_ELLIPSE_GRADIENT: 1178 { 1179 const BRect* rect; 1180 BGradient* gradient; 1181 if (callbacks.draw_ellipse_gradient == NULL || !reader.Get(rect) || !reader.GetGradient(gradient)) 1182 break; 1183 ObjectDeleter<BGradient> gradientDeleter(gradient); 1184 1185 callbacks.draw_ellipse_gradient(userData, *rect, *gradient, 1186 header->op == B_PIC_FILL_ELLIPSE_GRADIENT); 1187 break; 1188 } 1189 1190 case B_PIC_DRAW_STRING: 1191 { 1192 const float* escapementSpace; 1193 const float* escapementNonSpace; 1194 const char* string; 1195 size_t length; 1196 if (callbacks.draw_string == NULL 1197 || !reader.Get(escapementSpace) 1198 || !reader.Get(escapementNonSpace) 1199 || !reader.GetRemaining(string, length)) { 1200 break; 1201 } 1202 1203 callbacks.draw_string(userData, string, length, 1204 *escapementSpace, *escapementNonSpace); 1205 break; 1206 } 1207 1208 case B_PIC_DRAW_STRING_LOCATIONS: 1209 { 1210 const uint32* pointCount; 1211 const BPoint* pointList; 1212 const char* string; 1213 size_t length; 1214 if (callbacks.draw_string_locations == NULL 1215 || !reader.Get(pointCount) 1216 || !reader.Get(pointList, *pointCount) 1217 || !reader.GetRemaining(string, length)) { 1218 break; 1219 } 1220 1221 callbacks.draw_string_locations(userData, string, length, 1222 pointList, *pointCount); 1223 break; 1224 } 1225 1226 case B_PIC_DRAW_PIXELS: 1227 { 1228 const BRect* sourceRect; 1229 const BRect* destinationRect; 1230 const uint32* width; 1231 const uint32* height; 1232 const uint32* bytesPerRow; 1233 const uint32* colorSpace; 1234 const uint32* flags; 1235 const void* data; 1236 size_t length; 1237 if (callbacks.draw_pixels == NULL || !reader.Get(sourceRect) 1238 || !reader.Get(destinationRect) || !reader.Get(width) 1239 || !reader.Get(height) || !reader.Get(bytesPerRow) 1240 || !reader.Get(colorSpace) || !reader.Get(flags) 1241 || !reader.GetRemaining(data, length)) { 1242 break; 1243 } 1244 1245 callbacks.draw_pixels(userData, *sourceRect, *destinationRect, 1246 *width, *height, *bytesPerRow, (color_space)*colorSpace, 1247 *flags, data, length); 1248 break; 1249 } 1250 1251 case B_PIC_DRAW_PICTURE: 1252 { 1253 const BPoint* where; 1254 const int32* token; 1255 if (callbacks.draw_picture == NULL || !reader.Get(where) 1256 || !reader.Get(token)) { 1257 break; 1258 } 1259 1260 callbacks.draw_picture(userData, *where, *token); 1261 break; 1262 } 1263 1264 case B_PIC_SET_CLIPPING_RECTS: 1265 { 1266 const uint32* numRects; 1267 const BRect* rects; 1268 if (callbacks.set_clipping_rects == NULL 1269 || !reader.Get(numRects) || !reader.Get(rects, *numRects)) { 1270 break; 1271 } 1272 1273 callbacks.set_clipping_rects(userData, *numRects, rects); 1274 break; 1275 } 1276 1277 case B_PIC_CLEAR_CLIPPING_RECTS: 1278 { 1279 if (callbacks.set_clipping_rects == NULL) 1280 break; 1281 1282 callbacks.set_clipping_rects(userData, 0, NULL); 1283 break; 1284 } 1285 1286 case B_PIC_CLIP_TO_PICTURE: 1287 { 1288 const int32* token; 1289 const BPoint* where; 1290 const bool* inverse; 1291 if (callbacks.clip_to_picture == NULL || !reader.Get(token) 1292 || !reader.Get(where) || !reader.Get(inverse)) 1293 break; 1294 1295 callbacks.clip_to_picture(userData, *token, *where, *inverse); 1296 break; 1297 } 1298 1299 case B_PIC_PUSH_STATE: 1300 { 1301 if (callbacks.push_state == NULL) 1302 break; 1303 1304 callbacks.push_state(userData); 1305 break; 1306 } 1307 1308 case B_PIC_POP_STATE: 1309 { 1310 if (callbacks.pop_state == NULL) 1311 break; 1312 1313 callbacks.pop_state(userData); 1314 break; 1315 } 1316 1317 case B_PIC_ENTER_STATE_CHANGE: 1318 case B_PIC_ENTER_FONT_STATE: 1319 { 1320 const void* data; 1321 size_t length; 1322 if (!reader.GetRemaining(data, length)) 1323 break; 1324 1325 if (header->op == B_PIC_ENTER_STATE_CHANGE) { 1326 if (callbacks.enter_state_change != NULL) 1327 callbacks.enter_state_change(userData); 1328 } else if (callbacks.enter_font_state != NULL) 1329 callbacks.enter_font_state(userData); 1330 1331 status_t result = _Play(callbacks, userData, data, length, 1332 header->op); 1333 if (result != B_OK) 1334 return result; 1335 1336 if (header->op == B_PIC_ENTER_STATE_CHANGE) { 1337 if (callbacks.exit_state_change != NULL) 1338 callbacks.exit_state_change(userData); 1339 } else if (callbacks.exit_font_state != NULL) 1340 callbacks.exit_font_state(userData); 1341 1342 break; 1343 } 1344 1345 case B_PIC_SET_ORIGIN: 1346 { 1347 const BPoint* origin; 1348 if (callbacks.set_origin == NULL || !reader.Get(origin)) 1349 break; 1350 1351 callbacks.set_origin(userData, *origin); 1352 break; 1353 } 1354 1355 case B_PIC_SET_PEN_LOCATION: 1356 { 1357 const BPoint* location; 1358 if (callbacks.set_pen_location == NULL || !reader.Get(location)) 1359 break; 1360 1361 callbacks.set_pen_location(userData, *location); 1362 break; 1363 } 1364 1365 case B_PIC_SET_DRAWING_MODE: 1366 { 1367 const uint16* mode; 1368 if (callbacks.set_drawing_mode == NULL || !reader.Get(mode)) 1369 break; 1370 1371 callbacks.set_drawing_mode(userData, (drawing_mode)*mode); 1372 break; 1373 } 1374 1375 case B_PIC_SET_LINE_MODE: 1376 { 1377 const uint16* capMode; 1378 const uint16* joinMode; 1379 const float* miterLimit; 1380 if (callbacks.set_line_mode == NULL || !reader.Get(capMode) 1381 || !reader.Get(joinMode) || !reader.Get(miterLimit)) { 1382 break; 1383 } 1384 1385 callbacks.set_line_mode(userData, (cap_mode)*capMode, 1386 (join_mode)*joinMode, *miterLimit); 1387 break; 1388 } 1389 1390 case B_PIC_SET_PEN_SIZE: 1391 { 1392 const float* penSize; 1393 if (callbacks.set_pen_size == NULL || !reader.Get(penSize)) 1394 break; 1395 1396 callbacks.set_pen_size(userData, *penSize); 1397 break; 1398 } 1399 1400 case B_PIC_SET_FORE_COLOR: 1401 { 1402 const rgb_color* color; 1403 if (callbacks.set_fore_color == NULL || !reader.Get(color)) 1404 break; 1405 1406 callbacks.set_fore_color(userData, *color); 1407 break; 1408 } 1409 1410 case B_PIC_SET_BACK_COLOR: 1411 { 1412 const rgb_color* color; 1413 if (callbacks.set_back_color == NULL || !reader.Get(color)) 1414 break; 1415 1416 callbacks.set_back_color(userData, *color); 1417 break; 1418 } 1419 1420 case B_PIC_SET_STIPLE_PATTERN: 1421 { 1422 const pattern* stipplePattern; 1423 if (callbacks.set_stipple_pattern == NULL 1424 || !reader.Get(stipplePattern)) { 1425 break; 1426 } 1427 1428 callbacks.set_stipple_pattern(userData, *stipplePattern); 1429 break; 1430 } 1431 1432 case B_PIC_SET_SCALE: 1433 { 1434 const float* scale; 1435 if (callbacks.set_scale == NULL || !reader.Get(scale)) 1436 break; 1437 1438 callbacks.set_scale(userData, *scale); 1439 break; 1440 } 1441 1442 case B_PIC_SET_FONT_FAMILY: 1443 { 1444 const char* family; 1445 size_t length; 1446 if (callbacks.set_font_family == NULL 1447 || !reader.GetRemaining(family, length)) { 1448 break; 1449 } 1450 1451 callbacks.set_font_family(userData, family, length); 1452 break; 1453 } 1454 1455 case B_PIC_SET_FONT_STYLE: 1456 { 1457 const char* style; 1458 size_t length; 1459 if (callbacks.set_font_style == NULL 1460 || !reader.GetRemaining(style, length)) { 1461 break; 1462 } 1463 1464 callbacks.set_font_style(userData, style, length); 1465 break; 1466 } 1467 1468 case B_PIC_SET_FONT_SPACING: 1469 { 1470 const uint32* spacing; 1471 if (callbacks.set_font_spacing == NULL || !reader.Get(spacing)) 1472 break; 1473 1474 callbacks.set_font_spacing(userData, *spacing); 1475 break; 1476 } 1477 1478 case B_PIC_SET_FONT_SIZE: 1479 { 1480 const float* size; 1481 if (callbacks.set_font_size == NULL || !reader.Get(size)) 1482 break; 1483 1484 callbacks.set_font_size(userData, *size); 1485 break; 1486 } 1487 1488 case B_PIC_SET_FONT_ROTATE: 1489 { 1490 const float* rotation; 1491 if (callbacks.set_font_rotation == NULL 1492 || !reader.Get(rotation)) { 1493 break; 1494 } 1495 1496 callbacks.set_font_rotation(userData, *rotation); 1497 break; 1498 } 1499 1500 case B_PIC_SET_FONT_ENCODING: 1501 { 1502 const uint32* encoding; 1503 if (callbacks.set_font_encoding == NULL 1504 || !reader.Get(encoding)) { 1505 break; 1506 } 1507 1508 callbacks.set_font_encoding(userData, *encoding); 1509 break; 1510 } 1511 1512 case B_PIC_SET_FONT_FLAGS: 1513 { 1514 const uint32* flags; 1515 if (callbacks.set_font_flags == NULL || !reader.Get(flags)) 1516 break; 1517 1518 callbacks.set_font_flags(userData, *flags); 1519 break; 1520 } 1521 1522 case B_PIC_SET_FONT_SHEAR: 1523 { 1524 const float* shear; 1525 if (callbacks.set_font_shear == NULL || !reader.Get(shear)) 1526 break; 1527 1528 callbacks.set_font_shear(userData, *shear); 1529 break; 1530 } 1531 1532 case B_PIC_SET_FONT_FACE: 1533 { 1534 const uint32* face; 1535 if (callbacks.set_font_face == NULL || !reader.Get(face)) 1536 break; 1537 1538 callbacks.set_font_face(userData, *face); 1539 break; 1540 } 1541 1542 case B_PIC_SET_BLENDING_MODE: 1543 { 1544 const uint16* alphaSourceMode; 1545 const uint16* alphaFunctionMode; 1546 if (callbacks.set_blending_mode == NULL 1547 || !reader.Get(alphaSourceMode) 1548 || !reader.Get(alphaFunctionMode)) { 1549 break; 1550 } 1551 1552 callbacks.set_blending_mode(userData, 1553 (source_alpha)*alphaSourceMode, 1554 (alpha_function)*alphaFunctionMode); 1555 break; 1556 } 1557 1558 case B_PIC_SET_FILL_RULE: 1559 { 1560 const uint32* fillRule; 1561 if (callbacks.set_fill_rule == NULL 1562 || !reader.Get(fillRule)) { 1563 break; 1564 } 1565 1566 callbacks.set_fill_rule(userData, *fillRule); 1567 break; 1568 } 1569 1570 case B_PIC_SET_TRANSFORM: 1571 { 1572 const BAffineTransform* transform; 1573 if (callbacks.set_transform == NULL || !reader.Get(transform)) 1574 break; 1575 1576 callbacks.set_transform(userData, *transform); 1577 break; 1578 } 1579 1580 case B_PIC_AFFINE_TRANSLATE: 1581 { 1582 const double* x; 1583 const double* y; 1584 if (callbacks.translate_by == NULL || !reader.Get(x) 1585 || !reader.Get(y)) { 1586 break; 1587 } 1588 1589 callbacks.translate_by(userData, *x, *y); 1590 break; 1591 } 1592 1593 case B_PIC_AFFINE_SCALE: 1594 { 1595 const double* x; 1596 const double* y; 1597 if (callbacks.scale_by == NULL || !reader.Get(x) 1598 || !reader.Get(y)) { 1599 break; 1600 } 1601 1602 callbacks.scale_by(userData, *x, *y); 1603 break; 1604 } 1605 1606 case B_PIC_AFFINE_ROTATE: 1607 { 1608 const double* angleRadians; 1609 if (callbacks.rotate_by == NULL || !reader.Get(angleRadians)) 1610 break; 1611 1612 callbacks.rotate_by(userData, *angleRadians); 1613 break; 1614 } 1615 1616 case B_PIC_BLEND_LAYER: 1617 { 1618 Layer* const* layer; 1619 if (callbacks.blend_layer == NULL || !reader.Get<Layer*>(layer)) 1620 break; 1621 1622 callbacks.blend_layer(userData, *layer); 1623 break; 1624 } 1625 1626 case B_PIC_CLIP_TO_RECT: 1627 { 1628 const bool* inverse; 1629 const BRect* rect; 1630 1631 if (callbacks.clip_to_rect == NULL || !reader.Get(inverse) 1632 || !reader.Get(rect)) { 1633 break; 1634 } 1635 1636 callbacks.clip_to_rect(userData, *rect, *inverse); 1637 break; 1638 } 1639 1640 case B_PIC_CLIP_TO_SHAPE: 1641 { 1642 const bool* inverse; 1643 const uint32* opCount; 1644 const uint32* pointCount; 1645 const uint32* opList; 1646 const BPoint* pointList; 1647 if (callbacks.clip_to_shape == NULL || !reader.Get(inverse) 1648 || !reader.Get(opCount) || !reader.Get(pointCount) 1649 || !reader.Get(opList, *opCount) 1650 || !reader.Get(pointList, *pointCount)) { 1651 break; 1652 } 1653 1654 callbacks.clip_to_shape(userData, *opCount, opList, 1655 *pointCount, pointList, *inverse); 1656 break; 1657 } 1658 1659 default: 1660 break; 1661 } 1662 1663 #if DEBUG 1664 numOps++; 1665 #if DEBUG > 1 1666 printf("executed in %" B_PRId64 " usecs\n", system_time() 1667 - startOpTime); 1668 #endif 1669 #endif 1670 } 1671 1672 #if DEBUG 1673 printf("Done! %" B_PRId32 " ops, rendering completed in %" B_PRId64 1674 " usecs.\n", numOps, system_time() - startTime); 1675 #endif 1676 return B_OK; 1677 } 1678