xref: /haiku/src/kits/interface/PictureDataWriter.cpp (revision 4399ec510de9714e2440cdae346d00c286d69906)
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