00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020
00021 #include "Shape.h"
00022 #include "ShapeFrame.h"
00023 #include "ConvertShape.h"
00024 #include "u8/ConvertShapeU8.h"
00025 #include "crusader/ConvertShapeCrusader.h"
00026 #include "IDataSource.h"
00027
00028 DEFINE_RUNTIME_CLASSTYPE_CODE_BASE_CLASS(Shape);
00029
00030 DEFINE_CUSTOM_MEMORY_ALLOCATION(Shape);
00031
00032 Shape::Shape(const uint8* data, uint32 size, const ConvertShapeFormat *format,
00033 const uint16 id, const uint32 shape) : flexId(id), shapenum(shape)
00034 {
00035
00036
00037 this->data = data;
00038 this->size = size;
00039 this->palette = 0;
00040
00041 if (!format) format = DetectShapeFormat(data,size);
00042
00043 if (!format)
00044 {
00045
00046 perr << "Error: Unable to detect shape format" << std::endl;
00047 return;
00048 }
00049
00050
00051 if (format == &U8ShapeFormat || format == &U82DShapeFormat)
00052 LoadU8Format(data,size,format);
00053 else if (format == &PentagramShapeFormat)
00054 LoadPentagramFormat(data,size,format);
00055 else
00056 LoadGenericFormat(data,size,format);
00057 }
00058
00059 Shape::Shape(IDataSource *src, const ConvertShapeFormat *format)
00060 : flexId(0), shapenum(0)
00061 {
00062
00063
00064 this->size = src->getSize();
00065 uint8 *d = new uint8[this->size];
00066 this->data = d;
00067 src->read(d, this->size);
00068 this->palette = 0;
00069
00070 if (!format) format = DetectShapeFormat(data,size);
00071
00072 if (!format)
00073 {
00074
00075 perr << "Error: Unable to detect shape format" << std::endl;
00076 return;
00077 }
00078
00079
00080 if (format == &U8ShapeFormat || format == &U82DShapeFormat)
00081 LoadU8Format(data,size,format);
00082 else if (format == &PentagramShapeFormat)
00083 LoadPentagramFormat(data,size,format);
00084 else
00085 LoadGenericFormat(data,size,format);
00086 }
00087
00088 Shape::~Shape()
00089 {
00090 for (unsigned int i = 0; i < frames.size(); ++i)
00091 delete frames[i];
00092
00093 delete[] const_cast<uint8*>(data);
00094 }
00095
00096 void Shape::getShapeId(uint16 & id, uint32 & shape)
00097 {
00098 id = flexId;
00099 shape = shapenum;
00100 }
00101
00102
00103 #define READ1(data,offset) (data[offset])
00104 #define READ2(data,offset) (data[offset] + (data[offset+1] << 8))
00105 #define READ3(data,offset) (data[offset] + (data[offset+1] << 8) + (data[offset+2] << 16))
00106 #define READ4(data,offset) (data[offset] + (data[offset+1] << 8) + (data[offset+2] << 16) + (data[offset+3] << 24))
00107
00108
00109 void Shape::LoadU8Format(const uint8* data, uint32 size, const ConvertShapeFormat* format)
00110 {
00111 unsigned int framecount = READ2(data,4);
00112
00113 if (framecount == 0) {
00114 LoadGenericFormat(data, size, format);
00115 return;
00116 }
00117
00118 frames.reserve(framecount);
00119
00120 for (unsigned int i = 0; i < framecount; ++i) {
00121 uint32 frameoffset = READ3(data,6+6*i);
00122 uint32 framesize = READ2(data,10+6*i);
00123
00124 frames.push_back(new ShapeFrame(data + frameoffset, framesize, format));
00125 }
00126 }
00127
00128
00129 void Shape::LoadPentagramFormat(const uint8* data, uint32 size, const ConvertShapeFormat* format)
00130 {
00131 unsigned int framecount = READ4(data,4);
00132
00133 if (framecount == 0) {
00134 LoadGenericFormat(data, size, format);
00135 return;
00136 }
00137
00138 frames.reserve(framecount);
00139
00140 for (unsigned int i = 0; i < framecount; ++i) {
00141 uint32 frameoffset = READ4(data,8+8*i);
00142 uint32 framesize = READ4(data,12+8*i);
00143
00144 frames.push_back(new ShapeFrame(data + frameoffset, framesize, format));
00145 }
00146 }
00147
00148
00149 void Shape::LoadGenericFormat(const uint8* data, uint32 size, const ConvertShapeFormat* format)
00150 {
00151 uint32 framecount;
00152 uint32 frameoffset;
00153 uint32 framesize;
00154 IBufferDataSource ds(data,size);
00155
00156 if (format->bytes_ident) {
00157 uint8* ident = new uint8[format->bytes_ident];
00158 ds.read(ident, format->bytes_ident);
00159 bool match = std::memcmp(ident,format->ident,format->bytes_ident) == 0;
00160 delete[] ident;
00161
00162 if (!match) {
00163 frames.clear();
00164 return;
00165 }
00166 }
00167
00168
00169 uint8 special[256];
00170 if (format->bytes_special) {
00171 memset(special, 0, 256);
00172 for (uint32 i = 0; i < format->bytes_special; i++) special[ds.read1()&0xFF] = i+2;
00173 }
00174
00175
00176 ds.skip(format->bytes_header_unk);
00177
00178
00179 if (format->bytes_num_frames) framecount = ds.readX(format->bytes_num_frames);
00180 else framecount = 1;
00181 if (framecount == 0) framecount = ConvertShape::CalcNumFrames(&ds,format,size,0);
00182
00183 frames.reserve(framecount);
00184
00185 for (unsigned int i = 0; i < framecount; ++i) {
00186
00187 if (format->bytes_frame_offset) frameoffset = ds.readX(format->bytes_frame_offset) + format->bytes_special;
00188 else frameoffset = format->len_header + (format->len_frameheader*i);
00189
00190
00191 ds.skip(format->bytes_frameheader_unk);
00192
00193
00194 if (format->bytes_frame_length) framesize = ds.readX(format->bytes_frame_length) + format->bytes_frame_length_kludge;
00195 else framesize = size-frameoffset;
00196
00197 ConvertShapeFrame *prev=0, p;
00198
00199 if (format->bytes_special && i > 0) {
00200 prev = &p;
00201 frames[i-1]->getConvertShapeFrame(p);
00202 }
00203
00204 frames.push_back(new ShapeFrame(data + frameoffset, framesize, format, special, prev));
00205 }
00206 }
00207
00208
00209 const ConvertShapeFormat *Shape::DetectShapeFormat(const uint8* data, uint32 size)
00210 {
00211 IBufferDataSource ds(data,size);
00212 return Shape::DetectShapeFormat(&ds, size);
00213 }
00214
00215 const ConvertShapeFormat *Shape::DetectShapeFormat(IDataSource * ds, uint32 size)
00216 {
00217 const ConvertShapeFormat *ret = 0;
00218
00219 if (ConvertShape::CheckUnsafe(ds, &PentagramShapeFormat, size))
00220 ret = &PentagramShapeFormat;
00221 else if (ConvertShape::CheckUnsafe(ds, &U8SKFShapeFormat, size))
00222 ret = &U8SKFShapeFormat;
00223 else if (ConvertShape::CheckUnsafe(ds, &U8ShapeFormat, size))
00224 ret = &U8ShapeFormat;
00225 else if (ConvertShape::CheckUnsafe(ds, &U82DShapeFormat, size))
00226 ret = &U82DShapeFormat;
00227 else if (ConvertShape::CheckUnsafe(ds, &CrusaderShapeFormat, size))
00228 ret = &CrusaderShapeFormat;
00229 else if (ConvertShape::CheckUnsafe(ds, &Crusader2DShapeFormat, size))
00230 ret = &Crusader2DShapeFormat;
00231 else if (ConvertShape::CheckUnsafe(ds, &U8CMPShapeFormat, size))
00232 ret = &U8CMPShapeFormat;
00233
00234 return ret;
00235 }
00236
00237 void Shape::getTotalDimensions(sint32& w,sint32& h,sint32& x,sint32& y) const
00238 {
00239 if (frames.empty()) {
00240 w = 0; h = 0; x = 0; y = 0;
00241 return;
00242 }
00243
00244 sint32 minx = 1000000, maxx = -1000000;
00245 sint32 miny = 1000000, maxy = -1000000;
00246
00247 for (unsigned int i = 0; i < frames.size(); ++i) {
00248 ShapeFrame* frame = frames[i];
00249 if (-frame->xoff < minx)
00250 minx = -frame->xoff;
00251 if (-frame->yoff < miny)
00252 miny = -frame->yoff;
00253 if (frame->width-frame->xoff-1 > maxx)
00254 maxx = frame->width-frame->xoff-1;
00255 if (frame->height-frame->yoff-1 > maxy)
00256 maxy = frame->height-frame->yoff-1;
00257 }
00258
00259 w = maxx - minx + 1;
00260 h = maxy - miny + 1;
00261 x = -minx;
00262 y = -miny;
00263 }