/* * Copyright 2006, Haiku Inc. * Distributed under the terms of the MIT License. * * Authors: * Stefano Ceccherini (burton666@libero.it) */ #include #include #include #include #include #include #define THROW_ERROR(error) throw (status_t)(error) PictureDataWriter::PictureDataWriter() : fData(NULL) { } PictureDataWriter::PictureDataWriter(BPositionIO *data) : fData(data) { } status_t PictureDataWriter::SetTo(BPositionIO *data) { if (data == NULL) return B_BAD_VALUE; fData = data; return B_OK; } status_t PictureDataWriter::WriteSetOrigin(const BPoint &point) { try { BeginOp(B_PIC_SET_ORIGIN); Write(point); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteInvertRect(const BRect &rect) { try { WriteSetDrawingMode(B_OP_INVERT); BeginOp(B_PIC_FILL_RECT); Write(rect); EndOp(); WriteSetDrawingMode(B_OP_COPY); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteSetDrawingMode(const drawing_mode &mode) { try { BeginOp(B_PIC_SET_DRAWING_MODE); Write((int16)mode); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteSetPenSize(const float &penSize) { try { BeginOp(B_PIC_SET_PEN_SIZE); Write(penSize); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteSetLineMode(const cap_mode &cap, const join_mode &join, const float &miterLimit) { try { BeginOp(B_PIC_SET_LINE_MODE); Write((int16)cap); Write((int16)join); Write(miterLimit); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteSetScale(const float &scale) { try { BeginOp(B_PIC_SET_SCALE); Write(scale); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteSetHighColor(const rgb_color &color) { try { BeginOp(B_PIC_SET_FORE_COLOR); Write(color); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteSetLowColor(const rgb_color &color) { try { BeginOp(B_PIC_SET_BACK_COLOR); Write(color); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteDrawRect(const BRect &rect, const bool &fill) { try { BeginOp(fill ? B_PIC_FILL_RECT : B_PIC_STROKE_RECT); Write(rect); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteDrawRoundRect(const BRect &rect, const BPoint &radius, const bool &fill) { try { BeginOp(fill ? B_PIC_FILL_ROUND_RECT : B_PIC_STROKE_ROUND_RECT); Write(rect); Write(radius); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteDrawEllipse(const BRect &rect, const bool &fill) { try { BeginOp(fill ? B_PIC_FILL_ELLIPSE : B_PIC_STROKE_ELLIPSE); Write(rect); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteDrawArc(const BPoint ¢er, const BPoint &radius, const float &startTheta, const float &arcTheta, const bool &fill) { try { BeginOp(fill ? B_PIC_FILL_ARC : B_PIC_STROKE_ARC); Write(center); Write(radius); Write(startTheta); Write(arcTheta); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteStrokeLine(const BPoint &start, const BPoint &end) { try { BeginOp(B_PIC_STROKE_LINE); Write(start); Write(end); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteDrawString(const BPoint &where, const char *string, const int32 &length, const escapement_delta &escapement) { try { BeginOp(B_PIC_SET_PEN_LOCATION); Write(where); EndOp(); BeginOp(B_PIC_DRAW_STRING); Write(escapement.space); Write(escapement.nonspace); //WriteData(string, length + 1); // TODO: is string 0 terminated? why is length given? WriteData(string, length); Write(0); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteDrawShape(const int32 &opCount, const void *opList, const int32 &ptCount, const void *ptList, const bool &fill) { try { BeginOp(fill ? B_PIC_FILL_SHAPE : B_PIC_STROKE_SHAPE); Write(opCount); Write(ptCount); WriteData(opList, opCount * sizeof(uint32)); WriteData(ptList, ptCount * sizeof(BPoint)); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::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) { if (length != height * bytesPerRow) debugger("PictureDataWriter::WriteDrawBitmap: invalid length"); try { BeginOp(B_PIC_DRAW_PIXELS); Write(srcRect); Write(dstRect); Write(width); Write(height); Write(bytesPerRow); Write(colorSpace); Write(flags); WriteData(data, length); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteSetFontFamily(const font_family &family) { /*BeginOp(B_PIC_SET_FONT_FAMILY); Write( EndOp();*/ return B_OK; } status_t PictureDataWriter::WriteSetFontStyle(const font_style &style) { /*BeginOp(B_PIC_SET_FONT_STYLE); Write( EndOp();*/ return B_OK; } status_t PictureDataWriter::WriteSetFontSpacing(const int32 &spacing) { try { BeginOp(B_PIC_SET_FONT_SPACING); Write(spacing); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteSetFontSize(const float &size) { try { BeginOp(B_PIC_SET_FONT_SIZE); Write(size); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteSetFontRotation(const float &rotation) { try { BeginOp(B_PIC_SET_FONT_ROTATE); Write(rotation); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteSetFontEncoding(const int32 &encoding) { try { BeginOp(B_PIC_SET_FONT_ENCODING); Write(encoding); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteSetFontFlags(const int32 &flags) { try { BeginOp(B_PIC_SET_FONT_FLAGS); Write(flags); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteSetFontShear(const int32 &shear) { try { BeginOp(B_PIC_SET_FONT_SHEAR); Write(shear); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WriteSetFontFace(const int32 &face) { try { BeginOp(B_PIC_SET_FONT_FACE); Write(face); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WritePushState() { try { BeginOp(B_PIC_PUSH_STATE); EndOp(); } catch (status_t &status) { return status; } return B_OK; } status_t PictureDataWriter::WritePopState() { try { BeginOp(B_PIC_POP_STATE); EndOp(); } catch (status_t &status) { return status; } return B_OK; } // private void PictureDataWriter::BeginOp(const int16 &op) { if (fData == NULL) THROW_ERROR(B_NO_INIT); fStack.push(fData->Position()); fData->Write(&op, sizeof(op)); // Init the size of the opcode block to 0 size_t size = 0; fData->Write(&size, sizeof(size)); } void PictureDataWriter::EndOp() { if (fData == NULL) THROW_ERROR(B_NO_INIT); off_t curPos = fData->Position(); off_t stackPos = fStack.top(); fStack.pop(); // The size of the op is calculated like this: // current position on the stream minus the position on the stack, // minus the space occupied by the op code itself (int16) // and the space occupied by the size field (size_t) size_t size = curPos - stackPos - sizeof(size_t) - sizeof(int16); // Size was set to 0 in BeginOp(). Now we overwrite it with the correct value fData->Seek(stackPos + sizeof(int16), SEEK_SET); fData->Write(&size, sizeof(size)); fData->Seek(curPos, SEEK_SET); } void PictureDataWriter::WriteData(const void *data, size_t size) { ssize_t result = fData->Write(data, size); if (result < 0) THROW_ERROR(result); if (result != size) THROW_ERROR(B_IO_ERROR); }