ShapeFrame.cpp

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2003-2005 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 
00021 #include "ShapeFrame.h"
00022 #include "ConvertShape.h"
00023 #include "u8/ConvertShapeU8.h"
00024 #include "IDataSource.h"
00025 
00026 /*
00027   parse data and fill class
00028  */
00029 ShapeFrame::ShapeFrame(const uint8* data, uint32 size, const ConvertShapeFormat* format,
00030                                            const uint8 special[256], ConvertShapeFrame *prev) : line_offsets(0)
00031 {
00032         // Load it as u8
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 // Some macros to make things easier
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 // This will load a u8 style shape 'optimzed'.
00054 void ShapeFrame::LoadU8Format(const uint8* data, uint32 /*size*/)
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 // This will load a pentagram style shape 'optimzed'.
00077 void ShapeFrame::LoadPentagramFormat(const uint8* data, uint32 /*size*/)
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 // This will load any sort of shape via a ConvertShapeFormat struct
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 // This will load an U8-compressed shape
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 // Checks to see if the frame has a pixel at the point
00153 bool ShapeFrame::hasPoint(sint32 x, sint32 y) const
00154 {
00155         // Add the offset
00156         x += xoff;
00157         y += yoff;
00158 
00159         // First gross culling based on dims
00160         if (x < 0 || y < 0 || x >= width || y >= height) return false;
00161 
00162         //
00163         // This is all pretty simple.
00164         //
00165         // All we do is decompress the line the check is on. Then we see if there 
00166         // is a pixel at the location.
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 // Get the pixel at the point 
00197 uint8 ShapeFrame::getPixelAtPoint(sint32 x, sint32 y) const
00198 {
00199         // Add the offset
00200         x += xoff;
00201         y += yoff;
00202 
00203         // First gross culling based on dims
00204         if (x < 0 || y < 0 || x >= width || y >= height) return 0xFF;
00205 
00206         //
00207         // This is all pretty simple.
00208         //
00209         // All we do is decompress the line the check is on. Then we see if there 
00210         // is a pixel at the location. And if there is, return it
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 

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