ConvertShape.cpp

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2002, 2003 The Pentagram Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #include "pent_include.h"
00020 #include "ConvertShape.h"
00021 
00022 #include "IDataSource.h"
00023 #include "ODataSource.h"
00024 
00025 #include <cstring>
00026 
00027 //#define COMP_SHAPENUM 39
00028 
00029 #ifdef COMP_SHAPENUM
00030 extern int shapenum;
00031 #endif
00032 
00033 void ConvertShape::Read(IDataSource *source, const ConvertShapeFormat *csf, uint32 real_len)
00034 {
00035         // Just to be safe
00036         uint32 start_pos = source->getPos();
00037 
00038         // Read the ident
00039         if (csf->bytes_ident)
00040         {
00041                 char ident[4];
00042                 source->read(ident, csf->bytes_ident);
00043 
00044                 if (std::memcmp (ident, csf->ident, csf->bytes_ident))
00045                 {
00046                         perr << "Warning: Corrupt shape!" << std::endl;
00047                         return;
00048                 }
00049         }
00050 
00051         // Read special buffer
00052         uint8 special[256];
00053         if (csf->bytes_special) {
00054                 memset(special, 0, 256);
00055                 for (uint32 i = 0; i < csf->bytes_special; i++) special[source->read1()&0xFF] = i+2;
00056         }
00057 
00058         // Read the header unknown
00059         if (csf->bytes_header_unk) source->read(header_unknown, csf->bytes_header_unk);
00060 
00061 #ifdef COMP_SHAPENUM
00062         if (shapenum == COMP_SHAPENUM) pout << std::hex;
00063 #endif
00064 
00065         // Now read num_frames
00066         num_frames = 1;
00067         if (csf->bytes_num_frames) num_frames = source->readX(csf->bytes_num_frames);
00068         if (num_frames == 0) num_frames = CalcNumFrames(source,csf,real_len,start_pos);
00069 
00070 #ifdef COMP_SHAPENUM
00071         if (shapenum == COMP_SHAPENUM) pout << "num_frames " << num_frames << std::endl;
00072 #endif
00073 
00074 //      if (num_frames == 0xFFFF || num_frames == 0xFFFFFF || num_frames == -1)
00075 //      {
00076 //              perr << "Corrupt shape? " << std::endl;
00077 //              num_frames = 0;
00078 //              frames = 0;
00079 //              return;
00080 //      }
00081 
00082         // Create frames array
00083         frames = new ConvertShapeFrame[num_frames];
00084         std::memset (frames, 0, num_frames * sizeof(ConvertShapeFrame));
00085 
00086         // Now read the frames
00087         for(uint32 f = 0; f < num_frames; ++f) 
00088         {
00089 #ifdef COMP_SHAPENUM
00090                 if (shapenum == COMP_SHAPENUM) pout << "Frame " << f << std::endl;
00091 #endif
00092                 ConvertShapeFrame *frame = frames+f;
00093 
00094 #ifdef COMP_SHAPENUM
00095                 if (shapenum == COMP_SHAPENUM) pout << "Seeking to " << (csf->len_header + (csf->len_frameheader*f)) << std::endl;
00096                 if (shapenum == COMP_SHAPENUM) pout << "Real " << (start_pos + csf->len_header + (csf->len_frameheader*f)) << std::endl;
00097 #endif
00098                 // Seek to initial pos
00099                 source->seek(start_pos + csf->len_header + (csf->len_frameheader*f));
00100 
00101 #ifdef COMP_SHAPENUM
00102                 if (shapenum == COMP_SHAPENUM) pout << "seeked to " << source->getPos() << std::endl;
00103 #endif
00104 
00105                 // Read the offset
00106                 uint32 frame_offset = csf->len_header + (csf->len_frameheader*f);
00107                 if (csf->bytes_frame_offset) frame_offset = source->readX(csf->bytes_frame_offset);
00108 #ifdef COMP_SHAPENUM
00109                 if (shapenum == COMP_SHAPENUM) pout << "frame_offset " << frame_offset << std::endl;
00110 #endif
00111 
00112                 // Read the unknown
00113                 if (csf->bytes_frameheader_unk) source->read(frame->header_unknown, csf->bytes_frameheader_unk);
00114 
00115                 // Read frame_length
00116                 uint32 frame_length = real_len-frame_offset;
00117                 if (csf->bytes_frame_length) frame_length = source->readX(csf->bytes_frame_length) + csf->bytes_frame_length_kludge;
00118 #ifdef COMP_SHAPENUM
00119                 if (shapenum == COMP_SHAPENUM) pout << "frame_length " << frame_length << std::endl;
00120 #endif
00121 
00122                 // Seek to start of frame
00123                 source->seek(start_pos + frame_offset + csf->bytes_special);
00124 
00125                 if (csf->bytes_special)
00126                         frame->ReadCmpFrame(source, csf, special, f>0?frames+f-1:0);
00127                 else 
00128                         frame->Read(source, csf, frame_length);
00129         }
00130 
00131 #ifdef COMP_SHAPENUM
00132         if (shapenum == COMP_SHAPENUM) pout << std::dec;
00133 #endif
00134 }
00135 
00136 void ConvertShapeFrame::Read(IDataSource *source, const ConvertShapeFormat *csf, uint32 frame_length)
00137 {
00138         // Read unknown
00139         if (csf->bytes_frame_unknown) source->read(unknown, csf->bytes_frame_unknown);
00140 
00141         // Frame details
00142         compression = source->readX(csf->bytes_frame_compression);
00143         width = source->readXS(csf->bytes_frame_width);
00144         height = source->readXS(csf->bytes_frame_height);
00145         xoff = source->readXS(csf->bytes_frame_xoff);
00146         yoff = source->readXS(csf->bytes_frame_yoff);
00147 
00148 #ifdef COMP_SHAPENUM
00149         if (width <= 0 || height <= 0  ||shapenum == COMP_SHAPENUM )
00150         {
00151                 pout << "compression " << compression << std::endl;
00152                 pout << "width " << width << std::endl;
00153                 pout << "height " << height << std::endl;
00154                 pout << "xoff " << xoff << std::endl;
00155                 pout << "yoff " << yoff << std::endl;
00156         }
00157 #endif
00158 
00159         if (compression != 0 && compression != 1) {
00160                 compression = 0;
00161                 width = 0;
00162                 height = 0;
00163                 xoff = 0;
00164                 yoff = 0;
00165                 //perr << "Corrupt frame? (frame " << f << ")" << std::endl;
00166                 perr << "Corrupt frame?" << std::endl;
00167         }
00168 
00169         if (height) {
00170                 // Line offsets
00171                 line_offsets = new uint32 [height];
00172 
00173                 for(sint32 i = 0; i < height; ++i) 
00174                 {
00175                         line_offsets[i] = source->readX(csf->bytes_line_offset);
00176 
00177                         // Now fudge with the value and turn it into an offset into the rle data
00178                         // If required
00179                         if (!csf->line_offset_absolute) 
00180                                 line_offsets[i] -= (height-i)*csf->bytes_line_offset;
00181                 }
00182 
00183                 // Calculate the number of bytes of RLE data
00184                 bytes_rle = frame_length - (csf->len_frameheader2+(height*csf->bytes_line_offset));
00185 
00186 #ifdef COMP_SHAPENUM
00187                 if (bytes_rle < 0)
00188                 {
00189                         bytes_rle = 0;
00190                         perr << "Corrupt frame?" << std::endl;
00191                 }
00192                 
00193 #endif
00194         }
00195         else 
00196                 line_offsets = 0;
00197 
00198         // Read the RLE Data
00199         if (bytes_rle) {
00200                 rle_data = new uint8[bytes_rle];
00201                 source->read(rle_data, bytes_rle);
00202         }
00203         else 
00204                 rle_data = 0;
00205 }
00206 
00207 void ConvertShapeFrame::ReadCmpFrame(IDataSource *source, const ConvertShapeFormat *csf, const uint8 special[256], ConvertShapeFrame *prev)
00208 {
00209         static OAutoBufferDataSource *rlebuf = 0;
00210         uint8 outbuf[512];
00211 
00212         // Read unknown
00213         if (csf->bytes_frame_unknown) source->read(unknown, csf->bytes_frame_unknown);
00214 
00215         // Frame details
00216         compression = source->readX(csf->bytes_frame_compression);
00217         width = source->readXS(csf->bytes_frame_width);
00218         height = source->readXS(csf->bytes_frame_height);
00219         xoff = source->readXS(csf->bytes_frame_xoff);
00220         yoff = source->readXS(csf->bytes_frame_yoff);
00221 
00222         line_offsets = new uint32 [height];
00223 
00224         if (!rlebuf) rlebuf = new OAutoBufferDataSource(1024);
00225         rlebuf->clear();
00226 
00227         for(sint32 y = 0; y < height; ++y) 
00228         {
00229                 line_offsets[y] = rlebuf->getPos();
00230 
00231                 sint32 xpos = 0;
00232 
00233                 do
00234                 {
00235                         uint8 skip = source->read1();
00236                         xpos += skip;
00237 
00238                         if (xpos > width) {
00239                                 source->skip(-1); 
00240                                 skip = width-(xpos-skip);
00241                         }
00242 
00243                         rlebuf->write1(skip);
00244 
00245                         if (xpos >= width) break;
00246 
00247                         uint32 dlen = source->read1();
00248                         uint8 *o = outbuf;
00249 
00250                         // Is this required???? It seems hacky and pointless
00251                         if (dlen == 0 || dlen == 1) {
00252                                 source->skip(-1); 
00253                                 rlebuf->skip(-1);
00254                                 rlebuf->write1(skip+(width-xpos));
00255                                 break;
00256                         }
00257 
00258                         int type = 0;
00259                         
00260                         if (compression)  {
00261                                 type = dlen & 1;
00262                                 dlen >>= 1;
00263                         }
00264 
00265                         if (!type) {
00266 
00267                                 uint32 extra = 0;
00268 
00269                                 for (uint32 j = 0; j < dlen; j++) {
00270 
00271                                         uint8 c = source->read1();
00272 
00273                                         if (special[c] && prev) {
00274                                                 sint32 count = special[c];
00275                                                 prev->GetPixels(o,count,xpos-xoff,y-yoff);
00276                                                 o+=count;
00277                                                 extra += count-1;
00278                                                 xpos += count;
00279                                         }
00280                                         else if (c == 0xFF && prev) {
00281                                                 sint32 count = source->read1();
00282                                                 prev->GetPixels(o,count,xpos-xoff,y-yoff);
00283                                                 o+=count;
00284                                                 extra += count-2;
00285                                                 xpos += count;
00286                                                 j++;
00287                                         }
00288                                         else {
00289                                                 *o++ = c;
00290                                                 xpos++;
00291                                         }
00292                                 }
00293 
00294                                 if (((dlen+extra) << compression) > 255) {
00295                                         perr << "Error! Corrupt Frame. RLE dlen too large" << std::endl;
00296                                 }
00297 
00298                                 rlebuf->write1((dlen+extra) << compression);
00299                                 rlebuf->write(outbuf,dlen+extra);
00300                         }
00301                         else {
00302                                 rlebuf->write1((dlen<<1)|1);
00303                                 rlebuf->write1(source->read1());
00304                                 xpos+=dlen;
00305                         }
00306 
00307                 } while (xpos < width);
00308         }
00309 
00310         bytes_rle = rlebuf->getPos();
00311         rle_data = new uint8[bytes_rle];
00312         memcpy (rle_data, rlebuf->getBuf(), bytes_rle);
00313 }
00314 
00315 void ConvertShapeFrame::GetPixels(uint8 *buf, sint32 count, sint32 x, sint32 y)
00316 {
00317         x += xoff;
00318         y += yoff;
00319 
00320         if (y > height) return;
00321 
00322         sint32 xpos = 0;
00323         const uint8 * linedata = rle_data + line_offsets[y];
00324 
00325         do {
00326                 xpos += *linedata++;
00327           
00328                 if (xpos == width) break;
00329 
00330                 sint32 dlen = *linedata++;
00331                 int type = 0;
00332                 
00333                 if (compression) 
00334                 {
00335                         type = dlen & 1;
00336                         dlen >>= 1;
00337                 }
00338 
00339                 if (x >= xpos && x < (xpos+dlen))
00340                 {
00341                         int diff = x-xpos;
00342                         dlen-=diff;
00343                         xpos = x;
00344 
00345                         int num = count;
00346                         if (dlen < count) num = dlen;
00347 
00348                         if (!type) {
00349                                 const uint8 *l = (linedata+=diff);
00350 
00351                                 while (num--) {
00352                                         *buf++ = *l++;
00353                                         count--;
00354                                         x++;
00355                                 }
00356                         }
00357                         else {
00358                                 uint8 l = *linedata;
00359 
00360                                 while (num--) {
00361                                         *buf++ = l;
00362                                         count--;
00363                                         x++;
00364                                 }
00365                         }
00366 
00367                         if (count == 0) return;
00368                 }
00369                 
00370                 if (!type) linedata+=dlen;
00371                 else linedata++;
00372 
00373                 xpos += dlen;
00374 
00375         } while (xpos < width);
00376 }
00377 
00378 int ConvertShape::CalcNumFrames(IDataSource *source, const ConvertShapeFormat *csf, uint32 real_len, uint32 start_pos)
00379 {
00380         int f=0;
00381         uint32 first_offset = 0xFFFFFFFF;
00382 
00383         uint32 save_pos = source->getPos();
00384 
00385         for (f=0;;f++) {
00386 
00387                 // Seek to initial pos
00388                 source->seek(start_pos + csf->len_header + (csf->len_frameheader*f));
00389 
00390                 if ((source->getPos()-start_pos) >= first_offset) break;
00391 
00392                 // Read the offset
00393                 uint32 frame_offset = csf->len_header + (csf->len_frameheader*f);
00394                 if (csf->bytes_frame_offset) frame_offset = source->readX(csf->bytes_frame_offset) + csf->bytes_special;
00395 
00396                 if (frame_offset < first_offset) first_offset = frame_offset;
00397 
00398                 // Read the unknown
00399                 if (csf->bytes_frameheader_unk) source->skip(csf->bytes_frameheader_unk);
00400 
00401                 // Read frame_length
00402                 uint32 frame_length = real_len-frame_offset;
00403                 if (csf->bytes_frame_length) frame_length = source->readX(csf->bytes_frame_length) + csf->bytes_frame_length_kludge;
00404         }
00405 
00406         source->seek(save_pos);
00407 
00408         return f;
00409 }
00410 
00411 bool ConvertShape::Check(IDataSource *source, const ConvertShapeFormat *csf, uint32 real_len)
00412 {
00413 #if 0
00414         pout << "Testing " << csf->name << "..." << std::endl;
00415 #endif
00416         bool result = true;
00417 
00418         // Just to be safe
00419         int start_pos = source->getPos();
00420 
00421         // Read the ident
00422         if (csf->bytes_ident)
00423         {
00424                 char ident[5];
00425                 ident[csf->bytes_ident] = 0;
00426                 source->read(ident, csf->bytes_ident);
00427 
00428                 if (std::memcmp (ident, csf->ident, csf->bytes_ident))
00429                 {
00430                         // Return to start position
00431                         source->seek(start_pos);
00432                         return false;
00433                 }
00434         }
00435 
00436         // Read the header special colour
00437         if (csf->bytes_special) source->skip(csf->bytes_special);
00438 
00439         // Read the header unknown
00440         if (csf->bytes_header_unk) source->skip(csf->bytes_header_unk);
00441 
00442         // Now read num_frames
00443         int num_frames = 1;
00444         if (csf->bytes_num_frames) num_frames = source->readX(csf->bytes_num_frames);
00445         if (num_frames == 0) num_frames = CalcNumFrames(source,csf,real_len,start_pos);
00446 
00447         // Create frames array
00448         ConvertShapeFrame oneframe;
00449         std::memset (&oneframe, 0, sizeof(ConvertShapeFrame));
00450 
00451         // Now read the frames
00452         for (int f = 0; f < num_frames; f++) 
00453         {
00454                 ConvertShapeFrame *frame = &oneframe;
00455 
00456                 // Seek to initial pos
00457                 source->seek(start_pos + csf->len_header + (csf->len_frameheader*f));
00458 
00459                 // Read the offset
00460                 uint32 frame_offset = csf->len_header + (csf->len_frameheader*f);
00461                 if (csf->bytes_frame_offset) frame_offset = source->readX(csf->bytes_frame_offset) + csf->bytes_special;
00462 
00463                 // Read the unknown
00464                 if (csf->bytes_frameheader_unk) source->read(frame->header_unknown, csf->bytes_frameheader_unk);
00465 
00466                 // Read frame_length
00467                 uint32 frame_length = real_len-frame_offset;
00468                 if (csf->bytes_frame_length) frame_length = source->readX(csf->bytes_frame_length) + csf->bytes_frame_length_kludge;
00469 
00470                 // Invalid frame length
00471                 if ((frame_length + frame_offset) > real_len)
00472                 {
00473                         result = false;
00474                         break;
00475                 }
00476 
00477                 // Seek to start of frame
00478                 source->seek(start_pos + frame_offset);
00479 
00480                 // Read unknown
00481                 if (csf->bytes_frame_unknown) source->read(frame->unknown, csf->bytes_frame_unknown);
00482 
00483                 // Frame details
00484                 frame->compression = source->readX(csf->bytes_frame_compression);
00485                 frame->width = source->readXS(csf->bytes_frame_width);
00486                 frame->height = source->readXS(csf->bytes_frame_height);
00487                 frame->xoff = source->readXS(csf->bytes_frame_xoff);
00488                 frame->yoff = source->readXS(csf->bytes_frame_yoff);
00489 
00490                 if (frame->compression != 0 && frame->compression != 1 || frame->width < 0 || frame->height < 0)
00491                 {
00492                         frame->compression = 0;
00493                         frame->width = 0;
00494                         frame->height = 0;
00495                         frame->xoff = 0;
00496                         frame->yoff = 0;
00497                         result = false;
00498                         break;
00499                 }
00500 
00501                 if (frame->height)
00502                 {
00503                         // Line offsets
00504                         sint32 highest_offset_byte = 0;
00505 
00506                         // Calculate the number of bytes of RLE data
00507                         frame->bytes_rle = frame_length - (csf->len_frameheader2+(frame->height*csf->bytes_line_offset));
00508 
00509                         // Totally invalid shape
00510                         if (frame->bytes_rle < 0)
00511                         {
00512                                 result = false;
00513                                 break;
00514                         }
00515 
00516                         // Only attempt to decompress the shape if we are not a compressed shapes
00517                         if (!csf->bytes_special) {
00518 
00519                                 // Seek to first in offset table
00520                                 source->seek(start_pos + frame_offset + csf->len_frameheader2);
00521 
00522                                 // Loop through each of the frames and find the last rle run
00523                                 for (int i = 0; i < frame->height; i++) 
00524                                 {
00525                                         sint32 line_offset = source->readX(csf->bytes_line_offset);
00526 
00527                                         // Now fudge with the value and turn it into an offset into the rle data
00528                                         // if required
00529                                         if (!csf->line_offset_absolute) 
00530                                                 line_offset -= (frame->height-i)*csf->bytes_line_offset;
00531 
00532                                         if (line_offset > frame->bytes_rle)
00533                                         {
00534                                                 result = false;
00535                                                 break;
00536                                         }
00537 
00538                                         if (line_offset > highest_offset_byte) highest_offset_byte = line_offset;
00539                                 };
00540 
00541                                 // Failed for whatever reason
00542                                 if (result == false) break;
00543 
00544                                 // Jump to the line offset and calculate the length of the run
00545                                 source->seek(highest_offset_byte + start_pos + frame_offset + csf->len_frameheader2 + frame->height*csf->bytes_line_offset);
00546                                 int xpos = 0;
00547                                 uint32 dlen = 0;
00548 
00549                                 // Compressed
00550                                 if (frame->compression) do
00551                                 {
00552                                         xpos += source->read1();
00553                                         if (xpos == frame->width) break;
00554 
00555                                         dlen = source->read1();
00556                                         int type = dlen & 1;
00557                                         dlen >>= 1;
00558 
00559                                         if (!type) source->skip(dlen);
00560                                         else source->skip(1);
00561 
00562                                         xpos += dlen;
00563 
00564                                 } while (xpos < frame->width);
00565                                 // Uncompressed
00566                                 else do
00567                                 {
00568                                         xpos += source->read1();
00569                                         if (xpos == frame->width) break;
00570 
00571                                         dlen = source->read1();
00572                                         source->skip(dlen);
00573 
00574                                         xpos += dlen;
00575                                 } while (xpos < frame->width);
00576 
00577                                 // Calc 'real' bytes rle
00578                                 sint32 highest_rle_byte = source->getPos();
00579                                 highest_rle_byte -= start_pos + frame_offset + csf->len_frameheader2 + frame->height*csf->bytes_line_offset;
00580 
00581                                 // Too many bytes
00582                                 if (highest_rle_byte > frame->bytes_rle)
00583                                 {
00584                                         result = false;
00585                                         break;
00586                                 }
00587                         }
00588                 }
00589         }
00590 
00591         // Free frames
00592         oneframe.Free();
00593         num_frames = 0;
00594 
00595         // Return to start position
00596         source->seek(start_pos);
00597 
00598         return result;
00599 }
00600 
00601 bool ConvertShape::CheckUnsafe(IDataSource *source, const ConvertShapeFormat *csf, uint32 real_len)
00602 {
00603 #if 0
00604         pout << "Testing " << csf->name << "..." << std::endl;
00605 #endif
00606         bool result = true;
00607 
00608         // Just to be safe
00609         int start_pos = source->getPos();
00610 
00611         // Read the ident
00612         if (csf->bytes_ident)
00613         {
00614                 char ident[5];
00615                 ident[csf->bytes_ident] = 0;
00616                 source->read(ident, csf->bytes_ident);
00617 
00618                 if (std::memcmp (ident, csf->ident, csf->bytes_ident))
00619                 {
00620                         // Return to start position
00621                         source->seek(start_pos);
00622                         return false;
00623                 }
00624         }
00625 
00626         // Read the header special colour
00627         if (csf->bytes_special) source->skip(csf->bytes_special);
00628 
00629         // Read the header unknown
00630         if (csf->bytes_header_unk) source->skip(csf->bytes_header_unk);
00631 
00632         // Now read num_frames
00633         int num_frames = 1;
00634         if (csf->bytes_num_frames) num_frames = source->readX(csf->bytes_num_frames);
00635         if (num_frames == 0) num_frames = CalcNumFrames(source,csf,real_len,start_pos);
00636 
00637         // Create frames array
00638         ConvertShapeFrame oneframe;
00639         std::memset (&oneframe, 0, sizeof(ConvertShapeFrame));
00640 
00641         // Now read the frames
00642         for (int f = 0; f < num_frames; f++) 
00643         {
00644                 ConvertShapeFrame *frame = &oneframe;
00645 
00646                 // Seek to initial pos
00647                 source->seek(start_pos + csf->len_header + (csf->len_frameheader*f));
00648 
00649                 // Read the offset
00650                 uint32 frame_offset = csf->len_header + (csf->len_frameheader*f);
00651                 if (csf->bytes_frame_offset) frame_offset = source->readX(csf->bytes_frame_offset) + csf->bytes_special;
00652 
00653                 // Read the unknown
00654                 if (csf->bytes_frameheader_unk) source->read(frame->header_unknown, csf->bytes_frameheader_unk);
00655 
00656                 // Read frame_length
00657                 uint32 frame_length = real_len-frame_offset;
00658                 if (csf->bytes_frame_length) frame_length = source->readX(csf->bytes_frame_length) + csf->bytes_frame_length_kludge;
00659 
00660                 // Invalid frame length
00661                 if ((frame_length + frame_offset) > real_len)
00662                 {
00663                         result = false;
00664                         break;
00665                 }
00666 
00667                 // Seek to start of frame
00668                 source->seek(start_pos + frame_offset);
00669 
00670                 // Read unknown
00671                 if (csf->bytes_frame_unknown) source->read(frame->unknown, csf->bytes_frame_unknown);
00672 
00673                 // Frame details
00674                 frame->compression = source->readX(csf->bytes_frame_compression);
00675                 frame->width = source->readXS(csf->bytes_frame_width);
00676                 frame->height = source->readXS(csf->bytes_frame_height);
00677                 frame->xoff = source->readXS(csf->bytes_frame_xoff);
00678                 frame->yoff = source->readXS(csf->bytes_frame_yoff);
00679 
00680                 if (frame->compression != 0 && frame->compression != 1 || frame->width < 0 || frame->height < 0)
00681                 {
00682                         frame->compression = 0;
00683                         frame->width = 0;
00684                         frame->height = 0;
00685                         frame->xoff = 0;
00686                         frame->yoff = 0;
00687                         result = false;
00688                         break;
00689                 }
00690 
00691                 if (frame->height)
00692                 {
00693                         // Calculate the number of bytes of RLE data (may not be accurate but we don't care)
00694                         frame->bytes_rle = frame_length - (csf->len_frameheader2+(frame->height*csf->bytes_line_offset));
00695 
00696                         // Totally invalid shape
00697                         if (frame->bytes_rle < 0)
00698                         {
00699                                 result = false;
00700                                 break;
00701                         }
00702                 }
00703         }
00704 
00705         // Free frames
00706         oneframe.Free();
00707         num_frames = 0;
00708 
00709         // Return to start position
00710         source->seek(start_pos);
00711 
00712         return result;
00713 }
00714 
00715 void ConvertShape::Write(ODataSource *dest, const ConvertShapeFormat *csf, uint32 &write_len)
00716 {
00717         // Just to be safe
00718         uint32 start_pos = dest->getPos();
00719 
00720         // Write the ident
00721         if (csf->bytes_ident) dest->write(csf->ident, csf->bytes_ident);
00722 
00723         // Write the header unknown
00724         if (csf->bytes_header_unk) dest->write(header_unknown, csf->bytes_header_unk);
00725 
00726         // Now write num_frames
00727         if (csf->bytes_num_frames) dest->writeX(num_frames, csf->bytes_num_frames);
00728         else if (!csf->bytes_num_frames && num_frames > 1)
00729         {
00730                 perr << "Error: Unable to convert multiple frame shapes to " << csf->name << std::endl; 
00731                 return;
00732         }
00733 
00734         // Write filler space for the frame details
00735         for (uint32 i = 0; i < num_frames*csf->len_frameheader; i++) dest->write1(0);
00736 
00737         // Now write the frames
00738         for(uint32 f = 0; f < num_frames; f++) 
00739         {
00740                 ConvertShapeFrame *frame = frames+f;
00741 
00742                 // Get the frame offset
00743                 uint32 frame_offset = dest->getPos() - start_pos;
00744 
00745                 // Seek to the frame header pos
00746                 dest->seek(start_pos + csf->len_header + (csf->len_frameheader*f));
00747 
00748                 // Write the offset
00749                 if (csf->bytes_frame_offset) dest->writeX(frame_offset, csf->bytes_frame_offset);
00750 
00751                 // Write the unknown
00752                 if (csf->bytes_frameheader_unk) dest->write(frame->header_unknown, csf->bytes_frameheader_unk);
00753 
00754                 // Calc and write frame_length
00755                 if (csf->bytes_frame_length)
00756                 {
00757                         uint32 frame_length = csf->len_frameheader2 + (frame->height*csf->bytes_line_offset) + frame->bytes_rle;
00758                         dest->writeX(frame_length - csf->bytes_frame_length_kludge, csf->bytes_frame_length);
00759                 }
00760 
00761                 // Seek to start of frame
00762                 dest->seek(start_pos + frame_offset);
00763 
00764                 // Write unknown
00765                 if (csf->bytes_frame_unknown) dest->write(frame->unknown, csf->bytes_frame_unknown);
00766 
00767                 // Frame details
00768                 dest->writeX(frame->compression, csf->bytes_frame_compression);
00769                 dest->writeX(frame->width, csf->bytes_frame_width);
00770                 dest->writeX(frame->height, csf->bytes_frame_height);
00771                 dest->writeX(frame->xoff, csf->bytes_frame_xoff);
00772                 dest->writeX(frame->yoff, csf->bytes_frame_yoff);
00773 
00774                 // Line offsets
00775                 for (sint32 i = 0; i < frame->height; i++) 
00776                 {
00777                         sint32 actual_offset = frame->line_offsets[i];
00778                         
00779                         // Unfudge the value and write it, if requiretd
00780                         if (!csf->line_offset_absolute)  
00781                                 actual_offset += (frame->height-i)*csf->bytes_line_offset;
00782 
00783                         dest->writeX(actual_offset, csf->bytes_line_offset);
00784                 }
00785 
00786                 // Write the RLE Data
00787                 dest->write(frame->rle_data, frame->bytes_rle);
00788         }
00789 
00790         // Just cheat
00791         write_len = dest->getPos() - start_pos;
00792 }
00793 
00794 
00795 // Shape format configuration for Pentagram
00796 const ConvertShapeFormat                PentagramShapeFormat =
00797 {
00798         "Pentagram",
00799         8,              // header
00800         "PSHP", // ident
00801         4,              // bytes_ident 
00802         0,              // bytes_special
00803         0,              // header_unk
00804         4,              // num_frames
00805 
00806         8,              // frameheader
00807         4,              // frame_offset
00808         0,              // frameheader_unk
00809         4,              // frame_length
00810         0,              // frame_length_kludge
00811 
00812         20,             // frameheader2
00813         0,              // frame_unknown
00814         4,              // frame_compression
00815         4,              // frame_width
00816         4,              // frame_height
00817         4,              // frame_xoff
00818         4,              // frame_yoff
00819 
00820         4,              // line_offset
00821         1               // line_offset_absolute
00822 };

Generated on Fri Jul 27 22:27:12 2007 for pentagram by  doxygen 1.4.7