2 * Copyright 2006-2015 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Stefano Ceccherini, stefano.ceccherini@gmail.com
7 * Julian Harnath, <julian.harnath@rwth-achen.de>
10 #include <PictureDataWriter.h>
20 #include <PictureProtocol.h>
22 #define THROW_ERROR(error) throw (status_t)(error)
25 // TODO: Review writing of strings. AFAIK in the picture data format
26 // They are not supposed to be NULL terminated
27 // (at least, it's not mandatory) so we should write their size too.
28 PictureDataWriter::PictureDataWriter()
35 PictureDataWriter::PictureDataWriter(BPositionIO
* data
)
42 PictureDataWriter::~PictureDataWriter()
48 PictureDataWriter::SetTo(BPositionIO
* data
)
60 PictureDataWriter::WriteSetOrigin(const BPoint
& point
)
63 BeginOp(B_PIC_SET_ORIGIN
);
66 } catch (status_t
& status
) {
75 PictureDataWriter::WriteInvertRect(const BRect
& rect
)
78 WriteSetDrawingMode(B_OP_INVERT
);
80 BeginOp(B_PIC_FILL_RECT
);
84 WriteSetDrawingMode(B_OP_COPY
);
85 } catch (status_t
& status
) {
94 PictureDataWriter::WriteSetDrawingMode(const drawing_mode
& mode
)
97 BeginOp(B_PIC_SET_DRAWING_MODE
);
98 Write
<int16
>((int16
)mode
);
100 } catch (status_t
& status
) {
109 PictureDataWriter::WriteSetPenLocation(const BPoint
& point
)
112 BeginOp(B_PIC_SET_PEN_LOCATION
);
113 Write
<BPoint
>(point
);
115 } catch (status_t
& status
) {
124 PictureDataWriter::WriteSetPenSize(const float& penSize
)
127 BeginOp(B_PIC_SET_PEN_SIZE
);
128 Write
<float>(penSize
);
130 } catch (status_t
& status
) {
139 PictureDataWriter::WriteSetLineMode(const cap_mode
& cap
, const join_mode
& join
,
140 const float& miterLimit
)
143 BeginOp(B_PIC_SET_LINE_MODE
);
144 Write
<int16
>((int16
)cap
);
145 Write
<int16
>((int16
)join
);
146 Write
<float>(miterLimit
);
148 } catch (status_t
& status
) {
157 PictureDataWriter::WriteSetScale(const float& scale
)
160 BeginOp(B_PIC_SET_SCALE
);
163 } catch (status_t
& status
) {
172 PictureDataWriter::WriteSetTransform(BAffineTransform transform
)
175 BeginOp(B_PIC_SET_TRANSFORM
);
176 Write
<BAffineTransform
>(transform
);
178 } catch (status_t
& status
) {
187 PictureDataWriter::WriteTranslateBy(double x
, double y
)
190 BeginOp(B_PIC_AFFINE_TRANSLATE
);
194 } catch (status_t
& status
) {
203 PictureDataWriter::WriteScaleBy(double x
, double y
)
206 BeginOp(B_PIC_AFFINE_SCALE
);
210 } catch (status_t
& status
) {
219 PictureDataWriter::WriteRotateBy(double angleRadians
)
222 BeginOp(B_PIC_AFFINE_ROTATE
);
223 Write
<double>(angleRadians
);
225 } catch (status_t
& status
) {
234 PictureDataWriter::WriteSetPattern(const ::pattern
& pattern
)
237 BeginOp(B_PIC_SET_STIPLE_PATTERN
);
238 Write
< ::pattern
>(pattern
);
240 } catch (status_t
& status
) {
249 PictureDataWriter::WriteClipToPicture(int32 pictureToken
,
250 const BPoint
& origin
, bool inverse
)
252 // TODO: I don't know if it's compatible with R5's BPicture version
254 BeginOp(B_PIC_CLIP_TO_PICTURE
);
255 Write
<int32
>(pictureToken
);
256 Write
<BPoint
>(origin
);
257 Write
<bool>(inverse
);
259 } catch (status_t
& status
) {
268 PictureDataWriter::WriteSetClipping(const BRegion
& region
)
270 // TODO: I don't know if it's compatible with R5's BPicture version
272 const int32 numRects
= region
.CountRects();
273 if (numRects
> 0 && region
.Frame().IsValid()) {
274 BeginOp(B_PIC_SET_CLIPPING_RECTS
);
275 Write
<uint32
>(numRects
);
276 for (int32 i
= 0; i
< numRects
; i
++)
277 Write
<BRect
>(region
.RectAt(i
));
281 WriteClearClipping();
282 } catch (status_t
& status
) {
291 PictureDataWriter::WriteClearClipping()
294 BeginOp(B_PIC_CLEAR_CLIPPING_RECTS
);
296 } catch (status_t
& status
) {
305 PictureDataWriter::WriteSetHighColor(const rgb_color
& color
)
308 BeginOp(B_PIC_SET_FORE_COLOR
);
309 Write
<rgb_color
>(color
);
311 } catch (status_t
& status
) {
320 PictureDataWriter::WriteSetLowColor(const rgb_color
& color
)
323 BeginOp(B_PIC_SET_BACK_COLOR
);
324 Write
<rgb_color
>(color
);
326 } catch (status_t
& status
) {
335 PictureDataWriter::WriteDrawRect(const BRect
& rect
, const bool& fill
)
338 BeginOp(fill
? B_PIC_FILL_RECT
: B_PIC_STROKE_RECT
);
341 } catch (status_t
& status
) {
350 PictureDataWriter::WriteDrawRoundRect(const BRect
& rect
, const BPoint
& radius
,
354 BeginOp(fill
? B_PIC_FILL_ROUND_RECT
: B_PIC_STROKE_ROUND_RECT
);
356 Write
<BPoint
>(radius
);
358 } catch (status_t
& status
) {
367 PictureDataWriter::WriteDrawEllipse(const BRect
& rect
, const bool& fill
)
370 BeginOp(fill
? B_PIC_FILL_ELLIPSE
: B_PIC_STROKE_ELLIPSE
);
373 } catch (status_t
& status
) {
382 PictureDataWriter::WriteDrawArc(const BPoint
& center
, const BPoint
& radius
,
383 const float& startTheta
, const float& arcTheta
, const bool& fill
)
386 BeginOp(fill
? B_PIC_FILL_ARC
: B_PIC_STROKE_ARC
);
387 Write
<BPoint
>(center
);
388 Write
<BPoint
>(radius
);
389 Write
<float>(startTheta
);
390 Write
<float>(arcTheta
);
392 } catch (status_t
& status
) {
401 PictureDataWriter::WriteDrawPolygon(const int32
& numPoints
, BPoint
* points
,
402 const bool& isClosed
, const bool& fill
)
405 BeginOp(fill
? B_PIC_FILL_POLYGON
: B_PIC_STROKE_POLYGON
);
406 Write
<int32
>(numPoints
);
407 for (int32 i
= 0; i
< numPoints
; i
++)
408 Write
<BPoint
>(points
[i
]);
411 Write
<uint8
>((uint8
)isClosed
);
414 } catch (status_t
& status
) {
423 PictureDataWriter::WriteDrawBezier(const BPoint points
[4], const bool& fill
)
426 BeginOp(fill
? B_PIC_FILL_BEZIER
: B_PIC_STROKE_BEZIER
);
427 for (int32 i
= 0; i
< 4; i
++)
428 Write
<BPoint
>(points
[i
]);
431 } catch (status_t
& status
) {
440 PictureDataWriter::WriteStrokeLine(const BPoint
& start
, const BPoint
& end
)
443 BeginOp(B_PIC_STROKE_LINE
);
444 Write
<BPoint
>(start
);
447 } catch (status_t
& status
) {
456 PictureDataWriter::WriteDrawString(const BPoint
& where
, const char* string
,
457 const int32
& length
, const escapement_delta
& escapement
)
460 BeginOp(B_PIC_SET_PEN_LOCATION
);
461 Write
<BPoint
>(where
);
464 BeginOp(B_PIC_DRAW_STRING
);
465 Write
<float>(escapement
.space
);
466 Write
<float>(escapement
.nonspace
);
467 //WriteData(string, length + 1);
468 // TODO: is string 0 terminated? why is length given?
469 WriteData(string
, length
);
472 } catch (status_t
& status
) {
481 PictureDataWriter::WriteDrawShape(const int32
& opCount
, const void* opList
,
482 const int32
& ptCount
, const void* ptList
, const bool& fill
)
485 BeginOp(fill
? B_PIC_FILL_SHAPE
: B_PIC_STROKE_SHAPE
);
486 Write
<int32
>(opCount
);
487 Write
<int32
>(ptCount
);
488 WriteData(opList
, opCount
* sizeof(uint32
));
489 WriteData(ptList
, ptCount
* sizeof(BPoint
));
491 } catch (status_t
& status
) {
500 PictureDataWriter::WriteDrawBitmap(const BRect
& srcRect
, const BRect
& dstRect
,
501 const int32
& width
, const int32
& height
, const int32
& bytesPerRow
,
502 const int32
& colorSpace
, const int32
& flags
, const void* data
,
505 if (length
!= height
* bytesPerRow
)
506 debugger("PictureDataWriter::WriteDrawBitmap: invalid length");
508 BeginOp(B_PIC_DRAW_PIXELS
);
509 Write
<BRect
>(srcRect
);
510 Write
<BRect
>(dstRect
);
512 Write
<int32
>(height
);
513 Write
<int32
>(bytesPerRow
);
514 Write
<int32
>(colorSpace
);
516 WriteData(data
, length
);
518 } catch (status_t
& status
) {
527 PictureDataWriter::WriteDrawPicture(const BPoint
& where
, const int32
& token
)
529 // TODO: I'm not sure about this function. I think we need
530 // to attach the picture data too.
531 // The token won't be sufficient in many cases (for example, when
532 // we archive/flatten the picture.
534 BeginOp(B_PIC_DRAW_PICTURE
);
535 Write
<BPoint
>(where
);
538 } catch (status_t
& status
) {
547 PictureDataWriter::WriteSetFontFamily(const font_family family
)
550 BeginOp(B_PIC_SET_FONT_FAMILY
);
551 WriteData(family
, strlen(family
));
554 } catch (status_t
& status
) {
563 PictureDataWriter::WriteSetFontStyle(const font_style style
)
566 BeginOp(B_PIC_SET_FONT_STYLE
);
567 WriteData(style
, strlen(style
));
570 } catch (status_t
& status
) {
579 PictureDataWriter::WriteSetFontSpacing(const int32
& spacing
)
582 BeginOp(B_PIC_SET_FONT_SPACING
);
583 Write
<int32
>(spacing
);
585 } catch (status_t
& status
) {
594 PictureDataWriter::WriteSetFontSize(const float& size
)
597 BeginOp(B_PIC_SET_FONT_SIZE
);
600 } catch (status_t
& status
) {
609 PictureDataWriter::WriteSetFontRotation(const float& rotation
)
612 BeginOp(B_PIC_SET_FONT_ROTATE
);
613 Write
<float>(rotation
);
615 } catch (status_t
& status
) {
624 PictureDataWriter::WriteSetFontEncoding(const int32
& encoding
)
627 BeginOp(B_PIC_SET_FONT_ENCODING
);
628 Write
<int32
>(encoding
);
630 } catch (status_t
& status
) {
639 PictureDataWriter::WriteSetFontFlags(const int32
& flags
)
642 BeginOp(B_PIC_SET_FONT_FLAGS
);
645 } catch (status_t
& status
) {
654 PictureDataWriter::WriteSetFontShear(const float& shear
)
657 BeginOp(B_PIC_SET_FONT_SHEAR
);
660 } catch (status_t
& status
) {
669 PictureDataWriter::WriteSetFontFace(const int32
& face
)
672 BeginOp(B_PIC_SET_FONT_FACE
);
675 } catch (status_t
& status
) {
684 PictureDataWriter::WritePushState()
687 BeginOp(B_PIC_PUSH_STATE
);
689 } catch (status_t
& status
) {
698 PictureDataWriter::WritePopState()
701 BeginOp(B_PIC_POP_STATE
);
703 } catch (status_t
& status
) {
712 PictureDataWriter::WriteBlendLayer(Layer
* layer
)
715 BeginOp(B_PIC_BLEND_LAYER
);
716 Write
<Layer
*>(layer
);
718 } catch (status_t
& status
) {
727 PictureDataWriter::WriteClipToRect(const BRect
& rect
, bool inverse
)
730 BeginOp(B_PIC_CLIP_TO_RECT
);
731 Write
<bool>(inverse
);
734 } catch (status_t
& status
) {
743 PictureDataWriter::WriteClipToShape(int32 opCount
, const void* opList
,
744 int32 ptCount
, const void* ptList
, bool inverse
)
747 BeginOp(B_PIC_CLIP_TO_SHAPE
);
748 Write
<bool>(inverse
);
749 Write
<int32
>(opCount
);
750 Write
<int32
>(ptCount
);
751 WriteData(opList
, opCount
* sizeof(uint32
));
752 WriteData(ptList
, ptCount
* sizeof(BPoint
));
754 } catch (status_t
& status
) {
764 PictureDataWriter::BeginOp(const int16
& op
)
767 THROW_ERROR(B_NO_INIT
);
769 fStack
.push(fData
->Position());
770 fData
->Write(&op
, sizeof(op
));
772 // Init the size of the opcode block to 0
774 fData
->Write(&size
, sizeof(size
));
779 PictureDataWriter::EndOp()
782 THROW_ERROR(B_NO_INIT
);
784 off_t curPos
= fData
->Position();
785 off_t stackPos
= fStack
.top();
788 // The size of the op is calculated like this:
789 // current position on the stream minus the position on the stack,
790 // minus the space occupied by the op code itself (int16)
791 // and the space occupied by the size field (int32)
792 int32 size
= curPos
- stackPos
- sizeof(int32
) - sizeof(int16
);
794 // Size was set to 0 in BeginOp()
795 // Now we overwrite it with the correct value
796 fData
->Seek(stackPos
+ sizeof(int16
), SEEK_SET
);
797 fData
->Write(&size
, sizeof(size
));
798 fData
->Seek(curPos
, SEEK_SET
);
803 PictureDataWriter::WriteData(const void* data
, size_t size
)
805 ssize_t result
= fData
->Write(data
, size
);
809 if ((size_t)result
!= size
)
810 THROW_ERROR(B_IO_ERROR
);