2 * Copyright 2006-2009 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Stefano Ceccherini, stefano.ceccherini@gmail.com
9 #include <PictureDataWriter.h>
19 #include <PictureProtocol.h>
21 #define THROW_ERROR(error) throw (status_t)(error)
24 // TODO: Review writing of strings. AFAIK in the picture data format
25 // They are not supposed to be NULL terminated
26 // (at least, it's not mandatory) so we should write their size too.
27 PictureDataWriter::PictureDataWriter()
34 PictureDataWriter::PictureDataWriter(BPositionIO
* data
)
41 PictureDataWriter::~PictureDataWriter()
47 PictureDataWriter::SetTo(BPositionIO
* data
)
59 PictureDataWriter::WriteSetOrigin(const BPoint
& point
)
62 BeginOp(B_PIC_SET_ORIGIN
);
65 } catch (status_t
& status
) {
74 PictureDataWriter::WriteInvertRect(const BRect
& rect
)
77 WriteSetDrawingMode(B_OP_INVERT
);
79 BeginOp(B_PIC_FILL_RECT
);
83 WriteSetDrawingMode(B_OP_COPY
);
84 } catch (status_t
& status
) {
93 PictureDataWriter::WriteSetDrawingMode(const drawing_mode
& mode
)
96 BeginOp(B_PIC_SET_DRAWING_MODE
);
97 Write
<int16
>((int16
)mode
);
99 } catch (status_t
& status
) {
108 PictureDataWriter::WriteSetPenLocation(const BPoint
& point
)
111 BeginOp(B_PIC_SET_PEN_LOCATION
);
112 Write
<BPoint
>(point
);
114 } catch (status_t
& status
) {
123 PictureDataWriter::WriteSetPenSize(const float& penSize
)
126 BeginOp(B_PIC_SET_PEN_SIZE
);
127 Write
<float>(penSize
);
129 } catch (status_t
& status
) {
138 PictureDataWriter::WriteSetLineMode(const cap_mode
& cap
, const join_mode
& join
,
139 const float& miterLimit
)
142 BeginOp(B_PIC_SET_LINE_MODE
);
143 Write
<int16
>((int16
)cap
);
144 Write
<int16
>((int16
)join
);
145 Write
<float>(miterLimit
);
147 } catch (status_t
& status
) {
156 PictureDataWriter::WriteSetScale(const float& scale
)
159 BeginOp(B_PIC_SET_SCALE
);
162 } catch (status_t
& status
) {
171 PictureDataWriter::WriteSetTransform(BAffineTransform transform
)
174 BeginOp(B_PIC_SET_TRANSFORM
);
175 Write
<BAffineTransform
>(transform
);
177 } catch (status_t
& status
) {
186 PictureDataWriter::WriteSetPattern(const ::pattern
& pattern
)
189 BeginOp(B_PIC_SET_STIPLE_PATTERN
);
190 Write
< ::pattern
>(pattern
);
192 } catch (status_t
& status
) {
201 PictureDataWriter::WriteSetClipping(const BRegion
& region
)
203 // TODO: I don't know if it's compatible with R5's BPicture version
205 const int32 numRects
= region
.CountRects();
206 if (numRects
> 0 && region
.Frame().IsValid()) {
207 BeginOp(B_PIC_SET_CLIPPING_RECTS
);
208 Write
<uint32
>(numRects
);
209 for (int32 i
= 0; i
< numRects
; i
++)
210 Write
<BRect
>(region
.RectAt(i
));
214 WriteClearClipping();
215 } catch (status_t
& status
) {
224 PictureDataWriter::WriteClearClipping()
227 BeginOp(B_PIC_CLEAR_CLIPPING_RECTS
);
229 } catch (status_t
& status
) {
238 PictureDataWriter::WriteSetHighColor(const rgb_color
& color
)
241 BeginOp(B_PIC_SET_FORE_COLOR
);
242 Write
<rgb_color
>(color
);
244 } catch (status_t
& status
) {
253 PictureDataWriter::WriteSetLowColor(const rgb_color
& color
)
256 BeginOp(B_PIC_SET_BACK_COLOR
);
257 Write
<rgb_color
>(color
);
259 } catch (status_t
& status
) {
268 PictureDataWriter::WriteDrawRect(const BRect
& rect
, const bool& fill
)
271 BeginOp(fill
? B_PIC_FILL_RECT
: B_PIC_STROKE_RECT
);
274 } catch (status_t
& status
) {
283 PictureDataWriter::WriteDrawRoundRect(const BRect
& rect
, const BPoint
& radius
,
287 BeginOp(fill
? B_PIC_FILL_ROUND_RECT
: B_PIC_STROKE_ROUND_RECT
);
289 Write
<BPoint
>(radius
);
291 } catch (status_t
& status
) {
300 PictureDataWriter::WriteDrawEllipse(const BRect
& rect
, const bool& fill
)
303 BeginOp(fill
? B_PIC_FILL_ELLIPSE
: B_PIC_STROKE_ELLIPSE
);
306 } catch (status_t
& status
) {
315 PictureDataWriter::WriteDrawArc(const BPoint
& center
, const BPoint
& radius
,
316 const float& startTheta
, const float& arcTheta
, const bool& fill
)
319 BeginOp(fill
? B_PIC_FILL_ARC
: B_PIC_STROKE_ARC
);
320 Write
<BPoint
>(center
);
321 Write
<BPoint
>(radius
);
322 Write
<float>(startTheta
);
323 Write
<float>(arcTheta
);
325 } catch (status_t
& status
) {
334 PictureDataWriter::WriteDrawPolygon(const int32
& numPoints
, BPoint
* points
,
335 const bool& isClosed
, const bool& fill
)
338 BeginOp(fill
? B_PIC_FILL_POLYGON
: B_PIC_STROKE_POLYGON
);
339 Write
<int32
>(numPoints
);
340 for (int32 i
= 0; i
< numPoints
; i
++)
341 Write
<BPoint
>(points
[i
]);
344 Write
<uint8
>((uint8
)isClosed
);
347 } catch (status_t
& status
) {
356 PictureDataWriter::WriteDrawBezier(const BPoint points
[4], const bool& fill
)
359 BeginOp(fill
? B_PIC_FILL_BEZIER
: B_PIC_STROKE_BEZIER
);
360 for (int32 i
= 0; i
< 4; i
++)
361 Write
<BPoint
>(points
[i
]);
364 } catch (status_t
& status
) {
373 PictureDataWriter::WriteStrokeLine(const BPoint
& start
, const BPoint
& end
)
376 BeginOp(B_PIC_STROKE_LINE
);
377 Write
<BPoint
>(start
);
380 } catch (status_t
& status
) {
389 PictureDataWriter::WriteDrawString(const BPoint
& where
, const char* string
,
390 const int32
& length
, const escapement_delta
& escapement
)
393 BeginOp(B_PIC_SET_PEN_LOCATION
);
394 Write
<BPoint
>(where
);
397 BeginOp(B_PIC_DRAW_STRING
);
398 Write
<float>(escapement
.space
);
399 Write
<float>(escapement
.nonspace
);
400 //WriteData(string, length + 1);
401 // TODO: is string 0 terminated? why is length given?
402 WriteData(string
, length
);
405 } catch (status_t
& status
) {
414 PictureDataWriter::WriteDrawShape(const int32
& opCount
, const void* opList
,
415 const int32
& ptCount
, const void* ptList
, const bool& fill
)
418 BeginOp(fill
? B_PIC_FILL_SHAPE
: B_PIC_STROKE_SHAPE
);
419 Write
<int32
>(opCount
);
420 Write
<int32
>(ptCount
);
421 WriteData(opList
, opCount
* sizeof(uint32
));
422 WriteData(ptList
, ptCount
* sizeof(BPoint
));
424 } catch (status_t
& status
) {
433 PictureDataWriter::WriteDrawBitmap(const BRect
& srcRect
, const BRect
& dstRect
,
434 const int32
& width
, const int32
& height
, const int32
& bytesPerRow
,
435 const int32
& colorSpace
, const int32
& flags
, const void* data
,
438 if (length
!= height
* bytesPerRow
)
439 debugger("PictureDataWriter::WriteDrawBitmap: invalid length");
441 BeginOp(B_PIC_DRAW_PIXELS
);
442 Write
<BRect
>(srcRect
);
443 Write
<BRect
>(dstRect
);
445 Write
<int32
>(height
);
446 Write
<int32
>(bytesPerRow
);
447 Write
<int32
>(colorSpace
);
449 WriteData(data
, length
);
451 } catch (status_t
& status
) {
460 PictureDataWriter::WriteDrawPicture(const BPoint
& where
, const int32
& token
)
462 // TODO: I'm not sure about this function. I think we need
463 // to attach the picture data too.
464 // The token won't be sufficient in many cases (for example, when
465 // we archive/flatten the picture.
467 BeginOp(B_PIC_DRAW_PICTURE
);
468 Write
<BPoint
>(where
);
471 } catch (status_t
& status
) {
480 PictureDataWriter::WriteSetFontFamily(const font_family family
)
483 BeginOp(B_PIC_SET_FONT_FAMILY
);
484 WriteData(family
, strlen(family
));
487 } catch (status_t
& status
) {
496 PictureDataWriter::WriteSetFontStyle(const font_style style
)
499 BeginOp(B_PIC_SET_FONT_STYLE
);
500 WriteData(style
, strlen(style
));
503 } catch (status_t
& status
) {
512 PictureDataWriter::WriteSetFontSpacing(const int32
& spacing
)
515 BeginOp(B_PIC_SET_FONT_SPACING
);
516 Write
<int32
>(spacing
);
518 } catch (status_t
& status
) {
527 PictureDataWriter::WriteSetFontSize(const float& size
)
530 BeginOp(B_PIC_SET_FONT_SIZE
);
533 } catch (status_t
& status
) {
542 PictureDataWriter::WriteSetFontRotation(const float& rotation
)
545 BeginOp(B_PIC_SET_FONT_ROTATE
);
546 Write
<float>(rotation
);
548 } catch (status_t
& status
) {
557 PictureDataWriter::WriteSetFontEncoding(const int32
& encoding
)
560 BeginOp(B_PIC_SET_FONT_ENCODING
);
561 Write
<int32
>(encoding
);
563 } catch (status_t
& status
) {
572 PictureDataWriter::WriteSetFontFlags(const int32
& flags
)
575 BeginOp(B_PIC_SET_FONT_FLAGS
);
578 } catch (status_t
& status
) {
587 PictureDataWriter::WriteSetFontShear(const float& shear
)
590 BeginOp(B_PIC_SET_FONT_SHEAR
);
593 } catch (status_t
& status
) {
602 PictureDataWriter::WriteSetFontFace(const int32
& face
)
605 BeginOp(B_PIC_SET_FONT_FACE
);
608 } catch (status_t
& status
) {
617 PictureDataWriter::WritePushState()
620 BeginOp(B_PIC_PUSH_STATE
);
622 } catch (status_t
& status
) {
631 PictureDataWriter::WritePopState()
634 BeginOp(B_PIC_POP_STATE
);
636 } catch (status_t
& status
) {
646 PictureDataWriter::BeginOp(const int16
& op
)
649 THROW_ERROR(B_NO_INIT
);
651 fStack
.push(fData
->Position());
652 fData
->Write(&op
, sizeof(op
));
654 // Init the size of the opcode block to 0
656 fData
->Write(&size
, sizeof(size
));
661 PictureDataWriter::EndOp()
664 THROW_ERROR(B_NO_INIT
);
666 off_t curPos
= fData
->Position();
667 off_t stackPos
= fStack
.top();
670 // The size of the op is calculated like this:
671 // current position on the stream minus the position on the stack,
672 // minus the space occupied by the op code itself (int16)
673 // and the space occupied by the size field (int32)
674 int32 size
= curPos
- stackPos
- sizeof(int32
) - sizeof(int16
);
676 // Size was set to 0 in BeginOp()
677 // Now we overwrite it with the correct value
678 fData
->Seek(stackPos
+ sizeof(int16
), SEEK_SET
);
679 fData
->Write(&size
, sizeof(size
));
680 fData
->Seek(curPos
, SEEK_SET
);
685 PictureDataWriter::WriteData(const void* data
, size_t size
)
687 ssize_t result
= fData
->Write(data
, size
);
691 if ((size_t)result
!= size
)
692 THROW_ERROR(B_IO_ERROR
);