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 "ShapeFrame.h"
00022 #include "ConvertShape.h"
00023 #include "u8/ConvertShapeU8.h"
00024 #include "IDataSource.h"
00025
00026
00027
00028
00029 ShapeFrame::ShapeFrame(const uint8* data, uint32 size, const ConvertShapeFormat* format,
00030 const uint8 special[256], ConvertShapeFrame *prev) : line_offsets(0)
00031 {
00032
00033 if (!format || format == &U8ShapeFormat || format == &U82DShapeFormat)
00034 LoadU8Format(data,size);
00035 else if (format == &PentagramShapeFormat)
00036 LoadPentagramFormat(data,size);
00037 else if (format == &U8CMPShapeFormat)
00038 LoadU8CMPFormat(data, size, format, special, prev);
00039 else
00040 LoadGenericFormat(data,size,format);
00041 }
00042
00043 ShapeFrame::~ShapeFrame()
00044 {
00045 delete [] line_offsets;
00046 }
00047
00048
00049 #define READ1(data,offset) (data[offset])
00050 #define READ2(data,offset) (data[offset] + (data[offset+1] << 8))
00051 #define READ4(data,offset) (data[offset] + (data[offset+1] << 8) + (data[offset+2] << 16) + (data[offset+3] << 24))
00052
00053
00054 void ShapeFrame::LoadU8Format(const uint8* data, uint32 )
00055 {
00056 compressed = READ1(data,8);
00057 width = static_cast<sint16>(READ2(data,10));
00058 height = static_cast<sint16>(READ2(data,12));
00059 xoff = static_cast<sint16>(READ2(data,14));
00060 yoff = static_cast<sint16>(READ2(data,16));
00061
00062 if (height == 0) return;
00063
00064 line_offsets = new uint32[height];
00065
00066 data += 18;
00067 for (sint32 i = 0; i < height; i++)
00068 {
00069 line_offsets[i] = READ2(data,0) - ((height-i)*2);
00070 data+=2;
00071 }
00072
00073 rle_data = data;
00074 }
00075
00076
00077 void ShapeFrame::LoadPentagramFormat(const uint8* data, uint32 )
00078 {
00079 compressed = READ1(data,0);
00080 width = static_cast<sint32>(READ4(data,4));
00081 height = static_cast<sint32>(READ4(data,8));
00082 xoff = static_cast<sint32>(READ4(data,12));
00083 yoff = static_cast<sint32>(READ4(data,16));
00084
00085 if (height == 0) return;
00086
00087 line_offsets = new uint32[height];
00088
00089 data += 20;
00090 for (sint32 i = 0; i < height; i++)
00091 {
00092 line_offsets[i] = READ4(data,0);
00093 data+=4;
00094 }
00095
00096 rle_data = data;
00097 }
00098
00099
00100 void ShapeFrame::LoadGenericFormat(const uint8* data, uint32 size, const ConvertShapeFormat* format)
00101 {
00102 IBufferDataSource ds(data,size);
00103
00104 ds.skip(format->bytes_frame_unknown);
00105 compressed = ds.readX(format->bytes_frame_compression);
00106 width = ds.readXS(format->bytes_frame_width);
00107 height = ds.readXS(format->bytes_frame_height);
00108 xoff = ds.readXS(format->bytes_frame_xoff);
00109 yoff = ds.readXS(format->bytes_frame_yoff);
00110
00111 if (height == 0) return;
00112
00113 line_offsets = new uint32[height];
00114
00115 if (format->line_offset_absolute) for (sint32 i = 0; i < height; i++)
00116 {
00117 line_offsets[i] = ds.readX(format->bytes_line_offset);
00118 }
00119 else for (sint32 i = 0; i < height; i++)
00120 {
00121 line_offsets[i] = ds.readX(format->bytes_line_offset) - ((height-i)*format->bytes_line_offset);
00122 }
00123
00124 rle_data = data + format->len_frameheader2 + height*format->bytes_line_offset;
00125 }
00126
00127
00128 void ShapeFrame::LoadU8CMPFormat(const uint8* data, uint32 size, const ConvertShapeFormat* format, const uint8 special[256], ConvertShapeFrame *prev)
00129 {
00130 IBufferDataSource ds(data,size);
00131
00132 ConvertShapeFrame f;
00133
00134 f.ReadCmpFrame(&ds,format,special,prev);
00135
00136 uint32 to_alloc = f.height + (f.bytes_rle+3)/4;
00137 line_offsets = new uint32[to_alloc];
00138 rle_data = reinterpret_cast<uint8*>(line_offsets+f.height);
00139
00140 compressed = f.compression;
00141 height = f.height;
00142 width = f.width;
00143 xoff = f.xoff;
00144 yoff = f.yoff;
00145
00146 std::memcpy (line_offsets, f.line_offsets, f.height*4);
00147 std::memcpy (const_cast<uint8*>(rle_data), f.rle_data, f.bytes_rle);
00148
00149 f.Free();
00150 }
00151
00152
00153 bool ShapeFrame::hasPoint(sint32 x, sint32 y) const
00154 {
00155
00156 x += xoff;
00157 y += yoff;
00158
00159
00160 if (x < 0 || y < 0 || x >= width || y >= height) return false;
00161
00162
00163
00164
00165
00166
00167
00168
00169 sint32 xpos = 0;
00170 const uint8 * linedata = rle_data + line_offsets[y];
00171
00172 do {
00173 xpos += *linedata++;
00174
00175 if (xpos == width) break;
00176
00177 sint32 dlen = *linedata++;
00178 int type = 0;
00179
00180 if (compressed)
00181 {
00182 type = dlen & 1;
00183 dlen >>= 1;
00184 }
00185
00186 if (x >= xpos && x < (xpos+dlen)) return true;
00187 xpos += dlen;
00188 if (!type) linedata+=dlen;
00189 else linedata++;
00190
00191 } while (xpos < width);
00192
00193 return false;
00194 }
00195
00196
00197 uint8 ShapeFrame::getPixelAtPoint(sint32 x, sint32 y) const
00198 {
00199
00200 x += xoff;
00201 y += yoff;
00202
00203
00204 if (x < 0 || y < 0 || x >= width || y >= height) return 0xFF;
00205
00206
00207
00208
00209
00210
00211
00212
00213 sint32 xpos = 0;
00214 const uint8 * linedata = rle_data + line_offsets[y];
00215
00216 do {
00217 xpos += *linedata++;
00218
00219 if (xpos == width) break;
00220
00221 sint32 dlen = *linedata++;
00222 int type = 0;
00223
00224 if (compressed)
00225 {
00226 type = dlen & 1;
00227 dlen >>= 1;
00228 }
00229
00230 if (x >= xpos && x < (xpos+dlen))
00231 {
00232 if (!type) linedata+=x-xpos;
00233 return *linedata;
00234 }
00235 xpos += dlen;
00236 if (!type) linedata+=dlen;
00237 else linedata++;
00238
00239 } while (xpos < width);
00240
00241 return 0xFF;
00242 }
00243
00244 void ShapeFrame::getConvertShapeFrame(ConvertShapeFrame &csf, bool need_bytes_rle)
00245 {
00246 csf.compression = compressed;
00247 csf.width = width;
00248 csf.height = height;
00249 csf.xoff = xoff;
00250 csf.yoff = yoff;
00251 csf.line_offsets = line_offsets;
00252 csf.bytes_rle = 0;
00253 csf.rle_data = const_cast<uint8*>(rle_data);
00254 }
00255