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 ¢er, 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