1/* 2 * Copyright 2006-2018 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stefano Ceccherini, stefano.ceccherini@gmail.com 7 * Julian Harnath, <julian.harnath@rwth-achen.de> 8 * Stephan A��mus <superstippi@gmx.de> 9 */ 10 11#include <PictureDataWriter.h> 12 13#include <stdio.h> 14#include <string.h> 15 16#include <DataIO.h> 17#include <Gradient.h> 18#include <Point.h> 19#include <Rect.h> 20#include <Region.h> 21 22#include <PictureProtocol.h> 23 24#define THROW_ERROR(error) throw (status_t)(error) 25 26 27// TODO: Review writing of strings. AFAIK in the picture data format 28// They are not supposed to be NULL terminated 29// (at least, it's not mandatory) so we should write their size too. 30PictureDataWriter::PictureDataWriter() 31 : 32 fData(NULL) 33{ 34} 35 36 37PictureDataWriter::PictureDataWriter(BPositionIO* data) 38 : 39 fData(data) 40{ 41} 42 43 44PictureDataWriter::~PictureDataWriter() 45{ 46} 47 48 49status_t 50PictureDataWriter::SetTo(BPositionIO* data) 51{ 52 if (data == NULL) 53 return B_BAD_VALUE; 54 55 fData = data; 56 57 return B_OK; 58} 59 60 61status_t 62PictureDataWriter::WriteSetOrigin(const BPoint& point) 63{ 64 try { 65 BeginOp(B_PIC_SET_ORIGIN); 66 Write<BPoint>(point); 67 EndOp(); 68 } catch (status_t& status) { 69 return status; 70 } 71 72 return B_OK; 73} 74 75 76status_t 77PictureDataWriter::WriteInvertRect(const BRect& rect) 78{ 79 try { 80 WritePushState(); 81 WriteSetDrawingMode(B_OP_INVERT); 82 83 BeginOp(B_PIC_FILL_RECT); 84 Write<BRect>(rect); 85 EndOp(); 86 87 WritePopState(); 88 } catch (status_t& status) { 89 return status; 90 } 91 92 return B_OK; 93} 94 95 96status_t 97PictureDataWriter::WriteSetDrawingMode(const drawing_mode& mode) 98{ 99 try { 100 BeginOp(B_PIC_SET_DRAWING_MODE); 101 Write<int16>((int16)mode); 102 EndOp(); 103 } catch (status_t& status) { 104 return status; 105 } 106 107 return B_OK; 108} 109 110 111status_t 112PictureDataWriter::WriteSetPenLocation(const BPoint& point) 113{ 114 try { 115 BeginOp(B_PIC_SET_PEN_LOCATION); 116 Write<BPoint>(point); 117 EndOp(); 118 } catch (status_t& status) { 119 return status; 120 } 121 122 return B_OK; 123} 124 125 126status_t 127PictureDataWriter::WriteSetPenSize(const float& penSize) 128{ 129 try { 130 BeginOp(B_PIC_SET_PEN_SIZE); 131 Write<float>(penSize); 132 EndOp(); 133 } catch (status_t& status) { 134 return status; 135 } 136 137 return B_OK; 138} 139 140 141status_t 142PictureDataWriter::WriteSetLineMode(const cap_mode& cap, const join_mode& join, 143 const float& miterLimit) 144{ 145 try { 146 BeginOp(B_PIC_SET_LINE_MODE); 147 Write<int16>((int16)cap); 148 Write<int16>((int16)join); 149 Write<float>(miterLimit); 150 EndOp(); 151 } catch (status_t& status) { 152 return status; 153 } 154 155 return B_OK; 156} 157 158 159status_t 160PictureDataWriter::WriteSetFillRule(int32 fillRule) 161{ 162 try { 163 BeginOp(B_PIC_SET_FILL_RULE); 164 Write<int32>(fillRule); 165 EndOp(); 166 } catch (status_t& status) { 167 return status; 168 } 169 170 return B_OK; 171} 172 173 174status_t 175PictureDataWriter::WriteSetScale(const float& scale) 176{ 177 try { 178 BeginOp(B_PIC_SET_SCALE); 179 Write<float>(scale); 180 EndOp(); 181 } catch (status_t& status) { 182 return status; 183 } 184 185 return B_OK; 186} 187 188 189status_t 190PictureDataWriter::WriteSetTransform(BAffineTransform transform) 191{ 192 try { 193 BeginOp(B_PIC_SET_TRANSFORM); 194 Write<BAffineTransform>(transform); 195 EndOp(); 196 } catch (status_t& status) { 197 return status; 198 } 199 200 return B_OK; 201} 202 203 204status_t 205PictureDataWriter::WriteTranslateBy(double x, double y) 206{ 207 try { 208 BeginOp(B_PIC_AFFINE_TRANSLATE); 209 Write<double>(x); 210 Write<double>(y); 211 EndOp(); 212 } catch (status_t& status) { 213 return status; 214 } 215 216 return B_OK; 217} 218 219 220status_t 221PictureDataWriter::WriteScaleBy(double x, double y) 222{ 223 try { 224 BeginOp(B_PIC_AFFINE_SCALE); 225 Write<double>(x); 226 Write<double>(y); 227 EndOp(); 228 } catch (status_t& status) { 229 return status; 230 } 231 232 return B_OK; 233} 234 235 236status_t 237PictureDataWriter::WriteRotateBy(double angleRadians) 238{ 239 try { 240 BeginOp(B_PIC_AFFINE_ROTATE); 241 Write<double>(angleRadians); 242 EndOp(); 243 } catch (status_t& status) { 244 return status; 245 } 246 247 return B_OK; 248} 249 250 251status_t 252PictureDataWriter::WriteSetPattern(const ::pattern& pattern) 253{ 254 try { 255 BeginOp(B_PIC_SET_STIPLE_PATTERN); 256 Write< ::pattern>(pattern); 257 EndOp(); 258 } catch (status_t& status) { 259 return status; 260 } 261 262 return B_OK; 263} 264 265 266status_t 267PictureDataWriter::WriteClipToPicture(int32 pictureToken, 268 const BPoint& origin, bool inverse) 269{ 270 // TODO: I don't know if it's compatible with R5's BPicture version 271 try { 272 BeginOp(B_PIC_CLIP_TO_PICTURE); 273 Write<int32>(pictureToken); 274 Write<BPoint>(origin); 275 Write<bool>(inverse); 276 EndOp(); 277 } catch (status_t& status) { 278 return status; 279 } 280 281 return B_OK; 282} 283 284 285status_t 286PictureDataWriter::WriteSetClipping(const BRegion& region) 287{ 288 // TODO: I don't know if it's compatible with R5's BPicture version 289 try { 290 const int32 numRects = region.CountRects(); 291 if (numRects > 0 && region.Frame().IsValid()) { 292 BeginOp(B_PIC_SET_CLIPPING_RECTS); 293 Write<uint32>(numRects); 294 for (int32 i = 0; i < numRects; i++) 295 Write<BRect>(region.RectAt(i)); 296 297 EndOp(); 298 } else 299 WriteClearClipping(); 300 } catch (status_t& status) { 301 return status; 302 } 303 304 return B_OK; 305} 306 307 308status_t 309PictureDataWriter::WriteClearClipping() 310{ 311 try { 312 BeginOp(B_PIC_CLEAR_CLIPPING_RECTS); 313 EndOp(); 314 } catch (status_t& status) { 315 return status; 316 } 317 318 return B_OK; 319} 320 321 322status_t 323PictureDataWriter::WriteSetHighColor(const rgb_color& color) 324{ 325 try { 326 BeginOp(B_PIC_SET_FORE_COLOR); 327 Write<rgb_color>(color); 328 EndOp(); 329 } catch (status_t& status) { 330 return status; 331 } 332 333 return B_OK; 334} 335 336 337status_t 338PictureDataWriter::WriteSetLowColor(const rgb_color& color) 339{ 340 try { 341 BeginOp(B_PIC_SET_BACK_COLOR); 342 Write<rgb_color>(color); 343 EndOp(); 344 } catch (status_t& status) { 345 return status; 346 } 347 348 return B_OK; 349} 350 351 352status_t 353PictureDataWriter::WriteDrawRect(const BRect& rect, const bool& fill) 354{ 355 try { 356 BeginOp(fill ? B_PIC_FILL_RECT : B_PIC_STROKE_RECT); 357 Write<BRect>(rect); 358 EndOp(); 359 } catch (status_t& status) { 360 return status; 361 } 362 363 return B_OK; 364} 365 366 367status_t 368PictureDataWriter::WriteDrawRoundRect(const BRect& rect, const BPoint& radius, 369 const bool& fill) 370{ 371 try { 372 BeginOp(fill ? B_PIC_FILL_ROUND_RECT : B_PIC_STROKE_ROUND_RECT); 373 Write<BRect>(rect); 374 Write<BPoint>(radius); 375 EndOp(); 376 } catch (status_t& status) { 377 return status; 378 } 379 380 return B_OK; 381} 382 383 384status_t 385PictureDataWriter::WriteDrawEllipse(const BRect& rect, const bool& fill) 386{ 387 try { 388 BeginOp(fill ? B_PIC_FILL_ELLIPSE : B_PIC_STROKE_ELLIPSE); 389 Write<BRect>(rect); 390 EndOp(); 391 } catch (status_t& status) { 392 return status; 393 } 394 395 return B_OK; 396} 397 398 399status_t 400PictureDataWriter::WriteDrawArc(const BPoint& center, const BPoint& radius, 401 const float& startTheta, const float& arcTheta, const bool& fill) 402{ 403 try { 404 BeginOp(fill ? B_PIC_FILL_ARC : B_PIC_STROKE_ARC); 405 Write<BPoint>(center); 406 Write<BPoint>(radius); 407 Write<float>(startTheta); 408 Write<float>(arcTheta); 409 EndOp(); 410 } catch (status_t& status) { 411 return status; 412 } 413 414 return B_OK; 415} 416 417 418status_t 419PictureDataWriter::WriteDrawPolygon(const int32& numPoints, BPoint* points, 420 const bool& isClosed, const bool& fill) 421{ 422 try { 423 BeginOp(fill ? B_PIC_FILL_POLYGON : B_PIC_STROKE_POLYGON); 424 Write<int32>(numPoints); 425 for (int32 i = 0; i < numPoints; i++) 426 Write<BPoint>(points[i]); 427 428 if (!fill) 429 Write<uint8>((uint8)isClosed); 430 431 EndOp(); 432 } catch (status_t& status) { 433 return status; 434 } 435 436 return B_OK; 437} 438 439 440status_t 441PictureDataWriter::WriteDrawBezier(const BPoint points[4], const bool& fill) 442{ 443 try { 444 BeginOp(fill ? B_PIC_FILL_BEZIER : B_PIC_STROKE_BEZIER); 445 for (int32 i = 0; i < 4; i++) 446 Write<BPoint>(points[i]); 447 448 EndOp(); 449 } catch (status_t& status) { 450 return status; 451 } 452 453 return B_OK; 454} 455 456 457status_t 458PictureDataWriter::WriteStrokeLine(const BPoint& start, const BPoint& end) 459{ 460 try { 461 BeginOp(B_PIC_STROKE_LINE); 462 Write<BPoint>(start); 463 Write<BPoint>(end); 464 EndOp(); 465 } catch (status_t& status) { 466 return status; 467 } 468 469 return B_OK; 470} 471 472 473status_t 474PictureDataWriter::WriteDrawString(const BPoint& where, const char* string, 475 const int32& length, const escapement_delta& escapement) 476{ 477 try { 478 BeginOp(B_PIC_SET_PEN_LOCATION); 479 Write<BPoint>(where); 480 EndOp(); 481 482 BeginOp(B_PIC_DRAW_STRING); 483 Write<float>(escapement.space); 484 Write<float>(escapement.nonspace); 485 //WriteData(string, length + 1); 486 // TODO: is string 0 terminated? why is length given? 487 WriteData(string, length); 488 Write<uint8>(0); 489 EndOp(); 490 } catch (status_t& status) { 491 return status; 492 } 493 494 return B_OK; 495} 496 497 498status_t 499PictureDataWriter::WriteDrawString(const char* string, 500 int32 length, const BPoint* locations, int32 locationCount) 501{ 502 try { 503 BeginOp(B_PIC_DRAW_STRING_LOCATIONS); 504 Write<int32>(locationCount); 505 for (int32 i = 0; i < locationCount; i++) { 506 Write<BPoint>(locations[i]); 507 } 508 WriteData(string, length); 509 Write<uint8>(0); 510 EndOp(); 511 } catch (status_t& status) { 512 return status; 513 } 514 515 return B_OK; 516} 517 518 519status_t 520PictureDataWriter::WriteDrawShape(const int32& opCount, const void* opList, 521 const int32& ptCount, const void* ptList, const bool& fill) 522{ 523 try { 524 BeginOp(fill ? B_PIC_FILL_SHAPE : B_PIC_STROKE_SHAPE); 525 Write<int32>(opCount); 526 Write<int32>(ptCount); 527 WriteData(opList, opCount * sizeof(uint32)); 528 WriteData(ptList, ptCount * sizeof(BPoint)); 529 EndOp(); 530 } catch (status_t& status) { 531 return status; 532 } 533 534 return B_OK; 535} 536 537 538status_t 539PictureDataWriter::WriteDrawRectGradient(const BRect& rect, const BGradient& gradient, const bool& fill) 540{ 541 try { 542 BeginOp(fill ? B_PIC_FILL_RECT_GRADIENT : B_PIC_STROKE_RECT_GRADIENT); 543 Write<BRect>(rect); 544 gradient.Flatten(fData); 545 EndOp(); 546 } catch (status_t& status) { 547 return status; 548 } 549 550 return B_OK; 551} 552 553 554status_t 555PictureDataWriter::WriteDrawRoundRectGradient(const BRect& rect, const BPoint& radius, const BGradient& gradient, 556 const bool& fill) 557{ 558 try { 559 BeginOp(fill ? B_PIC_FILL_ROUND_RECT_GRADIENT : B_PIC_STROKE_ROUND_RECT_GRADIENT); 560 Write<BRect>(rect); 561 Write<BPoint>(radius); 562 gradient.Flatten(fData); 563 EndOp(); 564 } catch (status_t& status) { 565 return status; 566 } 567 568 return B_OK; 569} 570 571 572status_t 573PictureDataWriter::WriteDrawBezierGradient(const BPoint points[4], const BGradient& gradient, const bool& fill) 574{ 575 try { 576 BeginOp(fill ? B_PIC_FILL_BEZIER_GRADIENT : B_PIC_STROKE_BEZIER_GRADIENT); 577 for (int32 i = 0; i < 4; i++) 578 Write<BPoint>(points[i]); 579 580 gradient.Flatten(fData); 581 EndOp(); 582 } catch (status_t& status) { 583 return status; 584 } 585 586 return B_OK; 587} 588 589 590status_t 591PictureDataWriter::WriteDrawArcGradient(const BPoint& center, const BPoint& radius, 592 const float& startTheta, const float& arcTheta, const BGradient& gradient, const bool& fill) 593{ 594 try { 595 BeginOp(fill ? B_PIC_FILL_ARC_GRADIENT : B_PIC_STROKE_ARC_GRADIENT); 596 Write<BPoint>(center); 597 Write<BPoint>(radius); 598 Write<float>(startTheta); 599 Write<float>(arcTheta); 600 gradient.Flatten(fData); 601 EndOp(); 602 } catch (status_t& status) { 603 return status; 604 } 605 606 return B_OK; 607} 608 609 610status_t 611PictureDataWriter::WriteDrawEllipseGradient(const BRect& rect, const BGradient& gradient, const bool& fill) 612{ 613 try { 614 BeginOp(fill ? B_PIC_FILL_ELLIPSE_GRADIENT : B_PIC_STROKE_ELLIPSE_GRADIENT); 615 Write<BRect>(rect); 616 gradient.Flatten(fData); 617 EndOp(); 618 } catch (status_t& status) { 619 return status; 620 } 621 622 return B_OK; 623} 624 625 626status_t 627PictureDataWriter::WriteDrawPolygonGradient(const int32& numPoints, BPoint* points, 628 const bool& isClosed, const BGradient& gradient, const bool& fill) 629{ 630 try { 631 BeginOp(fill ? B_PIC_FILL_POLYGON_GRADIENT : B_PIC_STROKE_POLYGON_GRADIENT); 632 Write<int32>(numPoints); 633 for (int32 i = 0; i < numPoints; i++) 634 Write<BPoint>(points[i]); 635 636 if (!fill) 637 Write<uint8>((uint8)isClosed); 638 639 gradient.Flatten(fData); 640 EndOp(); 641 } catch (status_t& status) { 642 return status; 643 } 644 645 return B_OK; 646} 647 648 649status_t 650PictureDataWriter::WriteDrawShapeGradient(const int32& opCount, const void* opList, 651 const int32& ptCount, const void* ptList, const BGradient& gradient, const bool& fill) 652{ 653 try { 654 BeginOp(fill ? B_PIC_FILL_SHAPE_GRADIENT : B_PIC_STROKE_SHAPE_GRADIENT); 655 Write<int32>(opCount); 656 Write<int32>(ptCount); 657 WriteData(opList, opCount * sizeof(uint32)); 658 WriteData(ptList, ptCount * sizeof(BPoint)); 659 gradient.Flatten(fData); 660 EndOp(); 661 } catch (status_t& status) { 662 return status; 663 } 664 665 return B_OK; 666} 667 668 669status_t 670PictureDataWriter::WriteDrawBitmap(const BRect& srcRect, const BRect& dstRect, 671 const int32& width, const int32& height, const int32& bytesPerRow, 672 const int32& colorSpace, const int32& flags, const void* data, 673 const int32& length) 674{ 675 if (length != height * bytesPerRow) 676 debugger("PictureDataWriter::WriteDrawBitmap: invalid length"); 677 try { 678 BeginOp(B_PIC_DRAW_PIXELS); 679 Write<BRect>(srcRect); 680 Write<BRect>(dstRect); 681 Write<int32>(width); 682 Write<int32>(height); 683 Write<int32>(bytesPerRow); 684 Write<int32>(colorSpace); 685 Write<int32>(flags); 686 WriteData(data, length); 687 EndOp(); 688 } catch (status_t& status) { 689 return status; 690 } 691 692 return B_OK; 693} 694 695 696status_t 697PictureDataWriter::WriteDrawPicture(const BPoint& where, const int32& token) 698{ 699 // TODO: I'm not sure about this function. I think we need 700 // to attach the picture data too. 701 // The token won't be sufficient in many cases (for example, when 702 // we archive/flatten the picture. 703 try { 704 BeginOp(B_PIC_DRAW_PICTURE); 705 Write<BPoint>(where); 706 Write<int32>(token); 707 EndOp(); 708 } catch (status_t& status) { 709 return status; 710 } 711 712 return B_OK; 713} 714 715 716status_t 717PictureDataWriter::WriteSetFontFamily(const font_family family) 718{ 719 try { 720 BeginOp(B_PIC_SET_FONT_FAMILY); 721 WriteData(family, strlen(family)); 722 Write<uint8>(0); 723 EndOp(); 724 } catch (status_t& status) { 725 return status; 726 } 727 728 return B_OK; 729} 730 731 732status_t 733PictureDataWriter::WriteSetFontStyle(const font_style style) 734{ 735 try { 736 BeginOp(B_PIC_SET_FONT_STYLE); 737 WriteData(style, strlen(style)); 738 Write<uint8>(0); 739 EndOp(); 740 } catch (status_t& status) { 741 return status; 742 } 743 744 return B_OK; 745} 746 747 748status_t 749PictureDataWriter::WriteSetFontSpacing(const int32& spacing) 750{ 751 try { 752 BeginOp(B_PIC_SET_FONT_SPACING); 753 Write<int32>(spacing); 754 EndOp(); 755 } catch (status_t& status) { 756 return status; 757 } 758 759 return B_OK; 760} 761 762 763status_t 764PictureDataWriter::WriteSetFontSize(const float& size) 765{ 766 try { 767 BeginOp(B_PIC_SET_FONT_SIZE); 768 Write<float>(size); 769 EndOp(); 770 } catch (status_t& status) { 771 return status; 772 } 773 774 return B_OK; 775} 776 777 778status_t 779PictureDataWriter::WriteSetFontRotation(const float& rotation) 780{ 781 try { 782 BeginOp(B_PIC_SET_FONT_ROTATE); 783 Write<float>(rotation); 784 EndOp(); 785 } catch (status_t& status) { 786 return status; 787 } 788 789 return B_OK; 790} 791 792 793status_t 794PictureDataWriter::WriteSetFontEncoding(const int32& encoding) 795{ 796 try { 797 BeginOp(B_PIC_SET_FONT_ENCODING); 798 Write<int32>(encoding); 799 EndOp(); 800 } catch (status_t& status) { 801 return status; 802 } 803 804 return B_OK; 805} 806 807 808status_t 809PictureDataWriter::WriteSetFontFlags(const int32& flags) 810{ 811 try { 812 BeginOp(B_PIC_SET_FONT_FLAGS); 813 Write<int32>(flags); 814 EndOp(); 815 } catch (status_t& status) { 816 return status; 817 } 818 819 return B_OK; 820} 821 822 823status_t 824PictureDataWriter::WriteSetFontShear(const float& shear) 825{ 826 try { 827 BeginOp(B_PIC_SET_FONT_SHEAR); 828 Write<float>(shear); 829 EndOp(); 830 } catch (status_t& status) { 831 return status; 832 } 833 834 return B_OK; 835} 836 837 838status_t 839PictureDataWriter::WriteSetFontFace(const int32& face) 840{ 841 try { 842 BeginOp(B_PIC_SET_FONT_FACE); 843 Write<int32>(face); 844 EndOp(); 845 } catch (status_t& status) { 846 return status; 847 } 848 849 return B_OK; 850} 851 852 853status_t 854PictureDataWriter::WritePushState() 855{ 856 try { 857 BeginOp(B_PIC_PUSH_STATE); 858 EndOp(); 859 } catch (status_t& status) { 860 return status; 861 } 862 863 return B_OK; 864} 865 866 867status_t 868PictureDataWriter::WritePopState() 869{ 870 try { 871 BeginOp(B_PIC_POP_STATE); 872 EndOp(); 873 } catch (status_t& status) { 874 return status; 875 } 876 877 return B_OK; 878} 879 880 881status_t 882PictureDataWriter::WriteBlendLayer(Layer* layer) 883{ 884 try { 885 BeginOp(B_PIC_BLEND_LAYER); 886 Write<Layer*>(layer); 887 EndOp(); 888 } catch (status_t& status) { 889 return status; 890 } 891 892 return B_OK; 893} 894 895 896status_t 897PictureDataWriter::WriteClipToRect(const BRect& rect, bool inverse) 898{ 899 try { 900 BeginOp(B_PIC_CLIP_TO_RECT); 901 Write<bool>(inverse); 902 Write<BRect>(rect); 903 EndOp(); 904 } catch (status_t& status) { 905 return status; 906 } 907 908 return B_OK; 909} 910 911 912status_t 913PictureDataWriter::WriteClipToShape(int32 opCount, const void* opList, 914 int32 ptCount, const void* ptList, bool inverse) 915{ 916 try { 917 BeginOp(B_PIC_CLIP_TO_SHAPE); 918 Write<bool>(inverse); 919 Write<int32>(opCount); 920 Write<int32>(ptCount); 921 WriteData(opList, opCount * sizeof(uint32)); 922 WriteData(ptList, ptCount * sizeof(BPoint)); 923 EndOp(); 924 } catch (status_t& status) { 925 return status; 926 } 927 928 return B_OK; 929} 930 931 932// private 933void 934PictureDataWriter::BeginOp(const int16& op) 935{ 936 if (fData == NULL) 937 THROW_ERROR(B_NO_INIT); 938 939 fStack.push(fData->Position()); 940 fData->Write(&op, sizeof(op)); 941 942 // Init the size of the opcode block to 0 943 int32 size = 0; 944 fData->Write(&size, sizeof(size)); 945} 946 947 948void 949PictureDataWriter::EndOp() 950{ 951 if (fData == NULL) 952 THROW_ERROR(B_NO_INIT); 953 954 off_t curPos = fData->Position(); 955 off_t stackPos = fStack.top(); 956 fStack.pop(); 957 958 // The size of the op is calculated like this: 959 // current position on the stream minus the position on the stack, 960 // minus the space occupied by the op code itself (int16) 961 // and the space occupied by the size field (int32) 962 int32 size = curPos - stackPos - sizeof(int32) - sizeof(int16); 963 964 // Size was set to 0 in BeginOp() 965 // Now we overwrite it with the correct value 966 fData->Seek(stackPos + sizeof(int16), SEEK_SET); 967 fData->Write(&size, sizeof(size)); 968 fData->Seek(curPos, SEEK_SET); 969} 970 971 972void 973PictureDataWriter::WriteData(const void* data, size_t size) 974{ 975 ssize_t result = fData->Write(data, size); 976 if (result < 0) 977 THROW_ERROR(result); 978 979 if ((size_t)result != size) 980 THROW_ERROR(B_IO_ERROR); 981} 982