1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2001-2002, OpenBeOS 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 // DEALINGS IN THE SOFTWARE. 21 // 22 // File Name: Picture.cpp 23 // Author: Marc Flerackers (mflerackers@androme.be) 24 // Description: BPicture records a series of drawing instructions that can 25 // be "replayed" later. 26 //------------------------------------------------------------------------------ 27 28 // Standard Includes ----------------------------------------------------------- 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 33 // System Includes ------------------------------------------------------------- 34 #include <Picture.h> 35 #include <Message.h> 36 #include <ByteOrder.h> 37 #include <TPicture.h> 38 #include <Errors.h> 39 #include <List.h> 40 #include <AppServerLink.h> 41 #include <PortMessage.h> 42 #include <ServerProtocol.h> 43 44 // Project Includes ------------------------------------------------------------ 45 46 // Local Includes -------------------------------------------------------------- 47 48 // Local Defines --------------------------------------------------------------- 49 50 // Globals --------------------------------------------------------------------- 51 52 struct _BPictureExtent_ { 53 void *fNewData; 54 int32 fNewSize; 55 void *fOldData; 56 int32 fOldSize; 57 BList fPictures; // In R5 this is a BArray<BPicture*> which is completely 58 // inline. 59 }; 60 61 status_t do_playback(void * data, int32 size, BList& pictures, 62 void **callBackTable, int32 tableEntries, void *user); 63 64 //------------------------------------------------------------------------------ 65 BPicture::BPicture() 66 : token(-1), 67 extent(NULL), 68 usurped(NULL) 69 { 70 extent = new _BPictureExtent_; 71 extent->fNewData = NULL; 72 extent->fNewSize = 0; 73 extent->fOldData = NULL; 74 extent->fOldSize = 0; 75 } 76 //------------------------------------------------------------------------------ 77 BPicture::BPicture(const BPicture &picture) 78 : token(-1), 79 extent(NULL), 80 usurped(NULL) 81 { 82 init_data(); 83 84 if (picture.token != -1) 85 { 86 87 BPrivate::BAppServerLink link; 88 PortMessage msg; 89 90 link.Attach<int32>(AS_CLONE_PICTURE); 91 link.Attach<int32>(picture.token); 92 link.FlushWithReply(&msg); 93 msg.Read<int32>(&token); 94 95 } 96 if (picture.extent->fNewData != NULL) 97 { 98 extent->fNewSize = picture.extent->fNewSize; 99 extent->fNewData = malloc(extent->fNewSize); 100 memcpy(extent->fNewData, picture.extent->fNewData, extent->fNewSize); 101 102 BPicture *pic; 103 104 for (int32 i = 0; i < picture.extent->fPictures.CountItems(); i++) 105 { 106 pic = new BPicture(*(BPicture*)picture.extent->fPictures.ItemAt(i)); 107 extent->fPictures.AddItem(pic); 108 } 109 } 110 else if (picture.extent->fOldData != NULL) 111 { 112 extent->fOldSize = picture.extent->fOldSize; 113 extent->fOldData = malloc(extent->fOldSize); 114 memcpy(extent->fOldData, picture.extent->fOldData, extent->fOldSize); 115 116 // In old data the sub pictures are inside the data 117 } 118 } 119 //------------------------------------------------------------------------------ 120 BPicture::BPicture(BMessage *archive) 121 : token(-1), 122 extent(NULL), 123 usurped(NULL) 124 { 125 init_data(); 126 127 int32 version, size; 128 int8 endian; 129 const void *data; 130 131 if (archive->FindInt32("_ver", &version) != B_OK) 132 version = 0; 133 134 if (archive->FindInt8("_endian", &endian) != B_OK) 135 endian = 0; 136 137 if (archive->FindData("_data", B_RAW_TYPE, &data, (ssize_t*)&size) != B_OK) 138 return; 139 140 // Load sub pictures 141 BMessage picMsg; 142 int32 i = 0; 143 144 while (archive->FindMessage("piclib", i++, &picMsg) == B_OK) 145 { 146 BPicture *pic = new BPicture(&picMsg); 147 extent->fPictures.AddItem(pic); 148 } 149 150 if (version == 0) 151 import_old_data(data, size); 152 else if (version == 1) 153 { 154 extent->fNewSize = size; 155 extent->fNewData = malloc(extent->fNewSize); 156 memcpy(extent->fNewData, data, extent->fNewSize); 157 158 // swap_data(extent->fNewData, extent->fNewSize); 159 160 if (extent->fNewSize != 0 && extent->fNewData != 0) 161 { 162 BPrivate::BAppServerLink link; 163 PortMessage msg; 164 BPicture *pic; 165 166 link.Attach<int32>(AS_CREATE_PICTURE); 167 link.Attach<int32>(extent->fPictures.CountItems()); 168 for (int32 i = 0; i < extent->fPictures.CountItems(); i++) 169 { 170 pic=(BPicture*)extent->fPictures.ItemAt(i); 171 if(pic) 172 link.Attach<int32>(pic->token); 173 } 174 link.Attach<int32>(extent->fNewSize); 175 link.Attach(extent->fNewData,extent->fNewSize); 176 link.FlushWithReply(&msg); 177 msg.Read<int32>(&token); 178 } 179 } 180 181 // Do we just free the data now? 182 if (extent->fNewData) 183 { 184 free(extent->fNewData); 185 extent->fNewData = NULL; 186 extent->fNewSize = 0; 187 } 188 189 if (extent->fOldData) 190 { 191 free(extent->fOldData); 192 extent->fOldData = NULL; 193 extent->fOldSize = 0; 194 } 195 196 // What with the sub pictures? 197 for (i = 0; i < extent->fPictures.CountItems(); i++) 198 delete (BPicture *)extent->fPictures.ItemAt(i); 199 extent->fPictures.MakeEmpty(); 200 } 201 //------------------------------------------------------------------------------ 202 BPicture::~BPicture() 203 { 204 if (token != -1) 205 { 206 BPrivate::BAppServerLink link; 207 208 link.Attach<int32>(AS_DELETE_PICTURE); 209 link.Attach<int32>(token); 210 link.Flush(); 211 } 212 213 if (extent->fNewData != NULL) 214 { 215 free(extent->fNewData); 216 extent->fNewData = NULL; 217 extent->fNewSize = 0; 218 } 219 220 if (extent->fOldData != NULL) 221 { 222 free(extent->fOldData); 223 extent->fOldData = NULL; 224 extent->fOldSize = 0; 225 } 226 227 for (int32 i = 0; i < extent->fPictures.CountItems(); i++) 228 delete (BPicture *)extent->fPictures.ItemAt(i); 229 extent->fPictures.MakeEmpty(); 230 231 free(extent); 232 } 233 //------------------------------------------------------------------------------ 234 BArchivable *BPicture::Instantiate(BMessage *archive) 235 { 236 if (validate_instantiation(archive, "BPicture")) 237 return new BPicture(archive); 238 else 239 return NULL; 240 } 241 //------------------------------------------------------------------------------ 242 status_t BPicture::Archive(BMessage *archive, bool deep) const 243 { 244 if (!const_cast<BPicture*>(this)->assert_local_copy()) 245 return B_ERROR; 246 247 status_t err = BArchivable::Archive(archive, deep); 248 249 if (err != B_OK) 250 return err; 251 252 err = archive->AddInt32("_ver", 1); 253 254 if (err != B_OK) 255 return err; 256 257 err = archive->AddInt8("_endian", B_HOST_IS_BENDIAN); 258 259 if (err != B_OK) 260 return err; 261 262 err = archive->AddData("_data", B_RAW_TYPE, extent->fNewData, 263 extent->fNewSize); 264 265 for (int32 i = 0; i < extent->fPictures.CountItems(); i++) 266 { 267 BMessage picMsg; 268 269 ((BPicture*)extent->fPictures.ItemAt(i))->Archive(&picMsg, deep); 270 271 archive->AddMessage("piclib", &picMsg); 272 } 273 274 return err; 275 } 276 //------------------------------------------------------------------------------ 277 status_t BPicture::Perform(perform_code d, void *arg) 278 { 279 return BArchivable::Perform(d, arg); 280 } 281 //------------------------------------------------------------------------------ 282 status_t BPicture::Play(void **callBackTable, int32 tableEntries, void *user) 283 { 284 if (!assert_local_copy()) 285 return B_ERROR; 286 287 return do_playback(extent->fNewData, extent->fNewSize, extent->fPictures, 288 callBackTable, tableEntries, user); 289 } 290 //------------------------------------------------------------------------------ 291 status_t BPicture::Flatten(BDataIO *stream) 292 { 293 if (!assert_local_copy()) 294 return B_ERROR; 295 296 // TODO check the header 297 int32 bla1 = 2; 298 int32 bla2 = 0; 299 int32 count = 0; 300 301 stream->Write(&bla1, 4); 302 stream->Write(&bla2, 4); 303 304 count = extent->fPictures.CountItems(); 305 stream->Write(&count, 4); 306 307 for (int32 i = 0; i < extent->fPictures.CountItems(); i++) 308 ((BPicture*)extent->fPictures.ItemAt(i))->Flatten(stream); 309 310 stream->Write(&extent->fNewSize, 4); 311 stream->Write(extent->fNewData, extent->fNewSize); 312 313 return B_OK; 314 } 315 //------------------------------------------------------------------------------ 316 status_t BPicture::Unflatten(BDataIO *stream) 317 { 318 // TODO check the header 319 int32 bla1 = 2; 320 int32 bla2 = 0; 321 int32 count = 0; 322 323 stream->Read(&bla1, 4); 324 stream->Read(&bla2, 4); 325 326 stream->Read(&count, 4); 327 328 for (int32 i = 0; i < count; i++) 329 { 330 BPicture *pic = new BPicture; 331 332 pic->Unflatten(stream); 333 334 extent->fPictures.AddItem(pic); 335 } 336 337 stream->Read(&extent->fNewSize, 4); 338 extent->fNewData = malloc(extent->fNewSize); 339 stream->Read(extent->fNewData, extent->fNewSize); 340 341 // swap_data(extent->fNewData, extent->fNewSize); 342 343 BPrivate::BAppServerLink link; 344 PortMessage msg; 345 BPicture *pic; 346 347 link.Attach<int32>(AS_CREATE_PICTURE); 348 link.Attach<int32>(extent->fPictures.CountItems()); 349 for (int32 i = 0; i < extent->fPictures.CountItems(); i++) 350 { 351 pic=(BPicture*)extent->fPictures.ItemAt(i); 352 if(pic) 353 link.Attach<int32>(pic->token); 354 } 355 link.Attach<int32>(extent->fNewSize); 356 link.Attach(extent->fNewData, extent->fNewSize); 357 link.FlushWithReply(&msg); 358 msg.Read<int32>(&token); 359 360 if (extent->fNewData) 361 { 362 free(extent->fNewData); 363 extent->fNewData = NULL; 364 extent->fNewSize = 0; 365 } 366 367 return B_OK; 368 } 369 //------------------------------------------------------------------------------ 370 void BPicture::_ReservedPicture1() {} 371 void BPicture::_ReservedPicture2() {} 372 void BPicture::_ReservedPicture3() {} 373 //------------------------------------------------------------------------------ 374 BPicture &BPicture::operator=(const BPicture &) 375 { 376 return *this; 377 } 378 //------------------------------------------------------------------------------ 379 void BPicture::init_data() 380 { 381 token = -1; 382 usurped = NULL; 383 384 extent = new _BPictureExtent_; 385 extent->fNewData = NULL; 386 extent->fNewSize = 0; 387 extent->fOldData = NULL; 388 extent->fOldSize = 0; 389 } 390 //------------------------------------------------------------------------------ 391 void BPicture::import_data(const void *data, int32 size, BPicture **subs, 392 int32 subCount) 393 { 394 if (data == NULL || size == 0) 395 return; 396 397 BPrivate::BAppServerLink link; 398 PortMessage msg; 399 400 link.Attach<int32>(AS_CREATE_PICTURE); 401 link.Attach<int32>(subCount); 402 403 for (int32 i = 0; i < subCount; i++) 404 link.Attach<int32>(subs[i]->token); 405 406 link.Attach<int32>(size); 407 link.Attach(data, size); 408 link.FlushWithReply(&msg); 409 msg.Read<int32>(&token); 410 } 411 //------------------------------------------------------------------------------ 412 void BPicture::import_old_data(const void *data, int32 size) 413 { 414 // TODO: do we need to support old data, what is old data? 415 /*if (data == NULL) 416 return; 417 418 if (size == 0) 419 return; 420 421 convert_old_to_new(data, size, &extent->fNewData, &extent->fNewSize); 422 423 BPrivate::BAppServerLink link; 424 link.Attach<int32>(AS_CREATE_PICTURE); 425 link.Attach<int32>(0L); 426 link.Attach<int32>(extent->fNewSize); 427 link.Attach(extent->fNewData,extent->fNewSize); 428 link.FlushWithReply(&msg); 429 msg.Read<int32>(&token) 430 431 // Do we free all data now? 432 free(extent->fNewData); 433 extent->fNewData = 0; 434 extent->fNewSize = 0; 435 free(extent->fOldData); 436 extent->fOldData = 0; 437 extent->fOldSize = 0;*/ 438 } 439 //------------------------------------------------------------------------------ 440 void BPicture::set_token(int32 _token) 441 { 442 token = _token; 443 } 444 //------------------------------------------------------------------------------ 445 bool BPicture::assert_local_copy() 446 { 447 if (extent->fNewData != NULL) 448 return true; 449 450 if (token == -1) 451 return false; 452 453 /* BPrivate::BAppServerLink link; 454 int32 count; 455 456 link.Attach<int32>(AS_DOWNLOAD_PICTURE); 457 link.Attach<int32>(token); 458 link.FlushWithReply(&msg); 459 count=*((int32*)replydata.buffer); 460 461 // Read sub picture tokens 462 for (int32 i = 0; i < count; i++) 463 { 464 BPicture *pic = new BPicture; 465 466 link.sread(4, &pic->token); 467 468 extent->fPictures.AddItem(pic); 469 } 470 471 link.sread(4, &extent->fNewSize); 472 extent->fNewData = malloc(extent->fNewSize); 473 link.sread(extent->fNewSize, &extent->fNewData);*/ 474 475 return true; 476 } 477 //------------------------------------------------------------------------------ 478 bool BPicture::assert_old_local_copy() 479 { 480 if (extent->fOldData != NULL) 481 return true; 482 483 if (!assert_local_copy()) 484 return false; 485 486 // convert_new_to_old(extent->fNewData, extent->fNewSize, extent->fOldData, 487 // extent->fOldSize); 488 489 return true; 490 } 491 //------------------------------------------------------------------------------ 492 bool BPicture::assert_server_copy() 493 { 494 if (token != -1) 495 return true; 496 497 if (extent->fNewData == NULL) 498 return false; 499 500 /* for (int32 i = 0; i < extent->fPictures.CountItems(); i++) 501 extent->fPictures.ItemAt(i)->assert_server_copy(); 502 503 BPrivate::BAppServerLink link; 504 link.Attach<int32>(AS_CREATE_PICTURE); 505 link.Attach<int32>(extent->fPictures.CountItems()); 506 for (int32 i = 0; i < extent->fPictures.CountItems(); i++) 507 link.Attach<int32>(extent->fPictures.ItemAt(i)->token); 508 link.Attach<int32>(extent->fNewSize); 509 link.Attach(extent->fNewData,extent->fNewSize); 510 link.FlushWithReply(&msg); 511 msg.Read<int32>(&token); 512 513 return token != -1;*/ 514 return true; 515 } 516 //------------------------------------------------------------------------------ 517 BPicture::BPicture(const void *data, int32 size) 518 { 519 init_data(); 520 import_old_data(data, size); 521 } 522 //------------------------------------------------------------------------------ 523 const void *BPicture::Data() const 524 { 525 if (extent->fNewData == NULL) 526 { 527 const_cast<BPicture*>(this)->assert_local_copy(); 528 //convert_new_to_old(void *, long, void **, long *); 529 } 530 531 return extent->fNewData; 532 } 533 //------------------------------------------------------------------------------ 534 int32 BPicture::DataSize() const 535 { 536 if (extent->fNewData == NULL) 537 { 538 const_cast<BPicture*>(this)->assert_local_copy(); 539 //convert_new_to_old(void *, long, void **, long *); 540 } 541 542 return extent->fNewSize; 543 } 544 //------------------------------------------------------------------------------ 545 void BPicture::usurp(BPicture *lameDuck) 546 { 547 if (token != -1) 548 { 549 BPrivate::BAppServerLink link; 550 551 link.Attach<int32>(AS_DELETE_PICTURE); 552 link.Attach<int32>(token); 553 link.Flush(); 554 } 555 556 if (extent->fNewData != NULL) 557 { 558 free(extent->fNewData); 559 extent->fNewData = NULL; 560 extent->fNewSize = 0; 561 } 562 563 if (extent->fOldData != NULL) 564 { 565 free(extent->fOldData); 566 extent->fOldData = NULL; 567 extent->fOldSize = 0; 568 } 569 570 for (int32 i = 0; i < extent->fPictures.CountItems(); i++) 571 delete (BPicture *)extent->fPictures.ItemAt(i); 572 extent->fPictures.MakeEmpty(); 573 574 free(extent); 575 576 init_data(); 577 578 // Do the usurping 579 usurped = lameDuck; 580 } 581 //------------------------------------------------------------------------------ 582 BPicture *BPicture::step_down() 583 { 584 BPicture *lameDuck = usurped; 585 586 usurped = NULL; 587 588 return lameDuck; 589 } 590 //------------------------------------------------------------------------------ 591 status_t do_playback(void * data, int32 size, BList& pictures, 592 void **callBackTable, int32 tableEntries, void *user) 593 { 594 TPicture pic(data, size, pictures); 595 596 return pic.Play(callBackTable, tableEntries, user); 597 } 598 //------------------------------------------------------------------------------ 599 600 601