00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "paletteImage.h"
00016 #include "palettePage.h"
00017 #include "paletteGroup.h"
00018 #include "texturePlacement.h"
00019 #include "palettizer.h"
00020 #include "textureImage.h"
00021 #include "sourceTextureImage.h"
00022 #include "filenameUnifier.h"
00023
00024 #include "indent.h"
00025 #include "datagram.h"
00026 #include "datagramIterator.h"
00027 #include "bamReader.h"
00028 #include "bamWriter.h"
00029 #include "string_utils.h"
00030
00031 #include <algorithm>
00032
00033 TypeHandle PaletteImage::_type_handle;
00034
00035
00036
00037
00038
00039
00040
00041 PaletteImage::ClearedRegion::
00042 ClearedRegion() {
00043 _x = 0;
00044 _y = 0;
00045 _x_size = 0;
00046 _y_size = 0;
00047 }
00048
00049
00050
00051
00052
00053
00054 PaletteImage::ClearedRegion::
00055 ClearedRegion(TexturePlacement *placement) {
00056 _x = placement->get_placed_x();
00057 _y = placement->get_placed_y();
00058 _x_size = placement->get_placed_x_size();
00059 _y_size = placement->get_placed_y_size();
00060 }
00061
00062
00063
00064
00065
00066
00067 PaletteImage::ClearedRegion::
00068 ClearedRegion(const PaletteImage::ClearedRegion ©) :
00069 _x(copy._x),
00070 _y(copy._y),
00071 _x_size(copy._x_size),
00072 _y_size(copy._y_size)
00073 {
00074 }
00075
00076
00077
00078
00079
00080
00081 void PaletteImage::ClearedRegion::
00082 operator = (const PaletteImage::ClearedRegion ©) {
00083 _x = copy._x;
00084 _y = copy._y;
00085 _x_size = copy._x_size;
00086 _y_size = copy._y_size;
00087 }
00088
00089
00090
00091
00092
00093
00094 void PaletteImage::ClearedRegion::
00095 clear(PNMImage &image) {
00096 LRGBColord rgb(pal->_background[0], pal->_background[1], pal->_background[2]);
00097 double alpha = pal->_background[3];
00098
00099 for (int y = _y; y < _y + _y_size; y++) {
00100 for (int x = _x; x < _x + _x_size; x++) {
00101 image.set_xel(x, y, rgb);
00102 }
00103 }
00104 if (image.has_alpha()) {
00105 for (int y = _y; y < _y + _y_size; y++) {
00106 for (int x = _x; x < _x + _x_size; x++) {
00107 image.set_alpha(x, y, alpha);
00108 }
00109 }
00110 }
00111 }
00112
00113
00114
00115
00116
00117
00118
00119 void PaletteImage::ClearedRegion::
00120 write_datagram(Datagram &datagram) const {
00121 datagram.add_int32(_x);
00122 datagram.add_int32(_y);
00123 datagram.add_int32(_x_size);
00124 datagram.add_int32(_y_size);
00125 }
00126
00127
00128
00129
00130
00131
00132
00133 void PaletteImage::ClearedRegion::
00134 fillin(DatagramIterator &scan) {
00135 _x = scan.get_int32();
00136 _y = scan.get_int32();
00137 _x_size = scan.get_int32();
00138 _y_size = scan.get_int32();
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 PaletteImage::
00153 PaletteImage() {
00154 _page = (PalettePage *)NULL;
00155 _index = 0;
00156 _new_image = false;
00157 _got_image = false;
00158
00159 _swapped_image = 0;
00160 }
00161
00162
00163
00164
00165
00166
00167 PaletteImage::
00168 PaletteImage(PalettePage *page, int index) :
00169 _page(page),
00170 _index(index)
00171 {
00172 _properties = page->get_properties();
00173 _size_known = true;
00174 _x_size = pal->_pal_x_size;
00175 _y_size = pal->_pal_y_size;
00176 _new_image = true;
00177 _got_image = false;
00178 _swapped_image = 0;
00179
00180 setup_filename();
00181 }
00182
00183
00184
00185
00186
00187
00188 PaletteImage::
00189 PaletteImage(PalettePage *page, int index, unsigned swapIndex) :
00190 _page(page),
00191 _index(index),
00192 _swapped_image(swapIndex)
00193 {
00194 _properties = page->get_properties();
00195 _size_known = true;
00196 _x_size = pal->_pal_x_size;
00197 _y_size = pal->_pal_y_size;
00198 _new_image = true;
00199 _got_image = false;
00200
00201 setup_filename();
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211 PalettePage *PaletteImage::
00212 get_page() const {
00213 return _page;
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223 bool PaletteImage::
00224 is_empty() const {
00225 if (_placements.empty()) {
00226
00227 return true;
00228
00229 } else if (_placements.size() == 1) {
00230
00231
00232 return (_placements[0]->get_omit_reason() == OR_solitary);
00233
00234 } else {
00235
00236
00237 return false;
00238 }
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 double PaletteImage::
00250 count_utilization() const {
00251 int used_pixels = 0;
00252
00253 Placements::const_iterator pi;
00254 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
00255 TexturePlacement *placement = (*pi);
00256
00257 int texture_pixels =
00258 placement->get_placed_x_size() *
00259 placement->get_placed_y_size();
00260 used_pixels += texture_pixels;
00261 }
00262
00263 int total_pixels = get_x_size() * get_y_size();
00264
00265 return (double)used_pixels / (double)total_pixels;
00266 }
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 double PaletteImage::
00281 count_coverage() const {
00282 int coverage_pixels = 0;
00283
00284 Placements::const_iterator pi;
00285 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
00286 TexturePlacement *placement = (*pi);
00287 TextureImage *texture = placement->get_texture();
00288 nassertr(texture != (TextureImage *)NULL, 0.0);
00289
00290 int orig_pixels =
00291 texture->get_x_size() *
00292 texture->get_y_size();
00293 int placed_pixels =
00294 placement->get_placed_x_size() *
00295 placement->get_placed_y_size();
00296
00297 coverage_pixels += placed_pixels - orig_pixels;
00298 }
00299
00300 int total_pixels = get_x_size() * get_y_size();
00301
00302 return (double)coverage_pixels / (double)total_pixels;
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312 bool PaletteImage::
00313 place(TexturePlacement *placement) {
00314 nassertr(placement->is_size_known(), true);
00315 nassertr(!placement->is_placed(), true);
00316
00317 int x, y;
00318 if (find_hole(x, y, placement->get_x_size(), placement->get_y_size())) {
00319 placement->place_at(this, x, y);
00320 _placements.push_back(placement);
00321
00322
00323 TexturePlacement::TextureSwaps::iterator tsi;
00324 for (tsi = placement->_textureSwaps.begin(); tsi != placement->_textureSwaps.end(); ++tsi) {
00325 if ((tsi - placement->_textureSwaps.begin()) >= _swappedImages.size()) {
00326 PaletteImage *swappedImage = new PaletteImage(_page, _swappedImages.size(), tsi - placement->_textureSwaps.begin() + 1);
00327 swappedImage->_masterPlacements = &_placements;
00328 _swappedImages.push_back(swappedImage);
00329 }
00330 }
00331
00332 return true;
00333 }
00334
00335 return false;
00336 }
00337
00338
00339
00340
00341
00342
00343 void PaletteImage::
00344 unplace(TexturePlacement *placement) {
00345 nassertv(placement->is_placed() && placement->get_image() == this);
00346
00347 Placements::iterator pi;
00348 pi = find(_placements.begin(), _placements.end(), placement);
00349 while (pi != _placements.end()) {
00350 _placements.erase(pi);
00351 pi = find(_placements.begin(), _placements.end(), placement);
00352 }
00353 _cleared_regions.push_back(ClearedRegion(placement));
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 void PaletteImage::
00369 check_solitary() {
00370 if (_placements.size() == 1) {
00371
00372 TexturePlacement *placement = *_placements.begin();
00373 nassertv(placement->get_omit_reason() == OR_none ||
00374 placement->get_omit_reason() == OR_solitary);
00375
00376 if (pal->_omit_solitary || placement->get_omit_reason() == OR_solitary) {
00377
00378
00379
00380
00381 placement->omit_solitary();
00382 }
00383
00384 } else {
00385
00386 Placements::const_iterator pi;
00387 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
00388 TexturePlacement *placement = (*pi);
00389
00390
00391
00392
00393
00394
00395
00396 nassertv(placement->get_omit_reason() == OR_none ||
00397 placement->get_omit_reason() == OR_solitary);
00398 placement->not_solitary();
00399 }
00400 }
00401 }
00402
00403
00404
00405
00406
00407
00408
00409 void PaletteImage::
00410 optimal_resize() {
00411 if (is_empty()) {
00412 return;
00413 }
00414
00415 bool resized_any = false;
00416 bool success;
00417 do {
00418 success = false;
00419 nassertv(_x_size > 0 && _y_size > 0);
00420
00421
00422 if (resize_image(_x_size, _y_size / 2)) {
00423 success = true;
00424 resized_any = true;
00425 }
00426 if (resize_image(_x_size / 2, _y_size)) {
00427 success = true;
00428 resized_any = true;
00429 }
00430
00431 } while (success);
00432
00433 if (resized_any) {
00434 nout << "Resizing "
00435 << FilenameUnifier::make_user_filename(get_filename()) << " to "
00436 << _x_size << " " << _y_size << "\n";
00437
00438
00439 SwappedImages::iterator si;
00440 for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
00441 PaletteImage *swappedImage = (*si);
00442 swappedImage->resize_swapped_image(_x_size, _y_size);
00443 }
00444 }
00445 }
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 bool PaletteImage::
00457 resize_image(int x_size, int y_size) {
00458
00459
00460 _cleared_regions.clear();
00461 remove_image();
00462
00463
00464
00465 Placements saved;
00466 saved.swap(_placements);
00467
00468
00469 int saved_x_size = _x_size;
00470 int saved_y_size = _y_size;
00471
00472
00473
00474 sort(saved.begin(), saved.end(), SortPlacementBySize());
00475
00476
00477
00478 Placements::iterator pi;
00479 for (pi = saved.begin(); pi != saved.end(); ++pi) {
00480 (*pi)->force_replace();
00481 }
00482
00483
00484 _x_size = x_size;
00485 _y_size = y_size;
00486
00487 bool packed = true;
00488 for (pi = saved.begin(); pi != saved.end() && packed; ++pi) {
00489 if (!place(*pi)) {
00490 packed = false;
00491 }
00492 }
00493
00494 if (!packed) {
00495
00496 _x_size = saved_x_size;
00497 _y_size = saved_y_size;
00498
00499 Placements remove;
00500 remove.swap(_placements);
00501 for (pi = remove.begin(); pi != remove.end(); ++pi) {
00502 (*pi)->force_replace();
00503 }
00504
00505 bool all_packed = true;
00506 for (pi = saved.begin(); pi != saved.end(); ++pi) {
00507 if (!place(*pi)) {
00508 all_packed = false;
00509 }
00510 }
00511 nassertr(all_packed, false);
00512 }
00513
00514 return packed;
00515 }
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526 void PaletteImage::
00527 resize_swapped_image(int x_size, int y_size) {
00528
00529 _x_size = x_size;
00530 _y_size = y_size;
00531 }
00532
00533
00534
00535
00536
00537
00538
00539
00540 void PaletteImage::
00541 write_placements(ostream &out, int indent_level) const {
00542 Placements::const_iterator pi;
00543 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
00544 TexturePlacement *placement = (*pi);
00545 placement->write_placed(out, indent_level);
00546 }
00547 }
00548
00549
00550
00551
00552
00553
00554
00555 void PaletteImage::
00556 reset_image() {
00557
00558 Placements copy_placements = _placements;
00559 Placements::const_iterator pi;
00560 for (pi = copy_placements.begin(); pi != copy_placements.end(); ++pi) {
00561 TexturePlacement *placement = (*pi);
00562 placement->force_replace();
00563 }
00564
00565 _placements.clear();
00566 _cleared_regions.clear();
00567 remove_image();
00568 }
00569
00570
00571
00572
00573
00574
00575
00576
00577 void PaletteImage::
00578 setup_shadow_image() {
00579 _shadow_image.make_shadow_image(_basename);
00580
00581
00582 SwappedImages::iterator si;
00583 for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
00584 PaletteImage *swappedImage = (*si);
00585 swappedImage->setup_shadow_image();
00586 }
00587 }
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 void PaletteImage::
00598 update_image(bool redo_all) {
00599 if (is_empty() && pal->_aggressively_clean_mapdir) {
00600
00601
00602 remove_image();
00603 return;
00604 }
00605
00606 if (redo_all) {
00607
00608 remove_image();
00609 }
00610
00611
00612 update_filename();
00613
00614
00615 bool needs_update =
00616 _new_image || !exists() ||
00617 !_cleared_regions.empty();
00618
00619 Placements::iterator pi;
00620
00621
00622
00623 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
00624 TexturePlacement *placement = (*pi);
00625
00626 if (!placement->is_filled()) {
00627 needs_update = true;
00628
00629 } else {
00630 TextureImage *texture = placement->get_texture();
00631
00632
00633
00634 if (texture->is_texture_named()) {
00635 SourceTextureImage *source = texture->get_preferred_source();
00636
00637 if (source != (SourceTextureImage *)NULL &&
00638 source->get_filename().compare_timestamps(get_filename()) > 0) {
00639
00640
00641 placement->mark_unfilled();
00642 needs_update = true;
00643 }
00644 }
00645
00646
00647 TexturePlacement::TextureSwaps::iterator tsi;
00648 for (tsi = placement->_textureSwaps.begin(); tsi != placement->_textureSwaps.end(); ++tsi) {
00649 TextureImage *swapTexture = (*tsi);
00650
00651 if (swapTexture->is_texture_named()) {
00652 SourceTextureImage *sourceSwapTexture = swapTexture->get_preferred_source();
00653
00654 if (sourceSwapTexture != (SourceTextureImage *)NULL &&
00655 sourceSwapTexture->get_filename().compare_timestamps(get_filename()) > 0) {
00656
00657
00658 placement->mark_unfilled();
00659 needs_update = true;
00660 }
00661 }
00662 }
00663
00664 }
00665 }
00666
00667 if (!needs_update) {
00668
00669 return;
00670 }
00671
00672 get_image();
00673
00674 get_swapped_images();
00675
00676
00677 ClearedRegions::iterator ci;
00678 for (ci = _cleared_regions.begin(); ci != _cleared_regions.end(); ++ci) {
00679 ClearedRegion ®ion = (*ci);
00680 region.clear(_image);
00681
00682
00683 SwappedImages::iterator si;
00684 for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
00685 PaletteImage *swappedImage = (*si);
00686 region.clear(swappedImage->_image);
00687 }
00688 }
00689 _cleared_regions.clear();
00690
00691
00692 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
00693 TexturePlacement *placement = (*pi);
00694 if (!placement->is_filled()) {
00695 placement->fill_image(_image);
00696
00697
00698 SwappedImages::iterator si;
00699 for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
00700 PaletteImage *swappedImage = (*si);
00701 swappedImage->update_filename();
00702 placement->fill_swapped_image(swappedImage->_image, si - _swappedImages.begin());
00703 }
00704 }
00705 }
00706
00707 write(_image);
00708
00709 if (pal->_shadow_color_type != (PNMFileType *)NULL) {
00710 _shadow_image.write(_image);
00711 }
00712
00713 release_image();
00714
00715
00716 SwappedImages::iterator si;
00717 for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
00718 PaletteImage *swappedImage = (*si);
00719 swappedImage->write(swappedImage->_image);
00720 if (pal->_shadow_color_type != (PNMFileType *)NULL) {
00721 swappedImage->_shadow_image.write(swappedImage->_image);
00722 }
00723 swappedImage->release_image();
00724 }
00725 }
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 bool PaletteImage::
00737 update_filename() {
00738 Filename orig_filename = _filename;
00739 Filename orig_alpha_filename = _alpha_filename;
00740 Filename orig_shadow_filename = _shadow_image.get_filename();
00741
00742 if (setup_filename()) {
00743 nout << "Renaming " << FilenameUnifier::make_user_filename(orig_filename)
00744 << " to " << FilenameUnifier::make_user_filename(_filename) << "\n";
00745
00746 if (!orig_filename.empty() && orig_filename.exists()) {
00747 nout << "Deleting " << FilenameUnifier::make_user_filename(orig_filename) << "\n";
00748 orig_filename.unlink();
00749 }
00750 if (!orig_alpha_filename.empty() && orig_alpha_filename.exists()) {
00751 nout << "Deleting " << FilenameUnifier::make_user_filename(orig_alpha_filename) << "\n";
00752 orig_alpha_filename.unlink();
00753 }
00754 if (!orig_shadow_filename.empty() && orig_shadow_filename.exists()) {
00755 nout << "Deleting " << FilenameUnifier::make_user_filename(orig_shadow_filename) << "\n";
00756 orig_shadow_filename.unlink();
00757 }
00758 _new_image = true;
00759
00760
00761
00762
00763
00764
00765
00766 Placements::iterator pi;
00767 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
00768 TexturePlacement *placement = (*pi);
00769 placement->mark_eggs_stale();
00770 }
00771
00772 return true;
00773 }
00774
00775 return false;
00776 }
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787 bool PaletteImage::
00788 setup_filename() {
00789
00790
00791 _basename = string();
00792
00793 string::iterator si = pal->_generated_image_pattern.begin();
00794 while (si != pal->_generated_image_pattern.end()) {
00795 if ((*si) == '%') {
00796
00797 ++si;
00798 if (si != pal->_generated_image_pattern.end()) {
00799 switch (*si) {
00800 case '%':
00801 _basename += '%';
00802 break;
00803
00804 case 'g':
00805 _basename += _page->get_group()->get_name();
00806 break;
00807
00808 case 'p':
00809 _basename += _page->get_name();
00810 break;
00811
00812 case 'i':
00813 _basename += format_string(_index + 1);
00814 break;
00815
00816 default:
00817 _basename += '%';
00818 _basename += (*si);
00819 }
00820 ++si;
00821 }
00822 } else {
00823
00824 _basename += (*si);
00825 ++si;
00826 }
00827 }
00828
00829 if (_swapped_image > 0) {
00830 _basename += "_swp_";
00831 _basename += format_string(_swapped_image);
00832 }
00833
00834
00835
00836
00837
00838 if (_basename.empty() || _basename[_basename.length() - 1] != '.') {
00839 _basename += '.';
00840 }
00841
00842 bool any_changed = false;
00843
00844 if (set_filename(_page->get_group(), _basename)) {
00845 any_changed = true;
00846 }
00847
00848 if (_shadow_image.make_shadow_image(_basename)) {
00849 any_changed = true;
00850 }
00851
00852 return any_changed;
00853 }
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863 bool PaletteImage::
00864 find_hole(int &x, int &y, int x_size, int y_size) const {
00865 y = 0;
00866 while (y + y_size <= _y_size) {
00867 int next_y = _y_size;
00868
00869 x = 0;
00870 while (x + x_size <= _x_size) {
00871 int next_x = x;
00872
00873
00874 TexturePlacement *overlap = find_overlap(x, y, x_size, y_size);
00875
00876 if (overlap == (TexturePlacement *)NULL) {
00877
00878 return true;
00879 }
00880
00881 next_x = overlap->get_placed_x() + overlap->get_placed_x_size();
00882 next_y = min(next_y, overlap->get_placed_y() + overlap->get_placed_y_size());
00883 nassertr(next_x > x, false);
00884 x = next_x;
00885 }
00886
00887 nassertr(next_y > y, false);
00888 y = next_y;
00889 }
00890
00891
00892 return false;
00893 }
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906 TexturePlacement *PaletteImage::
00907 find_overlap(int x, int y, int x_size, int y_size) const {
00908 Placements::const_iterator pi;
00909 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
00910 TexturePlacement *placement = (*pi);
00911 if (placement->is_placed() &&
00912 placement->intersects(x, y, x_size, y_size)) {
00913 return placement;
00914 }
00915 }
00916
00917 return (TexturePlacement *)NULL;
00918 }
00919
00920
00921
00922
00923
00924
00925
00926 void PaletteImage::
00927 get_image() {
00928 if (_got_image) {
00929 return;
00930 }
00931
00932 if (!_new_image) {
00933 if (pal->_shadow_color_type != (PNMFileType *)NULL) {
00934 if (_shadow_image.get_filename().exists() && _shadow_image.read(_image)) {
00935 _got_image = true;
00936 return;
00937 }
00938 } else {
00939 if (get_filename().exists() && read(_image)) {
00940 _got_image = true;
00941 return;
00942 }
00943 }
00944 }
00945
00946 nout << "Generating new "
00947 << FilenameUnifier::make_user_filename(get_filename()) << "\n";
00948
00949
00950 _cleared_regions.clear();
00951
00952 _image.clear(get_x_size(), get_y_size(), _properties.get_num_channels());
00953 _image.fill(pal->_background[0], pal->_background[1], pal->_background[2]);
00954 if (_image.has_alpha()) {
00955 _image.alpha_fill(pal->_background[3]);
00956 }
00957
00958 _new_image = false;
00959 _got_image = true;
00960
00961
00962 Placements::iterator pi;
00963 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
00964 TexturePlacement *placement = (*pi);
00965 placement->fill_image(_image);
00966 }
00967 }
00968
00969
00970
00971
00972
00973
00974 void PaletteImage::
00975 get_swapped_image(int index) {
00976 if (_got_image) {
00977 return;
00978 }
00979
00980 if (!_new_image) {
00981 if (pal->_shadow_color_type != (PNMFileType *)NULL) {
00982 if (_shadow_image.get_filename().exists() && _shadow_image.read(_image)) {
00983 _got_image = true;
00984 return;
00985 }
00986 } else {
00987 if (get_filename().exists() && read(_image)) {
00988 _got_image = true;
00989 return;
00990 }
00991 }
00992 }
00993
00994 nout << "Generating new "
00995 << FilenameUnifier::make_user_filename(get_filename()) << "\n";
00996
00997
00998 _cleared_regions.clear();
00999
01000 _image.clear(get_x_size(), get_y_size(), _properties.get_num_channels());
01001 _image.fill(pal->_background[0], pal->_background[1], pal->_background[2]);
01002 if (_image.has_alpha()) {
01003 _image.alpha_fill(pal->_background[3]);
01004 }
01005
01006 _new_image = false;
01007 _got_image = true;
01008
01009
01010 Placements::iterator pi;
01011 for (pi = _masterPlacements->begin(); pi != _masterPlacements->end(); ++pi) {
01012 TexturePlacement *placement = (*pi);
01013 if (placement->_textureSwaps.size() > index)
01014 placement->fill_swapped_image(_image, index);
01015 else
01016 placement->fill_image(_image);
01017 }
01018 }
01019
01020
01021
01022
01023
01024
01025
01026 void PaletteImage::
01027 get_swapped_images() {
01028 SwappedImages::iterator si;
01029 for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
01030 PaletteImage *swappedImage = (*si);
01031 swappedImage->get_swapped_image(si - _swappedImages.begin());
01032 }
01033 }
01034
01035
01036
01037
01038
01039
01040
01041 void PaletteImage::
01042 release_image() {
01043 _image.clear();
01044 _got_image = false;
01045 }
01046
01047
01048
01049
01050
01051
01052 void PaletteImage::
01053 remove_image() {
01054 unlink();
01055 if (pal->_shadow_color_type != (PNMFileType *)NULL) {
01056 _shadow_image.unlink();
01057 }
01058 _new_image = true;
01059 }
01060
01061
01062
01063
01064
01065
01066
01067 void PaletteImage::
01068 register_with_read_factory() {
01069 BamReader::get_factory()->
01070 register_factory(get_class_type(), make_PaletteImage);
01071 }
01072
01073
01074
01075
01076
01077
01078
01079
01080 void PaletteImage::
01081 write_datagram(BamWriter *writer, Datagram &datagram) {
01082 ImageFile::write_datagram(writer, datagram);
01083
01084 datagram.add_uint32(_cleared_regions.size());
01085 ClearedRegions::const_iterator ci;
01086 for (ci = _cleared_regions.begin(); ci != _cleared_regions.end(); ++ci) {
01087 (*ci).write_datagram(datagram);
01088 }
01089
01090 datagram.add_uint32(_placements.size());
01091 Placements::const_iterator pi;
01092 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
01093 writer->write_pointer(datagram, (*pi));
01094 }
01095
01096 writer->write_pointer(datagram, _page);
01097 datagram.add_uint32(_index);
01098 datagram.add_string(_basename);
01099 datagram.add_bool(_new_image);
01100
01101
01102
01103
01104
01105
01106
01107
01108 }
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119 int PaletteImage::
01120 complete_pointers(TypedWritable **p_list, BamReader *manager) {
01121 int index = ImageFile::complete_pointers(p_list, manager);
01122
01123 int i;
01124 _placements.reserve(_num_placements);
01125 for (i = 0; i < _num_placements; i++) {
01126 TexturePlacement *placement;
01127 DCAST_INTO_R(placement, p_list[index], index);
01128 _placements.push_back(placement);
01129 index++;
01130 }
01131
01132 if (p_list[index] != (TypedWritable *)NULL) {
01133 DCAST_INTO_R(_page, p_list[index], index);
01134 }
01135 index++;
01136
01137 return index;
01138 }
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148 TypedWritable *PaletteImage::
01149 make_PaletteImage(const FactoryParams ¶ms) {
01150 PaletteImage *me = new PaletteImage;
01151 DatagramIterator scan;
01152 BamReader *manager;
01153
01154 parse_params(params, scan, manager);
01155 me->fillin(scan, manager);
01156 return me;
01157 }
01158
01159
01160
01161
01162
01163
01164
01165
01166 void PaletteImage::
01167 fillin(DatagramIterator &scan, BamReader *manager) {
01168 ImageFile::fillin(scan, manager);
01169
01170 int num_cleared_regions = scan.get_uint32();
01171 _cleared_regions.reserve(num_cleared_regions);
01172 for (int i = 0; i < num_cleared_regions; i++) {
01173 _cleared_regions.push_back(ClearedRegion());
01174 _cleared_regions.back().fillin(scan);
01175 }
01176
01177 _num_placements = scan.get_uint32();
01178 manager->read_pointers(scan, _num_placements);
01179
01180 manager->read_pointer(scan);
01181
01182 _index = scan.get_uint32();
01183 _basename = scan.get_string();
01184 _new_image = scan.get_bool();
01185 }