1 /* 2 * Copyright 2001-2006, Haiku Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marc Flerackers (mflerackers@androme.be) 7 * Stefano Ceccherini (burton666@libero.it) 8 */ 9 10 /** PicturePlayer is used to create and play picture data. */ 11 12 #include <stdio.h> 13 14 #include <PicturePlayer.h> 15 #include <PictureProtocol.h> 16 17 #include <Shape.h> 18 19 typedef void (*fnc)(void*); 20 typedef void (*fnc_BPoint)(void*, BPoint); 21 typedef void (*fnc_BPointBPoint)(void*, BPoint, BPoint); 22 typedef void (*fnc_BRect)(void*, BRect); 23 typedef void (*fnc_BRectBPoint)(void*, BRect, BPoint); 24 typedef void (*fnc_PBPoint)(void*, BPoint*); 25 typedef void (*fnc_i)(void*, int32); 26 typedef void (*fnc_iPBPointb)(void*, int32, BPoint*, bool); 27 typedef void (*fnc_iPBPoint)(void*, int32, BPoint*); 28 typedef void (*fnc_Pc)(void*, char*); 29 typedef void (*fnc_Pcff)(void*, char*, float, float); 30 typedef void (*fnc_BPointBPointff)(void*, BPoint, BPoint, float, float); 31 typedef void (*fnc_s)(void*, int16); 32 typedef void (*fnc_ssf)(void*, int16, int16, float); 33 typedef void (*fnc_f)(void*, float); 34 typedef void (*fnc_Color)(void*, rgb_color); 35 typedef void (*fnc_Pattern)(void*, pattern); 36 typedef void (*fnc_ss)(void *, int16, int16); 37 typedef void (*fnc_PBRecti)(void*, BRect*, int32); 38 typedef void (*fnc_DrawPixels)(void *, BRect, BRect, int32, int32, int32, 39 int32, int32, void*); 40 typedef void (*fnc_BShape)(void*, BShape*); 41 42 43 PicturePlayer::PicturePlayer(const void *data, int32 size, BList *pictures) 44 : fData(data, size), 45 fPictures(pictures) 46 { 47 } 48 49 50 PicturePlayer::~PicturePlayer() 51 { 52 } 53 54 55 int16 56 PicturePlayer::GetOp() 57 { 58 int16 data; 59 60 fData.Read(&data, sizeof(int16)); 61 62 return data; 63 } 64 65 66 int8 67 PicturePlayer::GetInt8() 68 { 69 int8 data; 70 71 fData.Read(&data, sizeof(int8)); 72 73 return data; 74 } 75 76 77 int16 78 PicturePlayer::GetInt16() 79 { 80 int16 data; 81 82 fData.Read(&data, sizeof(int16)); 83 84 return data; 85 } 86 87 88 int32 89 PicturePlayer::GetInt32() 90 { 91 int32 data; 92 93 fData.Read(&data, sizeof(int32)); 94 95 return data; 96 } 97 98 99 float 100 PicturePlayer::GetFloat() 101 { 102 float data; 103 104 fData.Read(&data, sizeof(float)); 105 106 return data; 107 } 108 109 110 BPoint 111 PicturePlayer::GetCoord() 112 { 113 BPoint data; 114 115 fData.Read(&data, sizeof(BPoint)); 116 117 return data; 118 } 119 120 121 BRect 122 PicturePlayer::GetRect() 123 { 124 BRect data; 125 126 fData.Read(&data, sizeof(BRect)); 127 128 return data; 129 } 130 131 132 rgb_color 133 PicturePlayer::GetColor() 134 { 135 rgb_color data; 136 137 fData.Read(&data, sizeof(rgb_color)); 138 139 return data; 140 } 141 142 143 void 144 PicturePlayer::GetData(void *data, int32 size) 145 { 146 fData.Read(data, size); 147 } 148 149 150 status_t 151 PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) 152 { 153 // TODO: we should probably check if the functions in the table are not NULL 154 // before calling them. 155 156 // lenght of the stream 157 size_t length = fData.Seek(0, SEEK_END); 158 fData.Seek(0, SEEK_SET); 159 160 while (fData.Position() < length) { 161 int16 op = GetOp(); 162 int32 size = GetInt32(); 163 off_t pos = fData.Position(); 164 165 switch (op) { 166 case B_PIC_MOVE_PEN_BY: 167 { 168 BPoint where = GetCoord(); 169 ((fnc_BPoint)callBackTable[1])(userData, where); 170 break; 171 } 172 173 case B_PIC_STROKE_LINE: 174 { 175 BPoint start = GetCoord(); 176 BPoint end = GetCoord(); 177 ((fnc_BPointBPoint)callBackTable[2])(userData, start, end); 178 break; 179 } 180 181 case B_PIC_STROKE_RECT: 182 { 183 BRect rect = GetRect(); 184 ((fnc_BRect)callBackTable[3])(userData, rect); 185 break; 186 } 187 188 case B_PIC_FILL_RECT: 189 { 190 BRect rect = GetRect(); 191 ((fnc_BRect)callBackTable[4])(userData, rect); 192 break; 193 } 194 195 case B_PIC_STROKE_ROUND_RECT: 196 { 197 BRect rect = GetRect(); 198 BPoint radii = GetCoord(); 199 ((fnc_BRectBPoint)callBackTable[5])(userData, rect, radii); 200 break; 201 } 202 203 case B_PIC_FILL_ROUND_RECT: 204 { 205 BRect rect = GetRect(); 206 BPoint radii = GetCoord(); 207 ((fnc_BRectBPoint)callBackTable[6])(userData, rect, radii); 208 break; 209 } 210 211 case B_PIC_STROKE_BEZIER: 212 { 213 BPoint control[4]; 214 GetData(control, sizeof(control)); 215 ((fnc_PBPoint)callBackTable[7])(userData, control); 216 break; 217 } 218 219 case B_PIC_FILL_BEZIER: 220 { 221 BPoint control[4]; 222 GetData(control, sizeof(control)); 223 ((fnc_PBPoint)callBackTable[8])(userData, control); 224 break; 225 } 226 227 case B_PIC_STROKE_ARC: 228 { 229 BPoint center = GetCoord(); 230 BPoint radii = GetCoord(); 231 float startTheta = GetFloat(); 232 float arcTheta = GetFloat(); 233 ((fnc_BPointBPointff)callBackTable[9])(userData, center, radii, 234 startTheta, arcTheta); 235 break; 236 } 237 238 case B_PIC_FILL_ARC: 239 { 240 BPoint center = GetCoord(); 241 BPoint radii = GetCoord(); 242 float startTheta = GetFloat(); 243 float arcTheta = GetFloat(); 244 ((fnc_BPointBPointff)callBackTable[10])(userData, center, radii, 245 startTheta, arcTheta); 246 break; 247 } 248 249 case B_PIC_STROKE_ELLIPSE: 250 { 251 BRect rect = GetRect(); 252 BPoint radii((rect.Width() + 1) / 2.0f, (rect.Height() + 1) / 2.0f); 253 BPoint center = rect.LeftTop() + radii; 254 ((fnc_BPointBPoint)callBackTable[11])(userData, center, radii); 255 break; 256 } 257 258 case B_PIC_FILL_ELLIPSE: 259 { 260 BRect rect = GetRect(); 261 BPoint radii((rect.Width() + 1) / 2.0f, (rect.Height() + 1) / 2.0f); 262 BPoint center = rect.LeftTop() + radii; 263 ((fnc_BPointBPoint)callBackTable[12])(userData, center, radii); 264 break; 265 } 266 267 case B_PIC_STROKE_POLYGON: 268 { 269 int32 numPoints = GetInt32(); 270 BPoint *points = new BPoint[numPoints]; 271 GetData(points, numPoints * sizeof(BPoint)); 272 bool isClosed = (bool)GetInt8(); 273 ((fnc_iPBPointb)callBackTable[13])(userData, numPoints, points, isClosed); 274 delete[] points; 275 break; 276 } 277 278 case B_PIC_FILL_POLYGON: 279 { 280 int32 numPoints = GetInt32(); 281 BPoint *points = new BPoint[numPoints]; 282 GetData(points, numPoints * sizeof(BPoint)); 283 ((fnc_iPBPoint)callBackTable[14])(userData, numPoints, points); 284 delete[] points; 285 break; 286 } 287 288 case B_PIC_STROKE_SHAPE: 289 case B_PIC_FILL_SHAPE: 290 { 291 int32 opCount = GetInt32(); 292 uint32 *opList = new uint32[opCount]; 293 GetData(opList, opCount * sizeof(uint32)); 294 295 int32 ptCount = GetInt32(); 296 BPoint *ptList = new BPoint[ptCount]; 297 GetData(ptList, ptCount * sizeof(BPoint)); 298 299 BShape shape; 300 shape.SetData(opCount, ptCount, opList, ptList); 301 302 const int32 tableIndex = (op == B_PIC_STROKE_SHAPE) ? 15 : 16; 303 ((fnc_BShape)callBackTable[tableIndex])(userData, &shape); 304 305 delete[] opList; 306 delete[] ptList; 307 308 break; 309 } 310 311 case B_PIC_DRAW_STRING: 312 { 313 int32 len = GetInt32(); 314 char *string = new char[len + 1]; 315 GetData(string, len); 316 string[len] = '\0'; 317 float deltax = GetFloat(); 318 float deltay = GetFloat(); 319 ((fnc_Pcff)callBackTable[17])(userData, string, deltax, deltay); 320 delete[] string; 321 break; 322 } 323 324 case B_PIC_DRAW_PIXELS: 325 { 326 BRect src = GetRect(); 327 BRect dest = GetRect(); 328 int32 width = GetInt32(); 329 int32 height = GetInt32(); 330 int32 bytesPerRow = GetInt32(); 331 int32 pixelFormat = GetInt32(); 332 int32 flags = GetInt32(); 333 int32 length = GetInt32(); 334 char *data = new char[length]; 335 GetData(data, length); 336 ((fnc_DrawPixels)callBackTable[18])(userData, src, dest, 337 width, height, bytesPerRow, pixelFormat, flags, data); 338 delete[] data; 339 break; 340 } 341 342 case B_PIC_DRAW_PICTURE: 343 { 344 break; 345 } 346 347 case B_PIC_SET_CLIPPING_RECTS: 348 { 349 break; 350 } 351 352 case B_PIC_CLEAR_CLIPPING_RECTS: 353 { 354 ((fnc_PBRecti)callBackTable[20])(userData, NULL, 0); 355 break; 356 } 357 358 case B_PIC_CLIP_TO_PICTURE: 359 { 360 break; 361 } 362 363 case B_PIC_PUSH_STATE: 364 { 365 ((fnc)callBackTable[22])(userData); 366 break; 367 } 368 369 case B_PIC_POP_STATE: 370 { 371 ((fnc)callBackTable[23])(userData); 372 break; 373 } 374 375 case B_PIC_ENTER_STATE_CHANGE: 376 { 377 ((fnc)callBackTable[24])(userData); 378 break; 379 } 380 381 case B_PIC_ENTER_FONT_STATE: 382 { 383 ((fnc)callBackTable[26])(userData); 384 break; 385 } 386 387 case B_PIC_SET_ORIGIN: 388 { 389 BPoint pt = GetCoord(); 390 ((fnc_BPoint)callBackTable[28])(userData, pt); 391 break; 392 } 393 394 case B_PIC_SET_PEN_LOCATION: 395 { 396 BPoint pt = GetCoord(); 397 ((fnc_BPoint)callBackTable[29])(userData, pt); 398 break; 399 } 400 401 case B_PIC_SET_DRAWING_MODE: 402 { 403 int16 mode = GetInt16(); 404 ((fnc_s)callBackTable[30])(userData, mode); 405 break; 406 } 407 408 case B_PIC_SET_LINE_MODE: 409 { 410 int16 capMode = GetInt16(); 411 int16 joinMode = GetInt16(); 412 float miterLimit = GetFloat(); 413 ((fnc_ssf)callBackTable[31])(userData, capMode, joinMode, miterLimit); 414 break; 415 } 416 417 case B_PIC_SET_PEN_SIZE: 418 { 419 float size = GetFloat(); 420 ((fnc_f)callBackTable[32])(userData, size); 421 break; 422 } 423 424 case B_PIC_SET_FORE_COLOR: 425 { 426 rgb_color color = GetColor(); 427 ((fnc_Color)callBackTable[33])(userData, color); 428 break; 429 } 430 431 case B_PIC_SET_BACK_COLOR: 432 { 433 rgb_color color = GetColor(); 434 ((fnc_Color)callBackTable[34])(userData, color); 435 break; 436 } 437 438 case B_PIC_SET_STIPLE_PATTERN: 439 { 440 pattern p; 441 GetData(&p, sizeof(p)); 442 ((fnc_Pattern)callBackTable[35])(userData, p); 443 break; 444 } 445 446 case B_PIC_SET_SCALE: 447 { 448 float scale = GetFloat(); 449 ((fnc_f)callBackTable[36])(userData, scale); 450 break; 451 } 452 453 case B_PIC_SET_FONT_FAMILY: 454 { 455 int32 len = GetInt32(); 456 char *string = new char[len + 1]; 457 GetData(string, len); 458 string[len] = '\0'; 459 ((fnc_Pc)callBackTable[37])(userData, string); 460 delete[] string; 461 break; 462 } 463 464 case B_PIC_SET_FONT_STYLE: 465 { 466 int32 len = GetInt32(); 467 char *string = new char[len + 1]; 468 GetData(string, len); 469 string[len] = '\0'; 470 ((fnc_Pc)callBackTable[38])(userData, string); 471 delete[] string; 472 break; 473 } 474 475 case B_PIC_SET_FONT_SPACING: 476 { 477 int32 spacing = GetInt32(); 478 ((fnc_i)callBackTable[39])(userData, spacing); 479 break; 480 } 481 482 case B_PIC_SET_FONT_SIZE: 483 { 484 float size = GetFloat(); 485 ((fnc_f)callBackTable[40])(userData, size); 486 break; 487 } 488 489 case B_PIC_SET_FONT_ROTATE: 490 { 491 float rotation = GetFloat(); 492 ((fnc_f)callBackTable[41])(userData, rotation); 493 break; 494 } 495 496 case B_PIC_SET_FONT_ENCODING: 497 { 498 int32 encoding = GetInt32(); 499 ((fnc_i)callBackTable[42])(userData, encoding); 500 break; 501 } 502 503 case B_PIC_SET_FONT_FLAGS: 504 { 505 int32 flags = GetInt32(); 506 ((fnc_i)callBackTable[43])(userData, flags); 507 break; 508 } 509 510 case B_PIC_SET_FONT_SHEAR: 511 { 512 float shear = GetFloat(); 513 ((fnc_f)callBackTable[44])(userData, shear); 514 break; 515 } 516 517 case B_PIC_SET_FONT_FACE: 518 { 519 int32 flags = GetInt32(); 520 ((fnc_i)callBackTable[46])(userData, flags); 521 break; 522 } 523 // TODO: Looks like R5 function table only exports 47 functions... 524 // I added this here as a temporary workaround, because there seems to be 525 // no room for this op, although it's obviously implemented in some way... 526 case B_PIC_SET_BLENDING_MODE: 527 { 528 int16 alphaSrcMode = GetInt16(); 529 int16 alphaFncMode = GetInt16(); 530 ((fnc_ss)callBackTable[47])(userData, alphaSrcMode, alphaFncMode); 531 break; 532 } 533 534 default: 535 break; 536 } 537 538 // If we didn't read enough bytes, skip them. This is not a error 539 // since the instructions can change over time. 540 // Don't do that for state change ops, they don't have a fixed size 541 if (op != B_PIC_ENTER_STATE_CHANGE && op != B_PIC_ENTER_FONT_STATE && fData.Position() - pos < size) 542 fData.Seek(size - (fData.Position() - pos), SEEK_CUR); 543 544 // TODO: what if too much was read, should we return B_ERROR? 545 } 546 547 return B_OK; 548 } 549