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