1 /* 2 * Copyright 2001-2007, 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 * Marcus Overhagen (marcus@overhagen.de) 9 */ 10 11 /** PicturePlayer is used to create and play picture data. */ 12 13 #include <stdio.h> 14 15 #include <PicturePlayer.h> 16 #include <PictureProtocol.h> 17 18 #include <Shape.h> 19 20 typedef void (*fnc)(void*); 21 typedef void (*fnc_BPoint)(void*, BPoint); 22 typedef void (*fnc_BPointBPoint)(void*, BPoint, BPoint); 23 typedef void (*fnc_BRect)(void*, BRect); 24 typedef void (*fnc_BRectBPoint)(void*, BRect, BPoint); 25 typedef void (*fnc_PBPoint)(void*, const BPoint*); 26 typedef void (*fnc_i)(void*, int32); 27 typedef void (*fnc_iPBPointb)(void*, int32, const BPoint*, bool); 28 typedef void (*fnc_iPBPoint)(void*, int32, const BPoint*); 29 typedef void (*fnc_Pc)(void*, const char*); 30 typedef void (*fnc_Pcff)(void*, const char*, float, float); 31 typedef void (*fnc_BPointBPointff)(void*, BPoint, BPoint, float, float); 32 typedef void (*fnc_s)(void*, int16); 33 typedef void (*fnc_ssf)(void*, int16, int16, float); 34 typedef void (*fnc_f)(void*, float); 35 typedef void (*fnc_Color)(void*, rgb_color); 36 typedef void (*fnc_Pattern)(void*, pattern); 37 typedef void (*fnc_ss)(void *, int16, int16); 38 typedef void (*fnc_PBRecti)(void*, const BRect*, int32); 39 typedef void (*fnc_DrawPixels)(void *, BRect, BRect, int32, int32, int32, 40 int32, int32, const void *); 41 typedef void (*fnc_BShape)(void*, BShape*); 42 43 44 PicturePlayer::PicturePlayer(const void *data, size_t size, BList *pictures) 45 : fData(data), 46 fSize(size), 47 fPictures(pictures) 48 { 49 } 50 51 52 PicturePlayer::~PicturePlayer() 53 { 54 } 55 56 57 status_t 58 PicturePlayer::Play(void **callBackTable, int32 tableEntries, void *userData) 59 { 60 // TODO: we should probably check if the functions in the table are not NULL 61 // before calling them. 62 63 const char *data = reinterpret_cast<const char *>(fData); 64 size_t pos = 0; 65 66 while ((pos + 6) <= fSize) { 67 int16 op = *reinterpret_cast<const int16 *>(data); 68 int32 size = *reinterpret_cast<const int32 *>(data + 2); 69 pos += 6; 70 data += 6; 71 72 if (pos + size > fSize) 73 debugger("PicturePlayer::Play: buffer overrun\n"); 74 75 switch (op) { 76 case B_PIC_MOVE_PEN_BY: 77 { 78 ((fnc_BPoint)callBackTable[1])(userData, 79 *reinterpret_cast<const BPoint *>(data)); /* where */ 80 break; 81 } 82 83 case B_PIC_STROKE_LINE: 84 { 85 ((fnc_BPointBPoint)callBackTable[2])(userData, 86 *reinterpret_cast<const BPoint *>(data), /* start */ 87 *reinterpret_cast<const BPoint *>(data + sizeof(BPoint))); /* end */ 88 break; 89 } 90 91 case B_PIC_STROKE_RECT: 92 { 93 ((fnc_BRect)callBackTable[3])(userData, 94 *reinterpret_cast<const BRect *>(data)); /* rect */ 95 break; 96 } 97 98 case B_PIC_FILL_RECT: 99 { 100 ((fnc_BRect)callBackTable[4])(userData, 101 *reinterpret_cast<const BRect *>(data)); /* rect */ 102 break; 103 } 104 105 case B_PIC_STROKE_ROUND_RECT: 106 { 107 ((fnc_BRectBPoint)callBackTable[5])(userData, 108 *reinterpret_cast<const BRect *>(data), /* rect */ 109 *reinterpret_cast<const BPoint *>(data + sizeof(BRect))); /* radii */ 110 break; 111 } 112 113 case B_PIC_FILL_ROUND_RECT: 114 { 115 ((fnc_BRectBPoint)callBackTable[6])(userData, 116 *reinterpret_cast<const BRect *>(data), /* rect */ 117 *reinterpret_cast<const BPoint *>(data + sizeof(BRect))); /* radii */ 118 break; 119 } 120 121 case B_PIC_STROKE_BEZIER: 122 { 123 ((fnc_PBPoint)callBackTable[7])(userData, 124 reinterpret_cast<const BPoint *>(data)); 125 break; 126 } 127 128 case B_PIC_FILL_BEZIER: 129 { 130 ((fnc_PBPoint)callBackTable[8])(userData, 131 reinterpret_cast<const BPoint *>(data)); 132 break; 133 } 134 135 case B_PIC_STROKE_ARC: 136 { 137 ((fnc_BPointBPointff)callBackTable[9])(userData, 138 *reinterpret_cast<const BPoint *>(data), /* center */ 139 *reinterpret_cast<const BPoint *>(data + sizeof(BPoint)), /* radii */ 140 *reinterpret_cast<const float *>(data + 2 * sizeof(BPoint)), /* startTheta */ 141 *reinterpret_cast<const float *>(data + 2 * sizeof(BPoint) + sizeof(float))); /* arcTheta */ 142 break; 143 } 144 145 case B_PIC_FILL_ARC: 146 { 147 ((fnc_BPointBPointff)callBackTable[10])(userData, 148 *reinterpret_cast<const BPoint *>(data), /* center */ 149 *reinterpret_cast<const BPoint *>(data + sizeof(BPoint)), /* radii */ 150 *reinterpret_cast<const float *>(data + 2 * sizeof(BPoint)), /* startTheta */ 151 *reinterpret_cast<const float *>(data + 2 * sizeof(BPoint) + sizeof(float))); /* arcTheta */ 152 break; 153 } 154 155 case B_PIC_STROKE_ELLIPSE: 156 { 157 const BRect *rect = reinterpret_cast<const BRect *>(data); 158 BPoint radii((rect->Width() + 1) / 2.0f, (rect->Height() + 1) / 2.0f); 159 BPoint center = rect->LeftTop() + radii; 160 ((fnc_BPointBPoint)callBackTable[11])(userData, center, radii); 161 break; 162 } 163 164 case B_PIC_FILL_ELLIPSE: 165 { 166 const BRect *rect = reinterpret_cast<const BRect *>(data); 167 BPoint radii((rect->Width() + 1) / 2.0f, (rect->Height() + 1) / 2.0f); 168 BPoint center = rect->LeftTop() + radii; 169 ((fnc_BPointBPoint)callBackTable[12])(userData, center, radii); 170 break; 171 } 172 173 case B_PIC_STROKE_POLYGON: 174 { 175 int32 numPoints = *reinterpret_cast<const int32 *>(data); 176 ((fnc_iPBPointb)callBackTable[13])(userData, 177 numPoints, 178 reinterpret_cast<const BPoint *>(data + sizeof(int32)), /* points */ 179 *reinterpret_cast<const uint8 *>(data + sizeof(int32) + numPoints * sizeof(BPoint))); /* is-closed */ 180 break; 181 } 182 183 case B_PIC_FILL_POLYGON: 184 { 185 ((fnc_iPBPoint)callBackTable[14])(userData, 186 *reinterpret_cast<const int32 *>(data), /* numPoints */ 187 reinterpret_cast<const BPoint *>(data + sizeof(int32))); /* points */ 188 break; 189 } 190 191 case B_PIC_STROKE_SHAPE: 192 case B_PIC_FILL_SHAPE: 193 { 194 int32 opCount = *reinterpret_cast<const int32 *>(data); 195 int32 ptCount = *reinterpret_cast<const int32 *>(data + sizeof(int32)); 196 const uint32 *opList = reinterpret_cast<const uint32 *>(data + 2 * sizeof(int32)); 197 const BPoint *ptList = reinterpret_cast<const BPoint *>(data + 2 * sizeof(int32) + opCount * sizeof(uint32)); 198 199 // TODO: remove BShape data copying 200 BShape shape; 201 shape.SetData(opCount, ptCount, opList, ptList); 202 203 const int32 tableIndex = (op == B_PIC_STROKE_SHAPE) ? 15 : 16; 204 ((fnc_BShape)callBackTable[tableIndex])(userData, &shape); 205 break; 206 } 207 208 case B_PIC_DRAW_STRING: 209 { 210 ((fnc_Pcff)callBackTable[17])(userData, 211 reinterpret_cast<const char *>(data + 2 * sizeof(float)), /* string */ 212 *reinterpret_cast<const float *>(data), /* escapement.space */ 213 *reinterpret_cast<const float *>(data + sizeof(float))); /* escapement.nonspace */ 214 break; 215 } 216 217 case B_PIC_DRAW_PIXELS: 218 { 219 ((fnc_DrawPixels)callBackTable[18])(userData, 220 *reinterpret_cast<const BRect *>(data), /* src */ 221 *reinterpret_cast<const BRect *>(data + 1 * sizeof(BRect)), /* dst */ 222 *reinterpret_cast<const int32 *>(data + 2 * sizeof(BRect)), /* width */ 223 *reinterpret_cast<const int32 *>(data + 2 * sizeof(BRect) + 1 * sizeof(int32)), /* height */ 224 *reinterpret_cast<const int32 *>(data + 2 * sizeof(BRect) + 2 * sizeof(int32)), /* bytesPerRow */ 225 *reinterpret_cast<const int32 *>(data + 2 * sizeof(BRect) + 3 * sizeof(int32)), /* pixelFormat */ 226 *reinterpret_cast<const int32 *>(data + 2 * sizeof(BRect) + 4 * sizeof(int32)), /* flags */ 227 reinterpret_cast<const void *>(data + 2 * sizeof(BRect) + 5 * sizeof(int32))); /* data */ 228 break; 229 } 230 231 case B_PIC_DRAW_PICTURE: 232 { 233 break; 234 } 235 236 case B_PIC_SET_CLIPPING_RECTS: 237 { 238 break; 239 } 240 241 case B_PIC_CLEAR_CLIPPING_RECTS: 242 { 243 ((fnc_PBRecti)callBackTable[20])(userData, NULL, 0); 244 break; 245 } 246 247 case B_PIC_CLIP_TO_PICTURE: 248 { 249 break; 250 } 251 252 case B_PIC_PUSH_STATE: 253 { 254 ((fnc)callBackTable[22])(userData); 255 break; 256 } 257 258 case B_PIC_POP_STATE: 259 { 260 ((fnc)callBackTable[23])(userData); 261 break; 262 } 263 264 case B_PIC_ENTER_STATE_CHANGE: 265 { 266 ((fnc)callBackTable[24])(userData); 267 break; 268 } 269 270 case B_PIC_ENTER_FONT_STATE: 271 { 272 ((fnc)callBackTable[26])(userData); 273 break; 274 } 275 276 case B_PIC_SET_ORIGIN: 277 { 278 ((fnc_BPoint)callBackTable[28])(userData, 279 *reinterpret_cast<const BPoint *>(data)); /* origin */ 280 break; 281 } 282 283 case B_PIC_SET_PEN_LOCATION: 284 { 285 ((fnc_BPoint)callBackTable[29])(userData, 286 *reinterpret_cast<const BPoint *>(data)); /* location */ 287 break; 288 } 289 290 case B_PIC_SET_DRAWING_MODE: 291 { 292 ((fnc_s)callBackTable[30])(userData, 293 *reinterpret_cast<const int16 *>(data)); /* mode */ 294 break; 295 } 296 297 case B_PIC_SET_LINE_MODE: 298 { 299 ((fnc_ssf)callBackTable[31])(userData, 300 *reinterpret_cast<const int16 *>(data), /* cap-mode */ 301 *reinterpret_cast<const int16 *>(data + 1 * sizeof(int16)), /* join-mode */ 302 *reinterpret_cast<const float *>(data + 2 * sizeof(int16))); /* miter-limit */ 303 break; 304 } 305 306 case B_PIC_SET_PEN_SIZE: 307 { 308 ((fnc_f)callBackTable[32])(userData, 309 *reinterpret_cast<const float *>(data)); /* size */ 310 break; 311 } 312 313 case B_PIC_SET_FORE_COLOR: 314 { 315 ((fnc_Color)callBackTable[33])(userData, 316 *reinterpret_cast<const rgb_color *>(data)); /* color */ 317 break; 318 } 319 320 case B_PIC_SET_BACK_COLOR: 321 { 322 ((fnc_Color)callBackTable[34])(userData, 323 *reinterpret_cast<const rgb_color *>(data)); /* color */ 324 break; 325 } 326 327 case B_PIC_SET_STIPLE_PATTERN: 328 { 329 ((fnc_Pattern)callBackTable[35])(userData, 330 *reinterpret_cast<const pattern *>(data)); /* pattern */ 331 break; 332 } 333 334 case B_PIC_SET_SCALE: 335 { 336 ((fnc_f)callBackTable[36])(userData, 337 *reinterpret_cast<const float *>(data)); /* scale */ 338 break; 339 } 340 341 case B_PIC_SET_FONT_FAMILY: 342 { 343 debugger("B_PIC_SET_FONT_FAMILY"); // TODO: is this unused? 344 ((fnc_Pc)callBackTable[37])(userData, 345 reinterpret_cast<const char *>(data)); /* string */ 346 break; 347 } 348 349 case B_PIC_SET_FONT_STYLE: 350 { 351 debugger("B_PIC_SET_FONT_STYLE"); // TODO: is this unused? 352 ((fnc_Pc)callBackTable[38])(userData, 353 reinterpret_cast<const char *>(data)); /* string */ 354 break; 355 } 356 357 case B_PIC_SET_FONT_SPACING: 358 { 359 ((fnc_i)callBackTable[39])(userData, 360 *reinterpret_cast<const int32 *>(data)); /* spacing */ 361 break; 362 } 363 364 case B_PIC_SET_FONT_SIZE: 365 { 366 ((fnc_f)callBackTable[40])(userData, 367 *reinterpret_cast<const float *>(data)); /* size */ 368 break; 369 } 370 371 case B_PIC_SET_FONT_ROTATE: 372 { 373 ((fnc_f)callBackTable[41])(userData, 374 *reinterpret_cast<const float *>(data)); /* rotation */ 375 break; 376 } 377 378 case B_PIC_SET_FONT_ENCODING: 379 { 380 ((fnc_i)callBackTable[42])(userData, 381 *reinterpret_cast<const int32 *>(data)); /* encoding */ 382 break; 383 } 384 385 case B_PIC_SET_FONT_FLAGS: 386 { 387 ((fnc_i)callBackTable[43])(userData, 388 *reinterpret_cast<const int32 *>(data)); /* flags */ 389 break; 390 } 391 392 case B_PIC_SET_FONT_SHEAR: 393 { 394 ((fnc_f)callBackTable[44])(userData, 395 *reinterpret_cast<const float *>(data)); /* shear */ 396 break; 397 } 398 399 case B_PIC_SET_FONT_FACE: 400 { 401 ((fnc_i)callBackTable[46])(userData, 402 *reinterpret_cast<const int32 *>(data)); /* flags */ 403 break; 404 } 405 406 // TODO: Looks like R5 function table only exports 47 functions... 407 // I added this here as a temporary workaround, because there seems to be 408 // no room for this op, although it's obviously implemented in some way... 409 case B_PIC_SET_BLENDING_MODE: 410 { 411 ((fnc_ss)callBackTable[47])(userData, 412 *reinterpret_cast<const int16 *>(data), /* alphaSrcMode */ 413 *reinterpret_cast<const int16 *>(data + sizeof(int16))); /* alphaFncMode */ 414 break; 415 } 416 417 default: 418 break; 419 } 420 421 pos += size; 422 data += size; 423 424 // TODO: what if too much was read, should we return B_ERROR? 425 } 426 427 return B_OK; 428 } 429