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 RETURN_STRING(B_PIC_STROKE_RECT_GRADIENT); 646 RETURN_STRING(B_PIC_FILL_RECT_GRADIENT); 647 RETURN_STRING(B_PIC_STROKE_ROUND_RECT_GRADIENT); 648 RETURN_STRING(B_PIC_FILL_ROUND_RECT_GRADIENT); 649 RETURN_STRING(B_PIC_STROKE_BEZIER_GRADIENT); 650 RETURN_STRING(B_PIC_FILL_BEZIER_GRADIENT); 651 RETURN_STRING(B_PIC_STROKE_POLYGON_GRADIENT); 652 RETURN_STRING(B_PIC_FILL_POLYGON_GRADIENT); 653 RETURN_STRING(B_PIC_STROKE_SHAPE_GRADIENT); 654 RETURN_STRING(B_PIC_FILL_SHAPE_GRADIENT); 655 RETURN_STRING(B_PIC_STROKE_ARC_GRADIENT); 656 RETURN_STRING(B_PIC_FILL_ARC_GRADIENT); 657 RETURN_STRING(B_PIC_STROKE_ELLIPSE_GRADIENT); 658 RETURN_STRING(B_PIC_FILL_ELLIPSE_GRADIENT); 659 660 RETURN_STRING(B_PIC_ENTER_STATE_CHANGE); 661 RETURN_STRING(B_PIC_SET_CLIPPING_RECTS); 662 RETURN_STRING(B_PIC_CLIP_TO_PICTURE); 663 RETURN_STRING(B_PIC_PUSH_STATE); 664 RETURN_STRING(B_PIC_POP_STATE); 665 RETURN_STRING(B_PIC_CLEAR_CLIPPING_RECTS); 666 RETURN_STRING(B_PIC_CLIP_TO_RECT); 667 RETURN_STRING(B_PIC_CLIP_TO_SHAPE); 668 669 RETURN_STRING(B_PIC_SET_ORIGIN); 670 RETURN_STRING(B_PIC_SET_PEN_LOCATION); 671 RETURN_STRING(B_PIC_SET_DRAWING_MODE); 672 RETURN_STRING(B_PIC_SET_LINE_MODE); 673 RETURN_STRING(B_PIC_SET_PEN_SIZE); 674 RETURN_STRING(B_PIC_SET_SCALE); 675 RETURN_STRING(B_PIC_SET_TRANSFORM); 676 RETURN_STRING(B_PIC_SET_FORE_COLOR); 677 RETURN_STRING(B_PIC_SET_BACK_COLOR); 678 RETURN_STRING(B_PIC_SET_STIPLE_PATTERN); 679 RETURN_STRING(B_PIC_ENTER_FONT_STATE); 680 RETURN_STRING(B_PIC_SET_BLENDING_MODE); 681 RETURN_STRING(B_PIC_SET_FILL_RULE); 682 RETURN_STRING(B_PIC_SET_FONT_FAMILY); 683 RETURN_STRING(B_PIC_SET_FONT_STYLE); 684 RETURN_STRING(B_PIC_SET_FONT_SPACING); 685 RETURN_STRING(B_PIC_SET_FONT_ENCODING); 686 RETURN_STRING(B_PIC_SET_FONT_FLAGS); 687 RETURN_STRING(B_PIC_SET_FONT_SIZE); 688 RETURN_STRING(B_PIC_SET_FONT_ROTATE); 689 RETURN_STRING(B_PIC_SET_FONT_SHEAR); 690 RETURN_STRING(B_PIC_SET_FONT_BPP); 691 RETURN_STRING(B_PIC_SET_FONT_FACE); 692 693 RETURN_STRING(B_PIC_AFFINE_TRANSLATE); 694 RETURN_STRING(B_PIC_AFFINE_SCALE); 695 RETURN_STRING(B_PIC_AFFINE_ROTATE); 696 697 RETURN_STRING(B_PIC_BLEND_LAYER); 698 699 default: return "Unknown op"; 700 } 701 #undef RETURN_STRING 702 } 703 #endif 704 705 706 PicturePlayer::PicturePlayer(const void *data, size_t size, BList *pictures) 707 : fData(data), 708 fSize(size), 709 fPictures(pictures) 710 { 711 } 712 713 714 PicturePlayer::~PicturePlayer() 715 { 716 } 717 718 719 status_t 720 PicturePlayer::Play(void** callBackTable, int32 tableEntries, void* userData) 721 { 722 const BPrivate::picture_player_callbacks kAdapterCallbacks = { 723 move_pen_by, 724 stroke_line, 725 draw_rect, 726 draw_round_rect, 727 draw_bezier, 728 draw_arc, 729 draw_ellipse, 730 draw_polygon, 731 draw_shape, 732 draw_string, 733 draw_pixels, 734 draw_picture, 735 set_clipping_rects, 736 clip_to_picture, 737 push_state, 738 pop_state, 739 enter_state_change, 740 exit_state_change, 741 enter_font_state, 742 exit_font_state, 743 set_origin, 744 set_pen_location, 745 set_drawing_mode, 746 set_line_mode, 747 set_pen_size, 748 set_fore_color, 749 set_back_color, 750 set_stipple_pattern, 751 set_scale, 752 set_font_family, 753 set_font_style, 754 set_font_spacing, 755 set_font_size, 756 set_font_rotation, 757 set_font_encoding, 758 set_font_flags, 759 set_font_shear, 760 set_font_face, 761 set_blending_mode, 762 set_transform, 763 translate_by, 764 scale_by, 765 rotate_by, 766 blend_layer, 767 clip_to_rect, 768 clip_to_shape, 769 draw_string_locations, 770 draw_rect_gradient, 771 draw_round_rect_gradient, 772 draw_bezier_gradient, 773 draw_arc_gradient, 774 draw_ellipse_gradient, 775 draw_polygon_gradient, 776 draw_shape_gradient, 777 set_fill_rule 778 }; 779 780 // We don't check if the functions in the table are NULL, but we 781 // check the tableEntries to see if the table is big enough. 782 // If an application supplies the wrong size or an invalid pointer, 783 // it's its own fault. 784 785 // If the caller supplied a function table smaller than needed, 786 // we use our dummy table, and copy the supported ops from the supplied one. 787 void *dummyTable[kOpsTableSize]; 788 789 adapter_context adapterContext; 790 adapterContext.user_data = userData; 791 adapterContext.function_table = callBackTable; 792 793 if ((size_t)tableEntries < kOpsTableSize) { 794 memcpy(dummyTable, callBackTable, tableEntries * sizeof(void*)); 795 for (size_t i = (size_t)tableEntries; i < kOpsTableSize; i++) 796 dummyTable[i] = (void*)nop; 797 798 adapterContext.function_table = dummyTable; 799 } 800 801 return _Play(kAdapterCallbacks, &adapterContext, fData, fSize, 0); 802 } 803 804 805 status_t 806 PicturePlayer::Play(const picture_player_callbacks& callbacks, 807 size_t callbacksSize, void* userData) 808 { 809 return _Play(callbacks, userData, fData, fSize, 0); 810 } 811 812 813 class DataReader { 814 public: 815 DataReader(const void* buffer, size_t length) 816 : 817 fBuffer((const uint8*)buffer), 818 fRemaining(length) 819 { 820 } 821 822 size_t 823 Remaining() const 824 { 825 return fRemaining; 826 } 827 828 template<typename T> 829 bool 830 Get(const T*& typed, size_t count = 1) 831 { 832 if (fRemaining < sizeof(T) * count) 833 return false; 834 835 typed = reinterpret_cast<const T *>(fBuffer); 836 fRemaining -= sizeof(T) * count; 837 fBuffer += sizeof(T) * count; 838 return true; 839 } 840 841 bool GetGradient(BGradient*& gradient) 842 { 843 BMemoryIO stream(fBuffer, fRemaining); 844 printf("fRemaining: %ld\n", fRemaining); 845 if (BGradient::Unflatten(gradient, &stream) != B_OK) { 846 printf("BGradient::Unflatten(_gradient, &stream) != B_OK\n"); 847 return false; 848 } 849 850 fRemaining -= stream.Position(); 851 fBuffer += stream.Position(); 852 return true; 853 } 854 855 template<typename T> 856 bool 857 GetRemaining(const T*& buffer, size_t& size) 858 { 859 if (fRemaining == 0) 860 return false; 861 862 buffer = reinterpret_cast<const T*>(fBuffer); 863 size = fRemaining; 864 fRemaining = 0; 865 return true; 866 } 867 868 private: 869 const uint8* fBuffer; 870 size_t fRemaining; 871 }; 872 873 874 struct picture_data_entry_header { 875 uint16 op; 876 uint32 size; 877 } _PACKED; 878 879 880 status_t 881 PicturePlayer::_Play(const picture_player_callbacks& callbacks, void* userData, 882 const void* buffer, size_t length, uint16 parentOp) 883 { 884 #if DEBUG 885 printf("Start rendering %sBPicture...\n", parentOp != 0 ? "sub " : ""); 886 bigtime_t startTime = system_time(); 887 int32 numOps = 0; 888 #endif 889 890 DataReader pictureReader(buffer, length); 891 892 while (pictureReader.Remaining() > 0) { 893 const picture_data_entry_header* header; 894 const uint8* opData = NULL; 895 if (!pictureReader.Get(header) 896 || !pictureReader.Get(opData, header->size)) { 897 return B_BAD_DATA; 898 } 899 900 DataReader reader(opData, header->size); 901 902 // Disallow ops that don't fit the parent. 903 switch (parentOp) { 904 case 0: 905 // No parent op, no restrictions. 906 break; 907 908 case B_PIC_ENTER_STATE_CHANGE: 909 if (header->op <= B_PIC_ENTER_STATE_CHANGE 910 || header->op > B_PIC_SET_TRANSFORM) { 911 return B_BAD_DATA; 912 } 913 break; 914 915 case B_PIC_ENTER_FONT_STATE: 916 if (header->op < B_PIC_SET_FONT_FAMILY 917 || header->op > B_PIC_SET_FONT_FACE) { 918 return B_BAD_DATA; 919 } 920 break; 921 922 default: 923 return B_BAD_DATA; 924 } 925 926 #if DEBUG > 1 927 bigtime_t startOpTime = system_time(); 928 printf("Op %s ", PictureOpToString(header->op)); 929 #endif 930 switch (header->op) { 931 case B_PIC_MOVE_PEN_BY: 932 { 933 const BPoint* where; 934 if (callbacks.move_pen_by == NULL || !reader.Get(where)) 935 break; 936 937 callbacks.move_pen_by(userData, *where); 938 break; 939 } 940 941 case B_PIC_STROKE_LINE: 942 { 943 const BPoint* start; 944 const BPoint* end; 945 if (callbacks.stroke_line == NULL || !reader.Get(start) 946 || !reader.Get(end)) { 947 break; 948 } 949 950 callbacks.stroke_line(userData, *start, *end); 951 break; 952 } 953 954 case B_PIC_STROKE_RECT: 955 case B_PIC_FILL_RECT: 956 { 957 const BRect* rect; 958 if (callbacks.draw_rect == NULL || !reader.Get(rect)) 959 break; 960 961 callbacks.draw_rect(userData, *rect, 962 header->op == B_PIC_FILL_RECT); 963 break; 964 } 965 966 case B_PIC_STROKE_ROUND_RECT: 967 case B_PIC_FILL_ROUND_RECT: 968 { 969 const BRect* rect; 970 const BPoint* radii; 971 if (callbacks.draw_round_rect == NULL || !reader.Get(rect) 972 || !reader.Get(radii)) { 973 break; 974 } 975 976 callbacks.draw_round_rect(userData, *rect, *radii, 977 header->op == B_PIC_FILL_ROUND_RECT); 978 break; 979 } 980 981 case B_PIC_STROKE_BEZIER: 982 case B_PIC_FILL_BEZIER: 983 { 984 const size_t kNumControlPoints = 4; 985 const BPoint* controlPoints; 986 if (callbacks.draw_bezier == NULL 987 || !reader.Get(controlPoints, kNumControlPoints)) { 988 break; 989 } 990 991 callbacks.draw_bezier(userData, kNumControlPoints, 992 controlPoints, header->op == B_PIC_FILL_BEZIER); 993 break; 994 } 995 996 case B_PIC_STROKE_ARC: 997 case B_PIC_FILL_ARC: 998 { 999 const BPoint* center; 1000 const BPoint* radii; 1001 const float* startTheta; 1002 const float* arcTheta; 1003 if (callbacks.draw_arc == NULL || !reader.Get(center) 1004 || !reader.Get(radii) || !reader.Get(startTheta) 1005 || !reader.Get(arcTheta)) { 1006 break; 1007 } 1008 1009 callbacks.draw_arc(userData, *center, *radii, *startTheta, 1010 *arcTheta, header->op == B_PIC_FILL_ARC); 1011 break; 1012 } 1013 1014 case B_PIC_STROKE_ELLIPSE: 1015 case B_PIC_FILL_ELLIPSE: 1016 { 1017 const BRect* rect; 1018 if (callbacks.draw_ellipse == NULL || !reader.Get(rect)) 1019 break; 1020 1021 callbacks.draw_ellipse(userData, *rect, 1022 header->op == B_PIC_FILL_ELLIPSE); 1023 break; 1024 } 1025 1026 case B_PIC_STROKE_POLYGON: 1027 case B_PIC_FILL_POLYGON: 1028 { 1029 const uint32* numPoints; 1030 const BPoint* points; 1031 if (callbacks.draw_polygon == NULL || !reader.Get(numPoints) 1032 || !reader.Get(points, *numPoints)) { 1033 break; 1034 } 1035 1036 bool isClosed = true; 1037 const bool* closedPointer; 1038 if (header->op != B_PIC_FILL_POLYGON) { 1039 if (!reader.Get(closedPointer)) 1040 break; 1041 1042 isClosed = *closedPointer; 1043 } 1044 1045 callbacks.draw_polygon(userData, *numPoints, points, isClosed, 1046 header->op == B_PIC_FILL_POLYGON); 1047 break; 1048 } 1049 1050 case B_PIC_STROKE_SHAPE: 1051 case B_PIC_FILL_SHAPE: 1052 { 1053 const uint32* opCount; 1054 const uint32* pointCount; 1055 const uint32* opList; 1056 const BPoint* pointList; 1057 if (callbacks.draw_shape == NULL || !reader.Get(opCount) 1058 || !reader.Get(pointCount) || !reader.Get(opList, *opCount) 1059 || !reader.Get(pointList, *pointCount)) { 1060 break; 1061 } 1062 1063 // TODO: remove BShape data copying 1064 BShape shape; 1065 shape.SetData(*opCount, *pointCount, opList, pointList); 1066 1067 callbacks.draw_shape(userData, shape, 1068 header->op == B_PIC_FILL_SHAPE); 1069 break; 1070 } 1071 1072 case B_PIC_STROKE_RECT_GRADIENT: 1073 case B_PIC_FILL_RECT_GRADIENT: 1074 { 1075 const BRect* rect; 1076 BGradient* gradient; 1077 if (callbacks.draw_rect_gradient == NULL || !reader.Get(rect) || !reader.GetGradient(gradient)) 1078 break; 1079 ObjectDeleter<BGradient> gradientDeleter(gradient); 1080 1081 callbacks.draw_rect_gradient(userData, *rect, *gradient, 1082 header->op == B_PIC_FILL_RECT_GRADIENT); 1083 break; 1084 } 1085 1086 case B_PIC_STROKE_ROUND_RECT_GRADIENT: 1087 case B_PIC_FILL_ROUND_RECT_GRADIENT: 1088 { 1089 const BRect* rect; 1090 const BPoint* radii; 1091 BGradient* gradient; 1092 if (callbacks.draw_round_rect_gradient == NULL || !reader.Get(rect) 1093 || !reader.Get(radii) || !reader.GetGradient(gradient)) { 1094 break; 1095 } 1096 ObjectDeleter<BGradient> gradientDeleter(gradient); 1097 1098 callbacks.draw_round_rect_gradient(userData, *rect, *radii, *gradient, 1099 header->op == B_PIC_FILL_ROUND_RECT_GRADIENT); 1100 break; 1101 } 1102 1103 case B_PIC_STROKE_BEZIER_GRADIENT: 1104 case B_PIC_FILL_BEZIER_GRADIENT: 1105 { 1106 const size_t kNumControlPoints = 4; 1107 const BPoint* controlPoints; 1108 BGradient* gradient; 1109 if (callbacks.draw_bezier_gradient == NULL 1110 || !reader.Get(controlPoints, kNumControlPoints) || !reader.GetGradient(gradient)) { 1111 break; 1112 } 1113 ObjectDeleter<BGradient> gradientDeleter(gradient); 1114 1115 callbacks.draw_bezier_gradient(userData, kNumControlPoints, 1116 controlPoints, *gradient, header->op == B_PIC_FILL_BEZIER_GRADIENT); 1117 break; 1118 } 1119 1120 case B_PIC_STROKE_POLYGON_GRADIENT: 1121 case B_PIC_FILL_POLYGON_GRADIENT: 1122 { 1123 const uint32* numPoints; 1124 const BPoint* points; 1125 BGradient* gradient; 1126 if (callbacks.draw_polygon_gradient == NULL || !reader.Get(numPoints) 1127 || !reader.Get(points, *numPoints)) { 1128 break; 1129 } 1130 1131 bool isClosed = true; 1132 const bool* closedPointer; 1133 if (header->op != B_PIC_FILL_POLYGON_GRADIENT) { 1134 if (!reader.Get(closedPointer)) 1135 break; 1136 1137 isClosed = *closedPointer; 1138 } 1139 1140 if (!reader.GetGradient(gradient)) 1141 break; 1142 ObjectDeleter<BGradient> gradientDeleter(gradient); 1143 1144 callbacks.draw_polygon_gradient(userData, *numPoints, points, isClosed, *gradient, 1145 header->op == B_PIC_FILL_POLYGON_GRADIENT); 1146 break; 1147 } 1148 1149 case B_PIC_STROKE_SHAPE_GRADIENT: 1150 case B_PIC_FILL_SHAPE_GRADIENT: 1151 { 1152 const uint32* opCount; 1153 const uint32* pointCount; 1154 const uint32* opList; 1155 const BPoint* pointList; 1156 BGradient* gradient; 1157 if (callbacks.draw_shape_gradient == NULL || !reader.Get(opCount) 1158 || !reader.Get(pointCount) || !reader.Get(opList, *opCount) 1159 || !reader.Get(pointList, *pointCount) || !reader.GetGradient(gradient)) { 1160 break; 1161 } 1162 ObjectDeleter<BGradient> gradientDeleter(gradient); 1163 1164 // TODO: remove BShape data copying 1165 BShape shape; 1166 shape.SetData(*opCount, *pointCount, opList, pointList); 1167 1168 callbacks.draw_shape_gradient(userData, shape, *gradient, 1169 header->op == B_PIC_FILL_SHAPE_GRADIENT); 1170 break; 1171 } 1172 1173 case B_PIC_STROKE_ARC_GRADIENT: 1174 case B_PIC_FILL_ARC_GRADIENT: 1175 { 1176 const BPoint* center; 1177 const BPoint* radii; 1178 const float* startTheta; 1179 const float* arcTheta; 1180 BGradient* gradient; 1181 if (callbacks.draw_arc_gradient == NULL || !reader.Get(center) 1182 || !reader.Get(radii) || !reader.Get(startTheta) 1183 || !reader.Get(arcTheta) || !reader.GetGradient(gradient)) { 1184 break; 1185 } 1186 ObjectDeleter<BGradient> gradientDeleter(gradient); 1187 1188 callbacks.draw_arc_gradient(userData, *center, *radii, *startTheta, 1189 *arcTheta, *gradient, header->op == B_PIC_FILL_ARC_GRADIENT); 1190 break; 1191 } 1192 1193 case B_PIC_STROKE_ELLIPSE_GRADIENT: 1194 case B_PIC_FILL_ELLIPSE_GRADIENT: 1195 { 1196 const BRect* rect; 1197 BGradient* gradient; 1198 if (callbacks.draw_ellipse_gradient == NULL || !reader.Get(rect) || !reader.GetGradient(gradient)) 1199 break; 1200 ObjectDeleter<BGradient> gradientDeleter(gradient); 1201 1202 callbacks.draw_ellipse_gradient(userData, *rect, *gradient, 1203 header->op == B_PIC_FILL_ELLIPSE_GRADIENT); 1204 break; 1205 } 1206 1207 case B_PIC_DRAW_STRING: 1208 { 1209 const float* escapementSpace; 1210 const float* escapementNonSpace; 1211 const char* string; 1212 size_t length; 1213 if (callbacks.draw_string == NULL 1214 || !reader.Get(escapementSpace) 1215 || !reader.Get(escapementNonSpace) 1216 || !reader.GetRemaining(string, length)) { 1217 break; 1218 } 1219 1220 callbacks.draw_string(userData, string, length, 1221 *escapementSpace, *escapementNonSpace); 1222 break; 1223 } 1224 1225 case B_PIC_DRAW_STRING_LOCATIONS: 1226 { 1227 const uint32* pointCount; 1228 const BPoint* pointList; 1229 const char* string; 1230 size_t length; 1231 if (callbacks.draw_string_locations == NULL 1232 || !reader.Get(pointCount) 1233 || !reader.Get(pointList, *pointCount) 1234 || !reader.GetRemaining(string, length)) { 1235 break; 1236 } 1237 1238 callbacks.draw_string_locations(userData, string, length, 1239 pointList, *pointCount); 1240 break; 1241 } 1242 1243 case B_PIC_DRAW_PIXELS: 1244 { 1245 const BRect* sourceRect; 1246 const BRect* destinationRect; 1247 const uint32* width; 1248 const uint32* height; 1249 const uint32* bytesPerRow; 1250 const uint32* colorSpace; 1251 const uint32* flags; 1252 const void* data; 1253 size_t length; 1254 if (callbacks.draw_pixels == NULL || !reader.Get(sourceRect) 1255 || !reader.Get(destinationRect) || !reader.Get(width) 1256 || !reader.Get(height) || !reader.Get(bytesPerRow) 1257 || !reader.Get(colorSpace) || !reader.Get(flags) 1258 || !reader.GetRemaining(data, length)) { 1259 break; 1260 } 1261 1262 callbacks.draw_pixels(userData, *sourceRect, *destinationRect, 1263 *width, *height, *bytesPerRow, (color_space)*colorSpace, 1264 *flags, data, length); 1265 break; 1266 } 1267 1268 case B_PIC_DRAW_PICTURE: 1269 { 1270 const BPoint* where; 1271 const int32* token; 1272 if (callbacks.draw_picture == NULL || !reader.Get(where) 1273 || !reader.Get(token)) { 1274 break; 1275 } 1276 1277 callbacks.draw_picture(userData, *where, *token); 1278 break; 1279 } 1280 1281 case B_PIC_SET_CLIPPING_RECTS: 1282 { 1283 const uint32* numRects; 1284 const BRect* rects; 1285 if (callbacks.set_clipping_rects == NULL 1286 || !reader.Get(numRects) || !reader.Get(rects, *numRects)) { 1287 break; 1288 } 1289 1290 callbacks.set_clipping_rects(userData, *numRects, rects); 1291 break; 1292 } 1293 1294 case B_PIC_CLEAR_CLIPPING_RECTS: 1295 { 1296 if (callbacks.set_clipping_rects == NULL) 1297 break; 1298 1299 callbacks.set_clipping_rects(userData, 0, NULL); 1300 break; 1301 } 1302 1303 case B_PIC_CLIP_TO_PICTURE: 1304 { 1305 const int32* token; 1306 const BPoint* where; 1307 const bool* inverse; 1308 if (callbacks.clip_to_picture == NULL || !reader.Get(token) 1309 || !reader.Get(where) || !reader.Get(inverse)) 1310 break; 1311 1312 callbacks.clip_to_picture(userData, *token, *where, *inverse); 1313 break; 1314 } 1315 1316 case B_PIC_PUSH_STATE: 1317 { 1318 if (callbacks.push_state == NULL) 1319 break; 1320 1321 callbacks.push_state(userData); 1322 break; 1323 } 1324 1325 case B_PIC_POP_STATE: 1326 { 1327 if (callbacks.pop_state == NULL) 1328 break; 1329 1330 callbacks.pop_state(userData); 1331 break; 1332 } 1333 1334 case B_PIC_ENTER_STATE_CHANGE: 1335 case B_PIC_ENTER_FONT_STATE: 1336 { 1337 const void* data; 1338 size_t length; 1339 if (!reader.GetRemaining(data, length)) 1340 break; 1341 1342 if (header->op == B_PIC_ENTER_STATE_CHANGE) { 1343 if (callbacks.enter_state_change != NULL) 1344 callbacks.enter_state_change(userData); 1345 } else if (callbacks.enter_font_state != NULL) 1346 callbacks.enter_font_state(userData); 1347 1348 status_t result = _Play(callbacks, userData, data, length, 1349 header->op); 1350 if (result != B_OK) 1351 return result; 1352 1353 if (header->op == B_PIC_ENTER_STATE_CHANGE) { 1354 if (callbacks.exit_state_change != NULL) 1355 callbacks.exit_state_change(userData); 1356 } else if (callbacks.exit_font_state != NULL) 1357 callbacks.exit_font_state(userData); 1358 1359 break; 1360 } 1361 1362 case B_PIC_SET_ORIGIN: 1363 { 1364 const BPoint* origin; 1365 if (callbacks.set_origin == NULL || !reader.Get(origin)) 1366 break; 1367 1368 callbacks.set_origin(userData, *origin); 1369 break; 1370 } 1371 1372 case B_PIC_SET_PEN_LOCATION: 1373 { 1374 const BPoint* location; 1375 if (callbacks.set_pen_location == NULL || !reader.Get(location)) 1376 break; 1377 1378 callbacks.set_pen_location(userData, *location); 1379 break; 1380 } 1381 1382 case B_PIC_SET_DRAWING_MODE: 1383 { 1384 const uint16* mode; 1385 if (callbacks.set_drawing_mode == NULL || !reader.Get(mode)) 1386 break; 1387 1388 callbacks.set_drawing_mode(userData, (drawing_mode)*mode); 1389 break; 1390 } 1391 1392 case B_PIC_SET_LINE_MODE: 1393 { 1394 const uint16* capMode; 1395 const uint16* joinMode; 1396 const float* miterLimit; 1397 if (callbacks.set_line_mode == NULL || !reader.Get(capMode) 1398 || !reader.Get(joinMode) || !reader.Get(miterLimit)) { 1399 break; 1400 } 1401 1402 callbacks.set_line_mode(userData, (cap_mode)*capMode, 1403 (join_mode)*joinMode, *miterLimit); 1404 break; 1405 } 1406 1407 case B_PIC_SET_PEN_SIZE: 1408 { 1409 const float* penSize; 1410 if (callbacks.set_pen_size == NULL || !reader.Get(penSize)) 1411 break; 1412 1413 callbacks.set_pen_size(userData, *penSize); 1414 break; 1415 } 1416 1417 case B_PIC_SET_FORE_COLOR: 1418 { 1419 const rgb_color* color; 1420 if (callbacks.set_fore_color == NULL || !reader.Get(color)) 1421 break; 1422 1423 callbacks.set_fore_color(userData, *color); 1424 break; 1425 } 1426 1427 case B_PIC_SET_BACK_COLOR: 1428 { 1429 const rgb_color* color; 1430 if (callbacks.set_back_color == NULL || !reader.Get(color)) 1431 break; 1432 1433 callbacks.set_back_color(userData, *color); 1434 break; 1435 } 1436 1437 case B_PIC_SET_STIPLE_PATTERN: 1438 { 1439 const pattern* stipplePattern; 1440 if (callbacks.set_stipple_pattern == NULL 1441 || !reader.Get(stipplePattern)) { 1442 break; 1443 } 1444 1445 callbacks.set_stipple_pattern(userData, *stipplePattern); 1446 break; 1447 } 1448 1449 case B_PIC_SET_SCALE: 1450 { 1451 const float* scale; 1452 if (callbacks.set_scale == NULL || !reader.Get(scale)) 1453 break; 1454 1455 callbacks.set_scale(userData, *scale); 1456 break; 1457 } 1458 1459 case B_PIC_SET_FONT_FAMILY: 1460 { 1461 const char* family; 1462 size_t length; 1463 if (callbacks.set_font_family == NULL 1464 || !reader.GetRemaining(family, length)) { 1465 break; 1466 } 1467 1468 callbacks.set_font_family(userData, family, length); 1469 break; 1470 } 1471 1472 case B_PIC_SET_FONT_STYLE: 1473 { 1474 const char* style; 1475 size_t length; 1476 if (callbacks.set_font_style == NULL 1477 || !reader.GetRemaining(style, length)) { 1478 break; 1479 } 1480 1481 callbacks.set_font_style(userData, style, length); 1482 break; 1483 } 1484 1485 case B_PIC_SET_FONT_SPACING: 1486 { 1487 const uint32* spacing; 1488 if (callbacks.set_font_spacing == NULL || !reader.Get(spacing)) 1489 break; 1490 1491 callbacks.set_font_spacing(userData, *spacing); 1492 break; 1493 } 1494 1495 case B_PIC_SET_FONT_SIZE: 1496 { 1497 const float* size; 1498 if (callbacks.set_font_size == NULL || !reader.Get(size)) 1499 break; 1500 1501 callbacks.set_font_size(userData, *size); 1502 break; 1503 } 1504 1505 case B_PIC_SET_FONT_ROTATE: 1506 { 1507 const float* rotation; 1508 if (callbacks.set_font_rotation == NULL 1509 || !reader.Get(rotation)) { 1510 break; 1511 } 1512 1513 callbacks.set_font_rotation(userData, *rotation); 1514 break; 1515 } 1516 1517 case B_PIC_SET_FONT_ENCODING: 1518 { 1519 const uint32* encoding; 1520 if (callbacks.set_font_encoding == NULL 1521 || !reader.Get(encoding)) { 1522 break; 1523 } 1524 1525 callbacks.set_font_encoding(userData, *encoding); 1526 break; 1527 } 1528 1529 case B_PIC_SET_FONT_FLAGS: 1530 { 1531 const uint32* flags; 1532 if (callbacks.set_font_flags == NULL || !reader.Get(flags)) 1533 break; 1534 1535 callbacks.set_font_flags(userData, *flags); 1536 break; 1537 } 1538 1539 case B_PIC_SET_FONT_SHEAR: 1540 { 1541 const float* shear; 1542 if (callbacks.set_font_shear == NULL || !reader.Get(shear)) 1543 break; 1544 1545 callbacks.set_font_shear(userData, *shear); 1546 break; 1547 } 1548 1549 case B_PIC_SET_FONT_FACE: 1550 { 1551 const uint32* face; 1552 if (callbacks.set_font_face == NULL || !reader.Get(face)) 1553 break; 1554 1555 callbacks.set_font_face(userData, *face); 1556 break; 1557 } 1558 1559 case B_PIC_SET_BLENDING_MODE: 1560 { 1561 const uint16* alphaSourceMode; 1562 const uint16* alphaFunctionMode; 1563 if (callbacks.set_blending_mode == NULL 1564 || !reader.Get(alphaSourceMode) 1565 || !reader.Get(alphaFunctionMode)) { 1566 break; 1567 } 1568 1569 callbacks.set_blending_mode(userData, 1570 (source_alpha)*alphaSourceMode, 1571 (alpha_function)*alphaFunctionMode); 1572 break; 1573 } 1574 1575 case B_PIC_SET_FILL_RULE: 1576 { 1577 const uint32* fillRule; 1578 if (callbacks.set_fill_rule == NULL 1579 || !reader.Get(fillRule)) { 1580 break; 1581 } 1582 1583 callbacks.set_fill_rule(userData, *fillRule); 1584 break; 1585 } 1586 1587 case B_PIC_SET_TRANSFORM: 1588 { 1589 const BAffineTransform* transform; 1590 if (callbacks.set_transform == NULL || !reader.Get(transform)) 1591 break; 1592 1593 callbacks.set_transform(userData, *transform); 1594 break; 1595 } 1596 1597 case B_PIC_AFFINE_TRANSLATE: 1598 { 1599 const double* x; 1600 const double* y; 1601 if (callbacks.translate_by == NULL || !reader.Get(x) 1602 || !reader.Get(y)) { 1603 break; 1604 } 1605 1606 callbacks.translate_by(userData, *x, *y); 1607 break; 1608 } 1609 1610 case B_PIC_AFFINE_SCALE: 1611 { 1612 const double* x; 1613 const double* y; 1614 if (callbacks.scale_by == NULL || !reader.Get(x) 1615 || !reader.Get(y)) { 1616 break; 1617 } 1618 1619 callbacks.scale_by(userData, *x, *y); 1620 break; 1621 } 1622 1623 case B_PIC_AFFINE_ROTATE: 1624 { 1625 const double* angleRadians; 1626 if (callbacks.rotate_by == NULL || !reader.Get(angleRadians)) 1627 break; 1628 1629 callbacks.rotate_by(userData, *angleRadians); 1630 break; 1631 } 1632 1633 case B_PIC_BLEND_LAYER: 1634 { 1635 Layer* const* layer; 1636 if (callbacks.blend_layer == NULL || !reader.Get<Layer*>(layer)) 1637 break; 1638 1639 callbacks.blend_layer(userData, *layer); 1640 break; 1641 } 1642 1643 case B_PIC_CLIP_TO_RECT: 1644 { 1645 const bool* inverse; 1646 const BRect* rect; 1647 1648 if (callbacks.clip_to_rect == NULL || !reader.Get(inverse) 1649 || !reader.Get(rect)) { 1650 break; 1651 } 1652 1653 callbacks.clip_to_rect(userData, *rect, *inverse); 1654 break; 1655 } 1656 1657 case B_PIC_CLIP_TO_SHAPE: 1658 { 1659 const bool* inverse; 1660 const uint32* opCount; 1661 const uint32* pointCount; 1662 const uint32* opList; 1663 const BPoint* pointList; 1664 if (callbacks.clip_to_shape == NULL || !reader.Get(inverse) 1665 || !reader.Get(opCount) || !reader.Get(pointCount) 1666 || !reader.Get(opList, *opCount) 1667 || !reader.Get(pointList, *pointCount)) { 1668 break; 1669 } 1670 1671 callbacks.clip_to_shape(userData, *opCount, opList, 1672 *pointCount, pointList, *inverse); 1673 break; 1674 } 1675 1676 default: 1677 break; 1678 } 1679 1680 #if DEBUG 1681 numOps++; 1682 #if DEBUG > 1 1683 printf("executed in %" B_PRId64 " usecs\n", system_time() 1684 - startOpTime); 1685 #endif 1686 #endif 1687 } 1688 1689 #if DEBUG 1690 printf("Done! %" B_PRId32 " ops, rendering completed in %" B_PRId64 1691 " usecs.\n", numOps, system_time() - startTime); 1692 #endif 1693 return B_OK; 1694 } 1695