1 #include "SWFGlyphList.h" 2 #include <SWFShapeItem.h> 3 #include "gSWF.h" 4 #include <cstring> 5 6 namespace SWF { 7 GlyphList()8 GlyphList::GlyphList() { 9 nGlyphs = 0; 10 glyphs = NULL; 11 map = 0; 12 } 13 ~GlyphList()14 GlyphList::~GlyphList() { 15 delete[] glyphs; 16 delete[] map; 17 } 18 parse(Reader * r,int end,Context * ctx)19 bool GlyphList::parse(Reader *r, int end, Context *ctx) { 20 file_offset = r->getPosition(); 21 22 int nOffsets; 23 int s=0; 24 25 if (ctx->tagVersion>1) { 26 nGlyphs = ctx->glyphCount; 27 nOffsets = nGlyphs+1; 28 } else { 29 nGlyphs = (r->getWord()/2); 30 nOffsets = nGlyphs; 31 s=1; 32 } 33 34 if (ctx->debugTrace) { 35 fprintf(stderr, "GL nGlyphs: %i, glyphs %s, map %s\n", (int)nGlyphs, ctx->wideGlyphOffsets?"wide":"narrow", ctx->wideMap?"wide":"narrow"); 36 } 37 38 int offset[nGlyphs+1]; 39 memset(offset, 0, sizeof(int)*nGlyphs+1); 40 if (ctx->wideGlyphOffsets) { 41 for (int i=s; i<nOffsets; i++) { 42 offset[i] = r->getInt(); 43 } 44 } else { 45 for (int i=s; i<nOffsets; i++) { 46 offset[i] = r->getWord(); 47 } 48 } 49 50 if (ctx->tagVersion<=1) { 51 offset[0] = r->getPosition() - file_offset; 52 offset[nOffsets] = end-file_offset; 53 } 54 55 if (ctx->debugTrace) { 56 fprintf(stderr, "Glyphs @%i offset[0]: %i\n", r->getPosition(), offset[0]); 57 } 58 glyphs = new GlyphShape[nGlyphs]; 59 for (int i=0; i<nGlyphs; i++) { 60 if (ctx->debugTrace) { 61 fprintf(stderr, "PARSE glyph #%i @%i should be %i-%i\n", i, r->getPosition(), file_offset + offset[i], file_offset + offset[i+1]); 62 } 63 if (r->getPosition() != file_offset + offset[i]) { 64 fprintf(stderr,"WARNING: wrong offset at glyph %i, ofs %i but pos %i\n", i, offset[i], r->getPosition()-file_offset); 65 } 66 glyphs[i].parse(r, file_offset + offset[i+1], ctx); 67 r->byteAlign(); 68 } 69 70 if (ctx->tagVersion>1) { 71 if (ctx->debugTrace) { 72 fprintf(stderr,"- parse GlyphMap" ); 73 } 74 map = new int[nGlyphs]; 75 if (ctx->wideMap) { 76 for (int i=0; i<nGlyphs; i++) { 77 map[i] = r->getWord(); 78 } 79 } else { 80 for (int i=0; i<nGlyphs; i++) { 81 map[i] = r->getByte(); 82 } 83 } 84 } 85 86 return r->getError() == Reader::ok; 87 } 88 dump(int n,Context * ctx)89 void GlyphList::dump(int n, Context *ctx) { 90 for (int i=0; i<n; i++) { 91 printf(" "); 92 } 93 printf("GlyphList\n"); 94 95 for (int i=0; i<nGlyphs; i++) { 96 glyphs[i].dump(n+1, ctx); 97 } 98 printf("\n"); 99 } 100 calcSize(Context * ctx,int start_at)101 size_t GlyphList::calcSize(Context *ctx, int start_at) { 102 int r=start_at; 103 104 if (ctx->tagVersion>1) { 105 r += (ctx->wideGlyphOffsets ? 4 : 2) * (nGlyphs+1) * 8; 106 } else { 107 r += (nGlyphs+1) * 16; 108 } 109 110 for (int i=0; i<nGlyphs; i++) { 111 r += glyphs[i].getSize(ctx, r); 112 if (r%8 != 0) { 113 r += 8-(r%8); 114 } 115 } 116 117 if (ctx->tagVersion>1) { 118 r += (ctx->wideMap ? 2 : 1) * nGlyphs * 8; 119 } 120 121 r += Item::getHeaderSize(r-start_at); 122 return r-start_at; 123 } 124 write(Writer * w,Context * ctx)125 void GlyphList::write(Writer *w, Context *ctx) { 126 Item::writeHeader(w, ctx, 0); 127 int ofs = 0; 128 129 if (ctx->tagVersion>1) { 130 ofs = ((ctx->wideGlyphOffsets ? 4 : 2) * (nGlyphs+1)); 131 } else { 132 ofs = (nGlyphs+1)*2; 133 } 134 135 ctx->fillBits = 1; 136 ctx->lineBits = 1; 137 138 ctx->wideGlyphOffsets ? w->putInt(ofs) : w->putWord(ofs); 139 for (int i=0; i<nGlyphs; i++) { 140 int p = glyphs[i].getSize(ctx,ofs); 141 if (p%8 != 0) { 142 p += 8-(p%8); 143 } 144 ofs += (p)/8; 145 ctx->wideGlyphOffsets ? w->putInt(ofs) : w->putWord(ofs); 146 } 147 148 ofs = w->getPosition(); 149 for (int i=0; i<nGlyphs; i++) { 150 glyphs[i].write(w, ctx); 151 w->byteAlign(); 152 } 153 154 if (ctx->tagVersion>1) { 155 for (int i=0; i<nGlyphs; i++) { 156 ctx->wideMap ? w->putWord(map[i]) : w->putByte(map[i]); 157 } 158 } 159 } 160 writeXML(xmlNodePtr xml,Context * ctx)161 void GlyphList::writeXML(xmlNodePtr xml, Context *ctx) { 162 char tmp[32]; 163 164 xmlNodePtr node = xml; 165 for (int i=0; i<nGlyphs; i++) { 166 xmlNodePtr child = xmlNewChild(node, NULL, (const xmlChar *)"Glyph", NULL); 167 glyphs[i].writeXML(child, ctx); 168 if (ctx->tagVersion>1 && map) { 169 snprintf(tmp, 32, "%i", map[i]); 170 xmlSetProp(child, (const xmlChar *)"map", (const xmlChar *)tmp); 171 } 172 } 173 } 174 parseXML(xmlNodePtr node,Context * ctx)175 void GlyphList::parseXML(xmlNodePtr node, Context *ctx) { 176 { 177 nGlyphs = 0; 178 xmlNodePtr child = node; 179 while (child) { 180 if (!strcmp((const char *)child->name, "Glyph")) { 181 nGlyphs++; 182 } 183 child = child->next; 184 } 185 ctx->glyphCount = nGlyphs; 186 187 if (ctx->tagVersion>1) { 188 map = new int[nGlyphs]; 189 memset(map, 0, sizeof(int)*nGlyphs); 190 } 191 192 glyphs = new GlyphShape[nGlyphs]; 193 child = node; 194 int i=0; 195 while (child) { 196 if (!strcmp((const char *)child->name, "Glyph")) { 197 xmlNodePtr shape = child->children; 198 while (shape) { 199 if (!strcmp((const char *)shape->name, "GlyphShape")) { 200 glyphs[i].parseXML(shape, ctx); 201 202 if (ctx->tagVersion>1) { 203 xmlChar *tmp; 204 tmp = xmlGetProp(child, (const xmlChar *)"map"); 205 if (tmp) { 206 sscanf((char*)tmp, "%i", &map[i]); 207 xmlFree( tmp ); 208 if (map[i] > 0xFF) { 209 ctx->wideMap = true; 210 } 211 } else { 212 map[i] = 0; 213 } 214 } 215 216 i++; 217 shape = NULL; 218 } else { 219 shape = shape->next; 220 } 221 } 222 } 223 child = child->next; 224 } 225 226 if (ctx->swfVersion >= 6) { 227 ctx->wideMap = true; 228 } 229 } 230 } 231 allocate(int n)232 void GlyphList::allocate(int n) { 233 delete[] map; 234 delete[] glyphs; 235 236 nGlyphs = n; 237 glyphs = new GlyphShape[nGlyphs]; 238 map = new int[nGlyphs]; 239 memset(map, 0, sizeof(int)*nGlyphs); 240 } 241 getShapeN(int n)242 GlyphShape *GlyphList::getShapeN(int n) { 243 return &glyphs[n]; 244 } 245 setMapN(int n,int m)246 void GlyphList::setMapN(int n, int m) { 247 map[n] = m; 248 } 249 250 } 251