1 //C- -*- C++ -*-
2 //C- -------------------------------------------------------------------
3 //C- DjVuLibre-3.5
4 //C- Copyright (c) 2002 Leon Bottou and Yann Le Cun.
5 //C- Copyright (c) 2001 AT&T
6 //C-
7 //C- This software is subject to, and may be distributed under, the
8 //C- GNU General Public License, either Version 2 of the license,
9 //C- or (at your option) any later version. The license should have
10 //C- accompanied the software or you may obtain a copy of the license
11 //C- from the Free Software Foundation at http://www.fsf.org .
12 //C-
13 //C- This program is distributed in the hope that it will be useful,
14 //C- but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 //C- GNU General Public License for more details.
17 //C-
18 //C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
19 //C- Lizardtech Software. Lizardtech Software has authorized us to
20 //C- replace the original DjVu(r) Reference Library notice by the following
21 //C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
22 //C-
23 //C- ------------------------------------------------------------------
24 //C- | DjVu (r) Reference Library (v. 3.5)
25 //C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
26 //C- | The DjVu Reference Library is protected by U.S. Pat. No.
27 //C- | 6,058,214 and patents pending.
28 //C- |
29 //C- | This software is subject to, and may be distributed under, the
30 //C- | GNU General Public License, either Version 2 of the license,
31 //C- | or (at your option) any later version. The license should have
32 //C- | accompanied the software or you may obtain a copy of the license
33 //C- | from the Free Software Foundation at http://www.fsf.org .
34 //C- |
35 //C- | The computer code originally released by LizardTech under this
36 //C- | license and unmodified by other parties is deemed "the LIZARDTECH
37 //C- | ORIGINAL CODE." Subject to any third party intellectual property
38 //C- | claims, LizardTech grants recipient a worldwide, royalty-free,
39 //C- | non-exclusive license to make, use, sell, or otherwise dispose of
40 //C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the
41 //C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU
42 //C- | General Public License. This grant only confers the right to
43 //C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to
44 //C- | the extent such infringement is reasonably necessary to enable
45 //C- | recipient to make, have made, practice, sell, or otherwise dispose
46 //C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to
47 //C- | any greater extent that may be necessary to utilize further
48 //C- | modifications or combinations.
49 //C- |
50 //C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
51 //C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
52 //C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
53 //C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
54 //C- +------------------------------------------------------------------
55
56 #ifdef HAVE_CONFIG_H
57 # include "config.h"
58 #endif
59 #if NEED_GNUG_PRAGMAS
60 # pragma implementation
61 #endif
62
63 #include "DjVuDumpHelper.h"
64 #include "DataPool.h"
65 #include "DjVmDir.h"
66 #include "DjVuInfo.h"
67 #include "IFFByteStream.h"
68
69
70 #ifdef HAVE_NAMESPACES
71 namespace DJVU {
72 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
73 }
74 #endif
75 #endif
76
77
78 #ifdef putchar
79 #undef putchar
80 #endif
81
82 struct DjVmInfo
83 {
84 GP<DjVmDir> dir;
85 GPMap<int,DjVmDir::File> map;
86 };
87
88 inline static void
putchar(ByteStream & str,char ch)89 putchar(ByteStream & str, char ch)
90 {
91 str.write(&ch, 1);
92 }
93
94 // ---------- ROUTINES FOR SUMMARIZING CHUNK DATA
95
96 static void
display_djvu_info(ByteStream & out_str,IFFByteStream & iff,GUTF8String,size_t size,DjVmInfo &,int)97 display_djvu_info(ByteStream & out_str, IFFByteStream &iff,
98 GUTF8String, size_t size, DjVmInfo&, int)
99 {
100 GP<DjVuInfo> ginfo=DjVuInfo::create();
101 DjVuInfo &info=*ginfo;
102 info.decode(*iff.get_bytestream());
103 if (size >= 4)
104 out_str.format( "DjVu %dx%d", info.width, info.height);
105 if (size >= 5)
106 out_str.format( ", v%d", info.version);
107 if (size >= 8)
108 out_str.format( ", %d dpi", info.dpi);
109 if (size >= 9)
110 out_str.format( ", gamma=%3.1f", info.gamma);
111 }
112
113 static void
display_djbz(ByteStream & out_str,IFFByteStream & iff,GUTF8String,size_t,DjVmInfo &,int)114 display_djbz(ByteStream & out_str, IFFByteStream &iff,
115 GUTF8String, size_t, DjVmInfo&, int)
116 {
117 out_str.format( "JB2 shared dictionary");
118 }
119
120 static void
display_fgbz(ByteStream & out_str,IFFByteStream & iff,GUTF8String,size_t,DjVmInfo &,int)121 display_fgbz(ByteStream & out_str, IFFByteStream &iff,
122 GUTF8String, size_t, DjVmInfo&, int)
123 {
124 GP<ByteStream> gbs = iff.get_bytestream();
125 int version = gbs->read8();
126 int size = gbs->read16();
127 out_str.format( "JB2 colors data, v%d, %d colors",
128 version & 0x7f, size);
129 }
130
131 static void
display_sjbz(ByteStream & out_str,IFFByteStream & iff,GUTF8String,size_t,DjVmInfo &,int)132 display_sjbz(ByteStream & out_str, IFFByteStream &iff,
133 GUTF8String, size_t, DjVmInfo&, int)
134 {
135 out_str.format( "JB2 bilevel data");
136 }
137
138 static void
display_smmr(ByteStream & out_str,IFFByteStream & iff,GUTF8String,size_t,DjVmInfo &,int)139 display_smmr(ByteStream & out_str, IFFByteStream &iff,
140 GUTF8String, size_t, DjVmInfo&, int)
141 {
142 out_str.format( "G4/MMR stencil data");
143 }
144
145 static void
display_iw4(ByteStream & out_str,IFFByteStream & iff,GUTF8String,size_t,DjVmInfo &,int)146 display_iw4(ByteStream & out_str, IFFByteStream &iff,
147 GUTF8String, size_t, DjVmInfo&, int)
148 {
149 GP<ByteStream> gbs = iff.get_bytestream();
150 unsigned char serial = gbs->read8();
151 unsigned char slices = gbs->read8();
152 out_str.format( "IW4 data #%d, %d slices", serial+1, slices);
153 if (serial == 0)
154 {
155 unsigned char major = gbs->read8();
156 unsigned char minor = gbs->read8();
157 unsigned char xhi = gbs->read8();
158 unsigned char xlo = gbs->read8();
159 unsigned char yhi = gbs->read8();
160 unsigned char ylo = gbs->read8();
161 out_str.format( ", v%d.%d (%s), %dx%d", major & 0x7f, minor,
162 (major & 0x80 ? "b&w" : "color"),
163 (xhi<<8)+xlo, (yhi<<8)+ylo );
164 }
165 }
166
167 static void
display_djvm_dirm(ByteStream & out_str,IFFByteStream & iff,GUTF8String head,size_t,DjVmInfo & djvminfo,int)168 display_djvm_dirm(ByteStream & out_str, IFFByteStream & iff,
169 GUTF8String head, size_t, DjVmInfo& djvminfo, int)
170 {
171 GP<DjVmDir> dir = DjVmDir::create();
172 dir->decode(iff.get_bytestream());
173 GPList<DjVmDir::File> list = dir->get_files_list();
174 if (dir->is_indirect())
175 {
176 out_str.format( "Document directory (indirect, %d files %d pages)",
177 dir->get_files_num(), dir->get_pages_num());
178 for (GPosition p=list; p; ++p)
179 out_str.format( "\n%s%s -> %s", (const char*)head,
180 (const char*)list[p]->get_load_name(), (const char*)list[p]->get_save_name() );
181 }
182 else
183 {
184 out_str.format( "Document directory (bundled, %d files %d pages)",
185 dir->get_files_num(), dir->get_pages_num());
186 djvminfo.dir = dir;
187 djvminfo.map.empty();
188 for (GPosition p=list; p; ++p)
189 djvminfo.map[list[p]->offset] = list[p];
190 }
191 }
192
193 static void
display_th44(ByteStream & out_str,IFFByteStream & iff,GUTF8String,size_t,DjVmInfo & djvminfo,int counter)194 display_th44(ByteStream & out_str, IFFByteStream & iff,
195 GUTF8String, size_t, DjVmInfo & djvminfo, int counter)
196 {
197 int start_page=-1;
198 if (djvminfo.dir)
199 {
200 GPList<DjVmDir::File> files_list=djvminfo.dir->get_files_list();
201 for(GPosition pos=files_list;pos;++pos)
202 {
203 GP<DjVmDir::File> frec=files_list[pos];
204 if (iff.tell()>=frec->offset &&
205 iff.tell()<frec->offset+frec->size)
206 {
207 while(pos && !files_list[pos]->is_page())
208 ++pos;
209 if (pos)
210 start_page=files_list[pos]->get_page_num();
211 break;
212 }
213 }
214 }
215 if (start_page>=0)
216 out_str.format( "Thumbnail icon for page %d", start_page+counter+1);
217 else
218 out_str.format( "Thumbnail icon");
219 }
220
221 static void
display_incl(ByteStream & out_str,IFFByteStream & iff,GUTF8String,size_t,DjVmInfo &,int)222 display_incl(ByteStream & out_str, IFFByteStream & iff,
223 GUTF8String, size_t, DjVmInfo&, int)
224 {
225 GUTF8String name;
226 char ch;
227 while(iff.read(&ch, 1) && ch!='\n')
228 name += ch;
229 out_str.format( "Indirection chunk --> {%s}", (const char *) name);
230 }
231
232 static void
display_anno(ByteStream & out_str,IFFByteStream & iff,GUTF8String,size_t,DjVmInfo &,int)233 display_anno(ByteStream & out_str, IFFByteStream &iff,
234 GUTF8String, size_t, DjVmInfo&, int)
235 {
236 out_str.format( "Page annotation");
237 GUTF8String id;
238 iff.short_id(id);
239 out_str.format( " (hyperlinks, etc.)");
240 }
241
242 static void
display_text(ByteStream & out_str,IFFByteStream & iff,GUTF8String,size_t,DjVmInfo &,int)243 display_text(ByteStream & out_str, IFFByteStream &iff,
244 GUTF8String, size_t, DjVmInfo&, int)
245 {
246 out_str.format( "Hidden text");
247 GUTF8String id;
248 iff.short_id(id);
249 out_str.format( " (text, etc.)");
250 }
251
252 struct displaysubr
253 {
254 const char *id;
255 void (*subr)(ByteStream &, IFFByteStream &, GUTF8String,
256 size_t, DjVmInfo&, int counter);
257 };
258
259 static displaysubr disproutines[] =
260 {
261 { "DJVU.INFO", display_djvu_info },
262 { "DJVU.Smmr", display_smmr },
263 { "DJVU.Sjbz", display_sjbz },
264 { "DJVU.Djbz", display_djbz },
265 { "DJVU.FG44", display_iw4 },
266 { "DJVU.BG44", display_iw4 },
267 { "DJVU.FGbz", display_fgbz },
268 { "DJVI.Sjbz", display_sjbz },
269 { "DJVI.Djbz", display_djbz },
270 { "DJVI.FGbz", display_fgbz },
271 { "DJVI.FG44", display_iw4 },
272 { "DJVI.BG44", display_iw4 },
273 { "BM44.BM44", display_iw4 },
274 { "PM44.PM44", display_iw4 },
275 { "DJVM.DIRM", display_djvm_dirm },
276 { "THUM.TH44", display_th44 },
277 { "INCL", display_incl },
278 { "ANTa", display_anno },
279 { "ANTz", display_anno },
280 { "TXTa", display_text },
281 { "TXTz", display_text },
282 { 0, 0 },
283 };
284
285 // ---------- ROUTINES FOR DISPLAYING CHUNK STRUCTURE
286
287 static void
display_chunks(ByteStream & out_str,IFFByteStream & iff,const GUTF8String & head,DjVmInfo djvminfo)288 display_chunks(ByteStream & out_str, IFFByteStream &iff,
289 const GUTF8String &head, DjVmInfo djvminfo)
290 {
291 size_t size;
292 GUTF8String id, fullid;
293 GUTF8String head2 = head + " ";
294 GPMap<int,DjVmDir::File> djvmmap;
295 int rawoffset;
296 GMap<GUTF8String, int> counters;
297
298 while ((size = iff.get_chunk(id, &rawoffset)))
299 {
300 if (!counters.contains(id)) counters[id]=0;
301 else counters[id]++;
302
303 GUTF8String msg;
304 msg.format("%s%s [%d] ", (const char *)head, (const char *)id, size);
305 out_str.format( "%s", (const char *)msg);
306 // Display DJVM is when adequate
307 if (djvminfo.dir)
308 {
309 GP<DjVmDir::File> rec = djvminfo.map[rawoffset];
310 if (rec)
311 {
312 GUTF8String id = rec->get_load_name();
313 GUTF8String title = rec->get_title();
314 out_str.format( "{%s}", (const char*) id);
315 if (rec->is_include())
316 out_str.format(" [I]");
317 if (rec->is_thumbnails())
318 out_str.format(" [T]");
319 if (rec->is_shared_anno())
320 out_str.format(" [S]");
321 if (rec->is_page())
322 out_str.format(" [P%d]", rec->get_page_num()+1);
323 if (id != title)
324 out_str.format(" (%s)", (const char*)title);
325 }
326 }
327 // Test chunk type
328 iff.full_id(fullid);
329 for (int i=0; disproutines[i].id; i++)
330 if (fullid == disproutines[i].id || id == disproutines[i].id)
331 {
332 int n = msg.length();
333 while (n++ < 14+(int) head.length()) putchar(out_str, ' ');
334 if (!iff.composite()) out_str.format( " ");
335 (*disproutines[i].subr)(out_str, iff, head2,
336 size, djvminfo, counters[id]);
337 break;
338 }
339 // Default display of composite chunk
340 out_str.format( "\n");
341 if (iff.composite())
342 display_chunks(out_str, iff, head2, djvminfo);
343 // Terminate
344 iff.close_chunk();
345 }
346 }
347
348 GP<ByteStream>
dump(const GP<DataPool> & pool)349 DjVuDumpHelper::dump(const GP<DataPool> & pool)
350 {
351 return dump(pool->get_stream());
352 }
353
354 GP<ByteStream>
dump(GP<ByteStream> gstr)355 DjVuDumpHelper::dump(GP<ByteStream> gstr)
356 {
357 GP<ByteStream> out_str=ByteStream::create();
358 GUTF8String head=" ";
359 GP<IFFByteStream> iff=IFFByteStream::create(gstr);
360 DjVmInfo djvminfo;
361 display_chunks(*out_str, *iff, head, djvminfo);
362 return out_str;
363 }
364
365
366 #ifdef HAVE_NAMESPACES
367 }
368 # ifndef NOT_USING_DJVU_NAMESPACE
369 using namespace DJVU;
370 # endif
371 #endif
372