00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #ifdef HAVE_CONFIG_H
00058 # include "config.h"
00059 #endif
00060 #if NEED_GNUG_PRAGMAS
00061 # pragma implementation
00062 #endif
00063
00064 #include "DjVuDumpHelper.h"
00065 #include "DataPool.h"
00066 #include "DjVmDir.h"
00067 #include "DjVuInfo.h"
00068 #include "IFFByteStream.h"
00069
00070
00071 #ifdef HAVE_NAMESPACES
00072 namespace DJVU {
00073 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
00074 }
00075 #endif
00076 #endif
00077
00078
00079 #ifdef putchar
00080 #undef putchar
00081 #endif
00082
00083 struct DjVmInfo
00084 {
00085 GP<DjVmDir> dir;
00086 GPMap<int,DjVmDir::File> map;
00087 };
00088
00089 inline static void
00090 putchar(ByteStream & str, char ch)
00091 {
00092 str.write(&ch, 1);
00093 }
00094
00095
00096
00097 static void
00098 display_djvu_info(ByteStream & out_str, IFFByteStream &iff,
00099 GUTF8String, size_t size, DjVmInfo&, int)
00100 {
00101 GP<DjVuInfo> ginfo=DjVuInfo::create();
00102 DjVuInfo &info=*ginfo;
00103 info.decode(*iff.get_bytestream());
00104 if (size >= 4)
00105 out_str.format( "DjVu %dx%d", info.width, info.height);
00106 if (size >= 5)
00107 out_str.format( ", v%d", info.version);
00108 if (size >= 8)
00109 out_str.format( ", %d dpi", info.dpi);
00110 if (size >= 8)
00111 out_str.format( ", gamma=%3.1f", info.gamma);
00112 }
00113
00114 static void
00115 display_djbz(ByteStream & out_str, IFFByteStream &iff,
00116 GUTF8String, size_t, DjVmInfo&, int)
00117 {
00118 out_str.format( "JB2 shared dictionary");
00119 }
00120
00121 static void
00122 display_fgbz(ByteStream & out_str, IFFByteStream &iff,
00123 GUTF8String, size_t, DjVmInfo&, int)
00124 {
00125 out_str.format( "JB2 colors data");
00126 }
00127
00128 static void
00129 display_sjbz(ByteStream & out_str, IFFByteStream &iff,
00130 GUTF8String, size_t, DjVmInfo&, int)
00131 {
00132 out_str.format( "JB2 bilevel data");
00133 }
00134
00135 static void
00136 display_smmr(ByteStream & out_str, IFFByteStream &iff,
00137 GUTF8String, size_t, DjVmInfo&, int)
00138 {
00139 out_str.format( "G4/MMR stencil data");
00140 }
00141
00142 static void
00143 display_iw4(ByteStream & out_str, IFFByteStream &iff,
00144 GUTF8String, size_t, DjVmInfo&, int)
00145 {
00146 GP<ByteStream> gbs = iff.get_bytestream();
00147 unsigned char serial = gbs->read8();
00148 unsigned char slices = gbs->read8();
00149 out_str.format( "IW4 data #%d, %d slices", serial+1, slices);
00150 if (serial == 0)
00151 {
00152 unsigned char major = gbs->read8();
00153 unsigned char minor = gbs->read8();
00154 unsigned char xhi = gbs->read8();
00155 unsigned char xlo = gbs->read8();
00156 unsigned char yhi = gbs->read8();
00157 unsigned char ylo = gbs->read8();
00158 out_str.format( ", v%d.%d (%s), %dx%d", major & 0x7f, minor,
00159 (major & 0x80 ? "b&w" : "color"), (xhi<<8)+xlo, (yhi<<8)+ylo );
00160 }
00161 }
00162
00163 static void
00164 display_djvm_dirm(ByteStream & out_str, IFFByteStream & iff,
00165 GUTF8String head, size_t, DjVmInfo& djvminfo, int)
00166 {
00167 GP<DjVmDir> dir = DjVmDir::create();
00168 dir->decode(iff.get_bytestream());
00169 GPList<DjVmDir::File> list = dir->get_files_list();
00170 if (dir->is_indirect())
00171 {
00172 out_str.format( "Document directory (indirect, %d files %d pages)",
00173 dir->get_files_num(), dir->get_pages_num());
00174 for (GPosition p=list; p; ++p)
00175 out_str.format( "\n%s%s -> %s", (const char*)head,
00176 (const char*)list[p]->get_load_name(), (const char*)list[p]->get_save_name() );
00177 }
00178 else
00179 {
00180 out_str.format( "Document directory (bundled, %d files %d pages)",
00181 dir->get_files_num(), dir->get_pages_num());
00182 djvminfo.dir = dir;
00183 djvminfo.map.empty();
00184 for (GPosition p=list; p; ++p)
00185 djvminfo.map[list[p]->offset] = list[p];
00186 }
00187 }
00188
00189 static void
00190 display_th44(ByteStream & out_str, IFFByteStream & iff,
00191 GUTF8String, size_t, DjVmInfo & djvminfo, int counter)
00192 {
00193 int start_page=-1;
00194 if (djvminfo.dir)
00195 {
00196 GPList<DjVmDir::File> files_list=djvminfo.dir->get_files_list();
00197 for(GPosition pos=files_list;pos;++pos)
00198 {
00199 GP<DjVmDir::File> frec=files_list[pos];
00200 if (iff.tell()>=frec->offset &&
00201 iff.tell()<frec->offset+frec->size)
00202 {
00203 while(pos && !files_list[pos]->is_page())
00204 ++pos;
00205 if (pos)
00206 start_page=files_list[pos]->get_page_num();
00207 break;
00208 }
00209 }
00210 }
00211 if (start_page>=0)
00212 out_str.format( "Thumbnail icon for page %d", start_page+counter+1);
00213 else
00214 out_str.format( "Thumbnail icon");
00215 }
00216
00217 static void
00218 display_incl(ByteStream & out_str, IFFByteStream & iff,
00219 GUTF8String, size_t, DjVmInfo&, int)
00220 {
00221 GUTF8String name;
00222 char ch;
00223 while(iff.read(&ch, 1) && ch!='\n')
00224 name += ch;
00225 out_str.format( "Indirection chunk --> {%s}", (const char *) name);
00226 }
00227
00228 static void
00229 display_anno(ByteStream & out_str, IFFByteStream &iff,
00230 GUTF8String, size_t, DjVmInfo&, int)
00231 {
00232 out_str.format( "Page annotation");
00233 GUTF8String id;
00234 iff.short_id(id);
00235 out_str.format( " (hyperlinks, etc.)");
00236 }
00237
00238 static void
00239 display_text(ByteStream & out_str, IFFByteStream &iff,
00240 GUTF8String, size_t, DjVmInfo&, int)
00241 {
00242 out_str.format( "Hidden text");
00243 GUTF8String id;
00244 iff.short_id(id);
00245 out_str.format( " (text, etc.)");
00246 }
00247
00248 struct displaysubr
00249 {
00250 const char *id;
00251 void (*subr)(ByteStream &, IFFByteStream &, GUTF8String,
00252 size_t, DjVmInfo&, int counter);
00253 };
00254
00255 static displaysubr disproutines[] =
00256 {
00257 { "DJVU.INFO", display_djvu_info },
00258 { "DJVU.Smmr", display_smmr },
00259 { "DJVU.Sjbz", display_sjbz },
00260 { "DJVU.Djbz", display_djbz },
00261 { "DJVU.FG44", display_iw4 },
00262 { "DJVU.BG44", display_iw4 },
00263 { "DJVU.FGbz", display_fgbz },
00264 { "DJVI.Sjbz", display_sjbz },
00265 { "DJVI.Djbz", display_djbz },
00266 { "DJVI.FGbz", display_fgbz },
00267 { "DJVI.FG44", display_iw4 },
00268 { "DJVI.BG44", display_iw4 },
00269 { "BM44.BM44", display_iw4 },
00270 { "PM44.PM44", display_iw4 },
00271 { "DJVM.DIRM", display_djvm_dirm },
00272 { "THUM.TH44", display_th44 },
00273 { "INCL", display_incl },
00274 { "ANTa", display_anno },
00275 { "ANTz", display_anno },
00276 { "TXTa", display_text },
00277 { "TXTz", display_text },
00278 { 0, 0 },
00279 };
00280
00281
00282
00283 static void
00284 display_chunks(ByteStream & out_str, IFFByteStream &iff,
00285 const GUTF8String &head, DjVmInfo djvminfo)
00286 {
00287 size_t size;
00288 GUTF8String id, fullid;
00289 GUTF8String head2 = head + " ";
00290 GPMap<int,DjVmDir::File> djvmmap;
00291 int rawoffset;
00292 GMap<GUTF8String, int> counters;
00293
00294 while ((size = iff.get_chunk(id, &rawoffset)))
00295 {
00296 if (!counters.contains(id)) counters[id]=0;
00297 else counters[id]++;
00298
00299 GUTF8String msg;
00300 msg.format("%s%s [%d] ", (const char *)head, (const char *)id, size);
00301 out_str.format( "%s", (const char *)msg);
00302
00303 if (djvminfo.dir)
00304 {
00305 GP<DjVmDir::File> rec = djvminfo.map[rawoffset];
00306 if (rec)
00307 out_str.format( "{%s}", (const char*) rec->get_load_name());
00308 }
00309
00310 iff.full_id(fullid);
00311 for (int i=0; disproutines[i].id; i++)
00312 if (fullid == disproutines[i].id || id == disproutines[i].id)
00313 {
00314 int n = msg.length();
00315 while (n++ < 14+(int) head.length()) putchar(out_str, ' ');
00316 if (!iff.composite()) out_str.format( " ");
00317 (*disproutines[i].subr)(out_str, iff, head2,
00318 size, djvminfo, counters[id]);
00319 break;
00320 }
00321
00322 out_str.format( "\n");
00323 if (iff.composite())
00324 display_chunks(out_str, iff, head2, djvminfo);
00325
00326 iff.close_chunk();
00327 }
00328 }
00329
00330 GP<ByteStream>
00331 DjVuDumpHelper::dump(const GP<DataPool> & pool)
00332 {
00333 return dump(pool->get_stream());
00334 }
00335
00336 GP<ByteStream>
00337 DjVuDumpHelper::dump(GP<ByteStream> gstr)
00338 {
00339 GP<ByteStream> out_str=ByteStream::create();
00340 GUTF8String head=" ";
00341 GP<IFFByteStream> iff=IFFByteStream::create(gstr);
00342 DjVmInfo djvminfo;
00343 display_chunks(*out_str, *iff, head, djvminfo);
00344 return out_str;
00345 }
00346
00347
00348 #ifdef HAVE_NAMESPACES
00349 }
00350 # ifndef NOT_USING_DJVU_NAMESPACE
00351 using namespace DJVU;
00352 # endif
00353 #endif