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.
PictureDataWriter()30 PictureDataWriter::PictureDataWriter()
31 :
32 fData(NULL)
33 {
34 }
35
36
PictureDataWriter(BPositionIO * data)37 PictureDataWriter::PictureDataWriter(BPositionIO* data)
38 :
39 fData(data)
40 {
41 }
42
43
~PictureDataWriter()44 PictureDataWriter::~PictureDataWriter()
45 {
46 }
47
48
49 status_t
SetTo(BPositionIO * data)50 PictureDataWriter::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
61 status_t
WriteSetOrigin(const BPoint & point)62 PictureDataWriter::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
76 status_t
WriteInvertRect(const BRect & rect)77 PictureDataWriter::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
96 status_t
WriteSetDrawingMode(const drawing_mode & mode)97 PictureDataWriter::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
111 status_t
WriteSetPenLocation(const BPoint & point)112 PictureDataWriter::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
126 status_t
WriteSetPenSize(const float & penSize)127 PictureDataWriter::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
141 status_t
WriteSetLineMode(const cap_mode & cap,const join_mode & join,const float & miterLimit)142 PictureDataWriter::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
159 status_t
WriteSetFillRule(int32 fillRule)160 PictureDataWriter::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
174 status_t
WriteSetScale(const float & scale)175 PictureDataWriter::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
189 status_t
WriteSetTransform(BAffineTransform transform)190 PictureDataWriter::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
204 status_t
WriteTranslateBy(double x,double y)205 PictureDataWriter::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
220 status_t
WriteScaleBy(double x,double y)221 PictureDataWriter::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
236 status_t
WriteRotateBy(double angleRadians)237 PictureDataWriter::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
251 status_t
WriteSetPattern(const::pattern & pattern)252 PictureDataWriter::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
266 status_t
WriteClipToPicture(int32 pictureToken,const BPoint & origin,bool inverse)267 PictureDataWriter::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
285 status_t
WriteSetClipping(const BRegion & region)286 PictureDataWriter::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
308 status_t
WriteClearClipping()309 PictureDataWriter::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
322 status_t
WriteSetHighColor(const rgb_color & color)323 PictureDataWriter::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
337 status_t
WriteSetLowColor(const rgb_color & color)338 PictureDataWriter::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
352 status_t
WriteDrawRect(const BRect & rect,const bool & fill)353 PictureDataWriter::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
367 status_t
WriteDrawRoundRect(const BRect & rect,const BPoint & radius,const bool & fill)368 PictureDataWriter::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
384 status_t
WriteDrawEllipse(const BRect & rect,const bool & fill)385 PictureDataWriter::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
399 status_t
WriteDrawArc(const BPoint & center,const BPoint & radius,const float & startTheta,const float & arcTheta,const bool & fill)400 PictureDataWriter::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
418 status_t
WriteDrawPolygon(const int32 & numPoints,BPoint * points,const bool & isClosed,const bool & fill)419 PictureDataWriter::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
440 status_t
WriteDrawBezier(const BPoint points[4],const bool & fill)441 PictureDataWriter::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
457 status_t
WriteStrokeLine(const BPoint & start,const BPoint & end)458 PictureDataWriter::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
473 status_t
WriteDrawString(const BPoint & where,const char * string,const int32 & length,const escapement_delta & escapement)474 PictureDataWriter::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
498 status_t
WriteDrawString(const char * string,int32 length,const BPoint * locations,int32 locationCount)499 PictureDataWriter::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
519 status_t
WriteDrawShape(const int32 & opCount,const void * opList,const int32 & ptCount,const void * ptList,const bool & fill)520 PictureDataWriter::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
538 status_t
WriteDrawRectGradient(const BRect & rect,const BGradient & gradient,const bool & fill)539 PictureDataWriter::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
554 status_t
WriteDrawRoundRectGradient(const BRect & rect,const BPoint & radius,const BGradient & gradient,const bool & fill)555 PictureDataWriter::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
572 status_t
WriteDrawBezierGradient(const BPoint points[4],const BGradient & gradient,const bool & fill)573 PictureDataWriter::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
590 status_t
WriteDrawArcGradient(const BPoint & center,const BPoint & radius,const float & startTheta,const float & arcTheta,const BGradient & gradient,const bool & fill)591 PictureDataWriter::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
610 status_t
WriteDrawEllipseGradient(const BRect & rect,const BGradient & gradient,const bool & fill)611 PictureDataWriter::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
626 status_t
WriteDrawPolygonGradient(const int32 & numPoints,BPoint * points,const bool & isClosed,const BGradient & gradient,const bool & fill)627 PictureDataWriter::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
649 status_t
WriteDrawShapeGradient(const int32 & opCount,const void * opList,const int32 & ptCount,const void * ptList,const BGradient & gradient,const bool & fill)650 PictureDataWriter::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
669 status_t
WriteDrawBitmap(const BRect & srcRect,const BRect & dstRect,const int32 & width,const int32 & height,const int32 & bytesPerRow,const int32 & colorSpace,const int32 & flags,const void * data,const int32 & length)670 PictureDataWriter::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
696 status_t
WriteDrawPicture(const BPoint & where,const int32 & token)697 PictureDataWriter::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
716 status_t
WriteSetFontFamily(const font_family family)717 PictureDataWriter::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
732 status_t
WriteSetFontStyle(const font_style style)733 PictureDataWriter::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
748 status_t
WriteSetFontSpacing(const int32 & spacing)749 PictureDataWriter::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
763 status_t
WriteSetFontSize(const float & size)764 PictureDataWriter::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
778 status_t
WriteSetFontRotation(const float & rotation)779 PictureDataWriter::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
793 status_t
WriteSetFontEncoding(const int32 & encoding)794 PictureDataWriter::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
808 status_t
WriteSetFontFlags(const int32 & flags)809 PictureDataWriter::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
823 status_t
WriteSetFontShear(const float & shear)824 PictureDataWriter::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
838 status_t
WriteSetFontFace(const int32 & face)839 PictureDataWriter::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
853 status_t
WritePushState()854 PictureDataWriter::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
867 status_t
WritePopState()868 PictureDataWriter::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
881 status_t
WriteBlendLayer(Layer * layer)882 PictureDataWriter::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
896 status_t
WriteClipToRect(const BRect & rect,bool inverse)897 PictureDataWriter::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
912 status_t
WriteClipToShape(int32 opCount,const void * opList,int32 ptCount,const void * ptList,bool inverse)913 PictureDataWriter::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
933 void
BeginOp(const int16 & op)934 PictureDataWriter::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
948 void
EndOp()949 PictureDataWriter::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
972 void
WriteData(const void * data,size_t size)973 PictureDataWriter::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