xref: /haiku/src/kits/interface/PictureDataWriter.cpp (revision 14e3d1b5768e7110b3d5c0855833267409b71dbb)
1 /*
2  * Copyright 2006, Haiku Inc.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Stefano Ceccherini (burton666@libero.it)
7  */
8 
9 #include <DataIO.h>
10 #include <Point.h>
11 #include <Rect.h>
12 
13 #include <PictureDataWriter.h>
14 #include <PictureProtocol.h>
15 
16 #include <stdio.h>
17 
18 #define THROW_ERROR(error) throw (status_t)(error)
19 
20 PictureDataWriter::PictureDataWriter()
21 	:
22 	fData(NULL)
23 {
24 }
25 
26 
27 PictureDataWriter::PictureDataWriter(BPositionIO *data)
28 	:
29 	fData(data)
30 {
31 }
32 
33 
34 status_t
35 PictureDataWriter::SetTo(BPositionIO *data)
36 {
37 	if (data == NULL)
38 		return B_BAD_VALUE;
39 	fData = data;
40 	return B_OK;
41 }
42 
43 
44 status_t
45 PictureDataWriter::WriteSetOrigin(const BPoint &point)
46 {
47 	try {
48 		BeginOp(B_PIC_SET_ORIGIN);
49 		Write<BPoint>(point);
50 		EndOp();
51 	} catch (status_t &status) {
52 		return status;
53 	}
54 	return B_OK;
55 }
56 
57 
58 status_t
59 PictureDataWriter::WriteInvertRect(const BRect &rect)
60 {
61 	try {
62 		WriteSetDrawingMode(B_OP_INVERT);
63 
64 		BeginOp(B_PIC_FILL_RECT);
65 		Write<BRect>(rect);
66 		EndOp();
67 
68 		WriteSetDrawingMode(B_OP_COPY);
69 	} catch (status_t &status) {
70 		return status;
71 	}
72 	return B_OK;
73 }
74 
75 
76 status_t
77 PictureDataWriter::WriteSetDrawingMode(const drawing_mode &mode)
78 {
79 	try {
80 		BeginOp(B_PIC_SET_DRAWING_MODE);
81 		Write<int16>((int16)mode);
82 		EndOp();
83 	} catch (status_t &status) {
84 		return status;
85 	}
86 	return B_OK;
87 }
88 
89 
90 status_t
91 PictureDataWriter::WriteSetPenSize(const float &penSize)
92 {
93 	try {
94 		BeginOp(B_PIC_SET_PEN_SIZE);
95 		Write<float>(penSize);
96 		EndOp();
97 	} catch (status_t &status) {
98 		return status;
99 	}
100 	return B_OK;
101 }
102 
103 
104 status_t
105 PictureDataWriter::WriteSetLineMode(const cap_mode &cap, const join_mode &join, const float &miterLimit)
106 {
107 	try {
108 		BeginOp(B_PIC_SET_LINE_MODE);
109 		Write<int16>((int16)cap);
110 		Write<int16>((int16)join);
111 		Write<float>(miterLimit);
112 		EndOp();
113 	} catch (status_t &status) {
114 		return status;
115 	}
116 	return B_OK;
117 }
118 
119 
120 status_t
121 PictureDataWriter::WriteSetScale(const float &scale)
122 {
123 	try {
124 		BeginOp(B_PIC_SET_SCALE);
125 		Write<float>(scale);
126 		EndOp();
127 	} catch (status_t &status) {
128 		return status;
129 	}
130 	return B_OK;
131 }
132 
133 
134 status_t
135 PictureDataWriter::WriteSetHighColor(const rgb_color &color)
136 {
137 	try {
138 		BeginOp(B_PIC_SET_FORE_COLOR);
139 		Write<rgb_color>(color);
140 		EndOp();
141 	} catch (status_t &status) {
142 		return status;
143 	}
144 	return B_OK;
145 }
146 
147 
148 status_t
149 PictureDataWriter::WriteSetLowColor(const rgb_color &color)
150 {
151 	try {
152 		BeginOp(B_PIC_SET_BACK_COLOR);
153 		Write<rgb_color>(color);
154 		EndOp();
155 	} catch (status_t &status) {
156 		return status;
157 	}
158 	return B_OK;
159 }
160 
161 
162 status_t
163 PictureDataWriter::WriteDrawRect(const BRect &rect, const bool &fill)
164 {
165 	try {
166 		BeginOp(fill ? B_PIC_FILL_RECT : B_PIC_STROKE_RECT);
167 		Write<BRect>(rect);
168 		EndOp();
169 	} catch (status_t &status) {
170 		return status;
171 	}
172 	return B_OK;
173 }
174 
175 
176 status_t
177 PictureDataWriter::WriteDrawRoundRect(const BRect &rect, const BPoint &radius, const bool &fill)
178 {
179 	try {
180 		BeginOp(fill ? B_PIC_FILL_ROUND_RECT : B_PIC_STROKE_ROUND_RECT);
181 		Write<BRect>(rect);
182 		Write<BPoint>(radius);
183 		EndOp();
184 	} catch (status_t &status) {
185 		return status;
186 	}
187 	return B_OK;
188 }
189 
190 
191 status_t
192 PictureDataWriter::WriteDrawEllipse(const BRect &rect, const bool &fill)
193 {
194 	try {
195 		BeginOp(fill ? B_PIC_FILL_ELLIPSE : B_PIC_STROKE_ELLIPSE);
196 		Write<BRect>(rect);
197 		EndOp();
198 	} catch (status_t &status) {
199 		return status;
200 	}
201 	return B_OK;
202 }
203 
204 
205 status_t
206 PictureDataWriter::WriteDrawArc(const BPoint &center, const BPoint &radius,
207 				const float &startTheta, const float &arcTheta, const bool &fill)
208 {
209 	try {
210 		BeginOp(fill ? B_PIC_FILL_ARC : B_PIC_STROKE_ARC);
211 		Write<BPoint>(center);
212 		Write<BPoint>(radius);
213 		Write<float>(startTheta);
214 		Write<float>(arcTheta);
215 		EndOp();
216 	} catch (status_t &status) {
217 		return status;
218 	}
219 	return B_OK;
220 }
221 
222 
223 status_t
224 PictureDataWriter::WriteStrokeLine(const BPoint &start, const BPoint &end)
225 {
226 	try {
227 		BeginOp(B_PIC_STROKE_LINE);
228 		Write<BPoint>(start);
229 		Write<BPoint>(end);
230 		EndOp();
231 	} catch (status_t &status) {
232 		return status;
233 	}
234 	return B_OK;
235 }
236 
237 
238 status_t
239 PictureDataWriter::WriteDrawString(const BPoint &where, const char *string,
240 				   const int32 &length, const escapement_delta &escapement)
241 {
242 	try {
243 		BeginOp(B_PIC_SET_PEN_LOCATION);
244 		Write<BPoint>(where);
245 		EndOp();
246 
247 		BeginOp(B_PIC_DRAW_STRING);
248 		Write<float>(escapement.space);
249 		Write<float>(escapement.nonspace);
250 		//WriteData(string, length + 1); // TODO: is string 0 terminated? why is length given?
251 		WriteData(string, length);
252 		Write<uint8>(0);
253 		EndOp();
254 	} catch (status_t &status) {
255 		return status;
256 	}
257 
258 	return B_OK;
259 }
260 
261 
262 status_t
263 PictureDataWriter::WriteDrawShape(const int32 &opCount, const void *opList,
264 				const int32 &ptCount, const void *ptList, const bool &fill)
265 {
266 	try {
267 		BeginOp(fill ? B_PIC_FILL_SHAPE : B_PIC_STROKE_SHAPE);
268 		Write<int32>(opCount);
269 		Write<int32>(ptCount);
270 		WriteData(opList, opCount * sizeof(uint32));
271 		WriteData(ptList, ptCount * sizeof(BPoint));
272 		EndOp();
273 	} catch (status_t &status) {
274 		return status;
275 	}
276 
277 	return B_OK;
278 }
279 
280 
281 status_t
282 PictureDataWriter::WriteDrawBitmap(const BRect &srcRect, const BRect &dstRect, const int32 &width, const int32 &height,
283 				const int32 &bytesPerRow, const int32 &colorSpace, const int32 &flags,
284 				const void *data, const int32 &length)
285 {
286 	if (length != height * bytesPerRow)
287 		debugger("PictureDataWriter::WriteDrawBitmap: invalid length");
288 	try {
289 		BeginOp(B_PIC_DRAW_PIXELS);
290 		Write<BRect>(srcRect);
291 		Write<BRect>(dstRect);
292 		Write<int32>(width);
293 		Write<int32>(height);
294 		Write<int32>(bytesPerRow);
295 		Write<int32>(colorSpace);
296 		Write<int32>(flags);
297 		WriteData(data, length);
298 		EndOp();
299 	} catch (status_t &status) {
300 		return status;
301 	}
302 	return B_OK;
303 }
304 
305 
306 status_t
307 PictureDataWriter::WriteSetFontFamily(const font_family &family)
308 {
309 	/*BeginOp(B_PIC_SET_FONT_FAMILY);
310 	Write(
311 	EndOp();*/
312 	return B_OK;
313 }
314 
315 
316 status_t
317 PictureDataWriter::WriteSetFontStyle(const font_style &style)
318 {
319 	/*BeginOp(B_PIC_SET_FONT_STYLE);
320 	Write(
321 	EndOp();*/
322 	return B_OK;
323 }
324 
325 
326 status_t
327 PictureDataWriter::WriteSetFontSpacing(const int32 &spacing)
328 {
329 	try {
330 		BeginOp(B_PIC_SET_FONT_SPACING);
331 		Write<int32>(spacing);
332 		EndOp();
333 	} catch (status_t &status) {
334 		return status;
335 	}
336 	return B_OK;
337 }
338 
339 
340 status_t
341 PictureDataWriter::WriteSetFontSize(const float &size)
342 {
343 	try {
344 		BeginOp(B_PIC_SET_FONT_SIZE);
345 		Write<float>(size);
346 		EndOp();
347 	} catch (status_t &status) {
348 		return status;
349 	}
350 	return B_OK;
351 }
352 
353 
354 status_t
355 PictureDataWriter::WriteSetFontRotation(const float &rotation)
356 {
357 	try {
358 		BeginOp(B_PIC_SET_FONT_ROTATE);
359 		Write<float>(rotation);
360 		EndOp();
361 	} catch (status_t &status) {
362 		return status;
363 	}
364 	return B_OK;
365 }
366 
367 
368 status_t
369 PictureDataWriter::WriteSetFontEncoding(const int32 &encoding)
370 {
371 	try {
372 		BeginOp(B_PIC_SET_FONT_ENCODING);
373 		Write<int32>(encoding);
374 		EndOp();
375 	} catch (status_t &status) {
376 		return status;
377 	}
378 	return B_OK;
379 }
380 
381 
382 status_t
383 PictureDataWriter::WriteSetFontFlags(const int32 &flags)
384 {
385 	try {
386 		BeginOp(B_PIC_SET_FONT_FLAGS);
387 		Write<int32>(flags);
388 		EndOp();
389 	} catch (status_t &status) {
390 		return status;
391 	}
392 	return B_OK;
393 }
394 
395 
396 status_t
397 PictureDataWriter::WriteSetFontShear(const int32 &shear)
398 {
399 	try {
400 		BeginOp(B_PIC_SET_FONT_SHEAR);
401 		Write<int32>(shear);
402 		EndOp();
403 	} catch (status_t &status) {
404 		return status;
405 	}
406 	return B_OK;
407 }
408 
409 
410 status_t
411 PictureDataWriter::WriteSetFontFace(const int32 &face)
412 {
413 	try {
414 		BeginOp(B_PIC_SET_FONT_FACE);
415 		Write<int32>(face);
416 		EndOp();
417 	} catch (status_t &status) {
418 		return status;
419 	}
420 	return B_OK;
421 }
422 
423 
424 status_t
425 PictureDataWriter::WritePushState()
426 {
427 	try {
428 		BeginOp(B_PIC_PUSH_STATE);
429 		EndOp();
430 	} catch (status_t &status) {
431 		return status;
432 	}
433 	return B_OK;
434 }
435 
436 
437 status_t
438 PictureDataWriter::WritePopState()
439 {
440 	try {
441 		BeginOp(B_PIC_POP_STATE);
442 		EndOp();
443 	} catch (status_t &status) {
444 		return status;
445 	}
446 	return B_OK;
447 }
448 
449 
450 // private
451 void
452 PictureDataWriter::BeginOp(const int16 &op)
453 {
454 	if (fData == NULL)
455 		THROW_ERROR(B_NO_INIT);
456 
457 	fStack.push(fData->Position());
458 	fData->Write(&op, sizeof(op));
459 
460 	// Init the size of the opcode block to 0
461 	size_t size = 0;
462 	fData->Write(&size, sizeof(size));
463 }
464 
465 
466 void
467 PictureDataWriter::EndOp()
468 {
469 	if (fData == NULL)
470 		THROW_ERROR(B_NO_INIT);
471 
472 	off_t curPos = fData->Position();
473 	off_t stackPos = fStack.top();
474 	fStack.pop();
475 
476 	// The size of the op is calculated like this:
477 	// current position on the stream minus the position on the stack,
478 	// minus the space occupied by the op code itself (int16)
479 	// and the space occupied by the size field (size_t)
480 	size_t size = curPos - stackPos - sizeof(size_t) - sizeof(int16);
481 
482 	// Size was set to 0 in BeginOp(). Now we overwrite it with the correct value
483 	fData->Seek(stackPos + sizeof(int16), SEEK_SET);
484 	fData->Write(&size, sizeof(size));
485 	fData->Seek(curPos, SEEK_SET);
486 }
487 
488 
489 void
490 PictureDataWriter::WriteData(const void *data, size_t size)
491 {
492 	ssize_t result = fData->Write(data, size);
493 	if (result < 0)
494 		THROW_ERROR(result);
495 	if (result != size)
496 		THROW_ERROR(B_IO_ERROR);
497 }
498