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 // From: Leon Bottou, 1/31/2002
64 // Lizardtech has split the corresponding cpp file into a decoder and an encoder.
65 // Only superficial changes.  The meat is mine.
66 
67 #include "JB2Image.h"
68 #include "GThreads.h"
69 #include "GRect.h"
70 #include "GBitmap.h"
71 #include <string.h>
72 
73 
74 #ifdef HAVE_NAMESPACES
75 namespace DJVU {
76 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
77 }
78 #endif
79 #endif
80 
81 ////////////////////////////////////////
82 //// CLASS JB2Codec::Decode:  DECLARATION
83 ////////////////////////////////////////
84 
85 // This class is accessed via the decode
86 // functions of class JB2Image
87 
88 
89 //**** Class JB2Codec
90 // This class implements the JB2 decoder.
91 // Contains all contextual information for decoding a JB2Image.
92 
93 class JB2Dict::JB2Codec::Decode : public JB2Dict::JB2Codec
94 {
95 public:
96   Decode(void);
97   void init(const GP<ByteStream> &gbs);
98 // virtual
99   void code(const GP<JB2Image> &jim);
code(JB2Image * jim)100   void code(JB2Image *jim) {const GP<JB2Image> gjim(jim);code(gjim);}
101   void code(const GP<JB2Dict> &jim);
code(JB2Dict * jim)102   void code(JB2Dict *jim) {const GP<JB2Dict> gjim(jim);code(gjim);}
103   void set_dict_callback(JB2DecoderCallback *cb, void *arg);
104 protected:
105   int CodeNum(const int lo, const int hi, NumContext &ctx);
106 
107 // virtual
108   bool CodeBit(const bool bit, BitContext &ctx);
109   void code_comment(GUTF8String &comment);
110   void code_record_type(int &rectype);
111   int code_match_index(int &index, JB2Dict &jim);
112   void code_inherited_shape_count(JB2Dict &jim);
113   void code_image_size(JB2Dict &jim);
114   void code_image_size(JB2Image &jim);
115   void code_absolute_location(JB2Blit *jblt,  int rows, int columns);
116   void code_absolute_mark_size(GBitmap &bm, int border=0);
117   void code_relative_mark_size(GBitmap &bm, int cw, int ch, int border=0);
118   void code_bitmap_directly(GBitmap &bm,const int dw, int dy,
119     unsigned char *up2, unsigned char *up1, unsigned char *up0 );
120   void code_bitmap_by_cross_coding (GBitmap &bm, GBitmap &cbm,
121     const int xd2c, const int dw, int dy, int cy,
122     unsigned char *up1, unsigned char *up0, unsigned char *xup1,
123     unsigned char *xup0, unsigned char *xdn1 );
124   int get_diff(const int x_diff,NumContext &rel_loc);
125 
126 private:
127   GP<ZPCodec> gzp;
128   JB2DecoderCallback *cbfunc;
129   void *cbarg;
130 };
131 
132 ////////////////////////////////////////
133 //// CLASS JB2DICT: IMPLEMENTATION
134 ////////////////////////////////////////
135 
136 
JB2Dict()137 JB2Dict::JB2Dict()
138   : inherited_shapes(0)
139 {
140 }
141 
142 void
init()143 JB2Dict::init()
144 {
145   inherited_shapes = 0;
146   inherited_dict = 0;
147   shapes.empty();
148 }
149 
150 JB2Shape &
get_shape(const int shapeno)151 JB2Dict::get_shape(const int shapeno)
152 {
153   JB2Shape *retval;
154   if(shapeno >= inherited_shapes)
155   {
156     retval=&shapes[shapeno - inherited_shapes];
157   }else if(inherited_dict)
158   {
159     retval=&(inherited_dict->get_shape(shapeno));
160   }else
161   {
162     G_THROW( ERR_MSG("JB2Image.bad_number") );
163   }
164   return *retval;
165 }
166 
167 const JB2Shape &
get_shape(const int shapeno) const168 JB2Dict::get_shape(const int shapeno) const
169 {
170   const JB2Shape *retval;
171   if(shapeno >= inherited_shapes)
172   {
173     retval=&shapes[shapeno - inherited_shapes];
174   }else if(inherited_dict)
175   {
176     retval=&(inherited_dict->get_shape(shapeno));
177   }else
178   {
179     G_THROW( ERR_MSG("JB2Image.bad_number") );
180   }
181   return *retval;
182 }
183 
184 void
set_inherited_dict(const GP<JB2Dict> & dict)185 JB2Dict::set_inherited_dict(const GP<JB2Dict> &dict)
186 {
187   if (shapes.size() > 0)
188     G_THROW( ERR_MSG("JB2Image.cant_set") );
189   if (inherited_dict)
190     G_THROW( ERR_MSG("JB2Image.cant_change") );
191   inherited_dict = dict;
192   inherited_shapes = dict->get_shape_count();
193   // Make sure that inherited bitmaps are marked as shared
194   for (int i=0; i<inherited_shapes; i++)
195     {
196       JB2Shape &jshp = dict->get_shape(i);
197       if (jshp.bits) jshp.bits->share();
198     }
199 }
200 
201 void
compress()202 JB2Dict::compress()
203 {
204   for (int i=shapes.lbound(); i<=shapes.hbound(); i++)
205     shapes[i].bits->compress();
206 }
207 
208 unsigned int
get_memory_usage() const209 JB2Dict::get_memory_usage() const
210 {
211   unsigned int usage = sizeof(JB2Dict);
212   usage += sizeof(JB2Shape) * shapes.size();
213   for (int i=shapes.lbound(); i<=shapes.hbound(); i++)
214     if (shapes[i].bits)
215       usage += shapes[i].bits->get_memory_usage();
216   return usage;
217 }
218 
219 int
add_shape(const JB2Shape & shape)220 JB2Dict::add_shape(const JB2Shape &shape)
221 {
222   if (shape.parent >= get_shape_count())
223     G_THROW( ERR_MSG("JB2Image.bad_parent_shape") );
224   int index = shapes.size();
225   shapes.touch(index);
226   shapes[index] = shape;
227   return index + inherited_shapes;
228 }
229 
230 void
decode(const GP<ByteStream> & gbs,JB2DecoderCallback * cb,void * arg)231 JB2Dict::decode(const GP<ByteStream> &gbs, JB2DecoderCallback *cb, void *arg)
232 {
233   init();
234   JB2Codec::Decode codec;
235   codec.init(gbs);
236   codec.set_dict_callback(cb,arg);
237   codec.code(this);
238 }
239 
240 
241 
242 ////////////////////////////////////////
243 //// CLASS JB2IMAGE: IMPLEMENTATION
244 ////////////////////////////////////////
245 
246 
JB2Image(void)247 JB2Image::JB2Image(void)
248   : width(0), height(0), reproduce_old_bug(false)
249 {
250 }
251 
252 void
init(void)253 JB2Image::init(void)
254 {
255   width = height = 0;
256   blits.empty();
257   JB2Dict::init();
258 }
259 
260 unsigned int
get_memory_usage() const261 JB2Image::get_memory_usage() const
262 {
263   unsigned int usage = JB2Dict::get_memory_usage();
264   usage += sizeof(JB2Image) - sizeof(JB2Dict);
265   usage += sizeof(JB2Blit) * blits.size();
266   return usage;
267 }
268 
269 void
set_dimension(int awidth,int aheight)270 JB2Image::set_dimension(int awidth, int aheight)
271 {
272   width = awidth;
273   height = aheight;
274 }
275 
276 int
add_blit(const JB2Blit & blit)277 JB2Image::add_blit(const JB2Blit &blit)
278 {
279   if (blit.shapeno >= (unsigned int)get_shape_count())
280     G_THROW( ERR_MSG("JB2Image.bad_shape") );
281   int index = blits.size();
282   blits.touch(index);
283   blits[index] = blit;
284   return index;
285 }
286 
287 GP<GBitmap>
get_bitmap(int subsample,int align) const288 JB2Image::get_bitmap(int subsample, int align) const
289 {
290   if (width==0 || height==0)
291     G_THROW( ERR_MSG("JB2Image.cant_create") );
292   int swidth = (width + subsample - 1) / subsample;
293   int sheight = (height + subsample - 1) / subsample;
294   int border = ((swidth + align - 1) & ~(align - 1)) - swidth;
295   GP<GBitmap> bm = GBitmap::create(sheight, swidth, border);
296   bm->set_grays(1+subsample*subsample);
297   for (int blitno = 0; blitno < get_blit_count(); blitno++)
298     {
299       const JB2Blit *pblit = get_blit(blitno);
300       const JB2Shape  &pshape = get_shape(pblit->shapeno);
301       if (pshape.bits)
302         bm->blit(pshape.bits, pblit->left, pblit->bottom, subsample);
303     }
304   return bm;
305 }
306 
307 GP<GBitmap>
get_bitmap(const GRect & rect,int subsample,int align,int dispy) const308 JB2Image::get_bitmap(const GRect &rect, int subsample, int align, int dispy) const
309 {
310   if (width==0 || height==0)
311     G_THROW( ERR_MSG("JB2Image.cant_create") );
312   int rxmin = rect.xmin * subsample;
313   int rymin = rect.ymin * subsample;
314   int swidth = rect.width();
315   int sheight = rect.height();
316   int border = ((swidth + align - 1) & ~(align - 1)) - swidth;
317   GP<GBitmap> bm = GBitmap::create(sheight, swidth, border);
318   bm->set_grays(1+subsample*subsample);
319   for (int blitno = 0; blitno < get_blit_count(); blitno++)
320     {
321       const JB2Blit *pblit = get_blit(blitno);
322       const JB2Shape  &pshape = get_shape(pblit->shapeno);
323       if (pshape.bits)
324         bm->blit(pshape.bits, pblit->left-rxmin, pblit->bottom-rymin+dispy, subsample);
325     }
326   return bm;
327 }
328 
329 void
decode(const GP<ByteStream> & gbs,JB2DecoderCallback * cb,void * arg)330 JB2Image::decode(const GP<ByteStream> &gbs, JB2DecoderCallback *cb, void *arg)
331 {
332   init();
333   JB2Codec::Decode codec;
334   codec.init(gbs);
335   codec.set_dict_callback(cb,arg);
336   codec.code(this);
337 }
338 
339 
340 
341 ////////////////////////////////////////
342 //// CLASS JB2CODEC : IMPLEMENTATION
343 ////////////////////////////////////////
344 
345 
346 
347 #define START_OF_DATA                   (0)
348 #define NEW_MARK                        (1)
349 #define NEW_MARK_LIBRARY_ONLY           (2)
350 #define NEW_MARK_IMAGE_ONLY             (3)
351 #define MATCHED_REFINE                  (4)
352 #define MATCHED_REFINE_LIBRARY_ONLY     (5)
353 #define MATCHED_REFINE_IMAGE_ONLY       (6)
354 #define MATCHED_COPY                    (7)
355 #define NON_MARK_DATA                   (8)
356 #define REQUIRED_DICT_OR_RESET          (9)
357 #define PRESERVED_COMMENT               (10)
358 #define END_OF_DATA                     (11)
359 
360 
361 
362 // STATIC DATA MEMBERS
363 
364 static const int BIGPOSITIVE = 262142;
365 static const int BIGNEGATIVE = -262143;
366 static const int CELLCHUNK = 20000;
367 static const int CELLEXTRA =   500;
368 
369 
370 // CONSTRUCTOR
371 
Decode(void)372 JB2Dict::JB2Codec::Decode::Decode(void)
373 : JB2Dict::JB2Codec(0), cbfunc(0), cbarg(0) {}
374 
375 void
init(const GP<ByteStream> & gbs)376 JB2Dict::JB2Codec::Decode::init(const GP<ByteStream> &gbs)
377 {
378   gzp=ZPCodec::create(gbs,false,true);
379 }
380 
JB2Codec(const bool xencoding)381 JB2Dict::JB2Codec::JB2Codec(const bool xencoding)
382   : encoding(xencoding),
383     cur_ncell(0),
384     gbitcells(bitcells,CELLCHUNK+CELLEXTRA),
385     gleftcell(leftcell,CELLCHUNK+CELLEXTRA),
386     grightcell(rightcell,CELLCHUNK+CELLEXTRA),
387     refinementp(false),
388     gotstartrecordp(0),
389     dist_comment_byte(0),
390     dist_comment_length(0),
391     dist_record_type(0),
392     dist_match_index(0),
393     dist_refinement_flag(0),
394     abs_loc_x(0),
395     abs_loc_y(0),
396     abs_size_x(0),
397     abs_size_y(0),
398     image_size_dist(0),
399     inherited_shape_count_dist(0),
400     offset_type_dist(0),
401     rel_loc_x_current(0),
402     rel_loc_x_last(0),
403     rel_loc_y_current(0),
404     rel_loc_y_last(0),
405     rel_size_x(0),
406     rel_size_y(0)
407 {
408   memset(bitdist, 0, sizeof(bitdist));
409   memset(cbitdist, 0, sizeof(cbitdist));
410   // Initialize numcoder
411   bitcells[0] = 0; // dummy cell
412   leftcell[0] = rightcell[0] = 0;
413   cur_ncell = 1;
414 }
415 
~JB2Codec()416 JB2Dict::JB2Codec::~JB2Codec() {}
417 
418 void
reset_numcoder()419 JB2Dict::JB2Codec::reset_numcoder()
420 {
421   dist_comment_byte = 0;
422   dist_comment_length = 0;
423   dist_record_type = 0;
424   dist_match_index = 0;
425   abs_loc_x = 0;
426   abs_loc_y = 0;
427   abs_size_x = 0;
428   abs_size_y = 0;
429   image_size_dist = 0;
430   inherited_shape_count_dist = 0;
431   rel_loc_x_current = 0;
432   rel_loc_x_last = 0;
433   rel_loc_y_current = 0;
434   rel_loc_y_last = 0;
435   rel_size_x = 0;
436   rel_size_y = 0;
437   gbitcells.clear();
438   gleftcell.clear();
439   grightcell.clear();
440   cur_ncell = 1;
441 }
442 
443 
444 void
set_dict_callback(JB2DecoderCallback * cb,void * arg)445 JB2Dict::JB2Codec::Decode::set_dict_callback(JB2DecoderCallback *cb, void *arg)
446 {
447   cbfunc = cb;
448   cbarg = arg;
449 }
450 
451 
452 // CODE NUMBERS
453 
454 inline bool
CodeBit(const bool,BitContext & ctx)455 JB2Dict::JB2Codec::Decode::CodeBit(const bool, BitContext &ctx)
456 {
457   return gzp->decoder(ctx)?true:false;
458 }
459 
460 int
CodeNum(int low,int high,NumContext & ctx)461 JB2Dict::JB2Codec::Decode::CodeNum(int low, int high, NumContext &ctx)
462 {
463   return JB2Codec::CodeNum(low,high,&ctx,0);
464 }
465 
466 int
CodeNum(int low,int high,NumContext * pctx,int v)467 JB2Dict::JB2Codec::CodeNum(int low, int high, NumContext *pctx, int v)
468 {
469   bool negative=false;
470   int cutoff;
471   // Check
472   if (!pctx || ((int)*pctx >= cur_ncell))
473     G_THROW( ERR_MSG("JB2Image.bad_numcontext") );
474   // Start all phases
475   cutoff = 0;
476   for(int phase=1,range=0xffffffff;range != 1;)
477     {
478       if (! *pctx)
479         {
480           const int max_ncell=gbitcells;
481           if (cur_ncell >= max_ncell)
482             {
483               const int nmax_ncell = max_ncell+CELLCHUNK;
484               gbitcells.resize(nmax_ncell);
485               gleftcell.resize(nmax_ncell);
486               grightcell.resize(nmax_ncell);
487             }
488           *pctx = cur_ncell ++;
489           bitcells[*pctx] = 0;
490           leftcell[*pctx] = rightcell[*pctx] = 0;
491         }
492       // encode
493       const bool decision = encoding
494         ? ((low < cutoff && high >= cutoff)
495           ? CodeBit((v>=cutoff),bitcells[*pctx])
496           : (v >= cutoff))
497         : ((low>=cutoff)||((high>=cutoff)&&CodeBit(false,bitcells[*pctx])));
498       // context for new bit
499       pctx = decision?(&rightcell[*pctx]):(&leftcell[*pctx]);
500       // phase dependent part
501       switch (phase)
502         {
503 	case 1:
504           negative = !decision;
505           if (negative)
506             {
507               if (encoding)
508                 v = - v - 1;
509               const int temp = - low - 1;
510               low = - high - 1;
511               high = temp;
512 	    }
513           phase = 2; cutoff =  1;
514           break;
515 
516 	case 2:
517           if (!decision)
518             {
519               phase = 3;
520               range = (cutoff + 1) / 2;
521               if (range == 1)
522                 cutoff = 0;
523               else
524                 cutoff -= range / 2;
525 	    }
526           else
527             {
528               cutoff += cutoff + 1;
529             }
530           break;
531 
532 	case 3:
533           range /= 2;
534           if (range != 1)
535             {
536               if (!decision)
537                 cutoff -= range / 2;
538               else
539                 cutoff += range / 2;
540 	    }
541           else if (!decision)
542             {
543                 cutoff --;
544 	    }
545           break;
546 	}
547     }
548     return (negative)?(- cutoff - 1):cutoff;
549 }
550 
551 
552 
553 // CODE COMMENTS
554 
555 void
code_comment(GUTF8String & comment)556 JB2Dict::JB2Codec::Decode::code_comment(GUTF8String &comment)
557 {
558       int size=CodeNum(0, BIGPOSITIVE, dist_comment_length);
559       comment.empty();
560       char *combuf = comment.getbuf(size);
561       for (int i=0; i<size; i++)
562         {
563           combuf[i]=CodeNum(0, 255, dist_comment_byte);
564         }
565       comment.getbuf();
566 }
567 
568 
569 // LIBRARY
570 
571 
572 void
init_library(JB2Dict & jim)573 JB2Dict::JB2Codec::init_library(JB2Dict &jim)
574 {
575   int nshape = jim.get_inherited_shape_count();
576   shape2lib.resize(0,nshape-1);
577   lib2shape.resize(0,nshape-1);
578   libinfo.resize(0,nshape-1);
579   for (int i=0; i<nshape; i++)
580     {
581       shape2lib[i] = i;
582       lib2shape[i] = i;
583       jim.get_bounding_box(i, libinfo[i]);
584     }
585 }
586 
587 int
add_library(const int shapeno,JB2Shape & jshp)588 JB2Dict::JB2Codec::add_library(const int shapeno, JB2Shape &jshp)
589 {
590   const int libno = lib2shape.hbound() + 1;
591   lib2shape.touch(libno);
592   lib2shape[libno] = shapeno;
593   shape2lib.touch(shapeno);
594   shape2lib[shapeno] = libno;
595   libinfo.touch(libno);
596   libinfo[libno].compute_bounding_box(*(jshp.bits));
597   return libno;
598 }
599 
600 
601 // CODE SIMPLE VALUES
602 
603 inline void
code_record_type(int & rectype)604 JB2Dict::JB2Codec::Decode::code_record_type(int &rectype)
605 {
606   rectype=CodeNum( START_OF_DATA, END_OF_DATA, dist_record_type);
607 }
608 
609 int
code_match_index(int & index,JB2Dict &)610 JB2Dict::JB2Codec::Decode::code_match_index(int &index, JB2Dict &)
611 {
612     int match=CodeNum(0, lib2shape.hbound(), dist_match_index);
613     index = lib2shape[match];
614     return match;
615 }
616 
617 
618 // HANDLE SHORT LIST
619 
620 int
update_short_list(const int v)621 JB2Dict::JB2Codec::update_short_list(const int v)
622 {
623   if (++ short_list_pos == 3)
624     short_list_pos = 0;
625   int * const s = short_list;
626   s[short_list_pos] = v;
627 
628   return (s[0] >= s[1])
629     ?((s[0] > s[2])?((s[1] >= s[2])?s[1]:s[2]):s[0])
630     :((s[0] < s[2])?((s[1] >= s[2])?s[2]:s[1]):s[0]);
631 }
632 
633 
634 
635 // CODE PAIRS
636 
637 
638 void
code_inherited_shape_count(JB2Dict & jim)639 JB2Dict::JB2Codec::Decode::code_inherited_shape_count(JB2Dict &jim)
640 {
641   int size=CodeNum(0, BIGPOSITIVE, inherited_shape_count_dist);
642     {
643       GP<JB2Dict> dict = jim.get_inherited_dict();
644       if (!dict && size>0)
645         {
646           // Call callback function to obtain dictionary
647           if (cbfunc)
648             dict = (*cbfunc)(cbarg);
649           if (dict)
650             jim.set_inherited_dict(dict);
651         }
652       if (!dict && size>0)
653         G_THROW( ERR_MSG("JB2Image.need_dict") );
654       if (dict && size!=dict->get_shape_count())
655         G_THROW( ERR_MSG("JB2Image.bad_dict") );
656     }
657 }
658 
659 void
code_image_size(JB2Dict & jim)660 JB2Dict::JB2Codec::Decode::code_image_size(JB2Dict &jim)
661 {
662   int w=CodeNum(0, BIGPOSITIVE, image_size_dist);
663   int h=CodeNum(0, BIGPOSITIVE, image_size_dist);
664   if (w || h)
665     G_THROW( ERR_MSG("JB2Image.bad_dict2") );
666   JB2Codec::code_image_size(jim);
667 }
668 
669 void
code_image_size(JB2Dict &)670 JB2Dict::JB2Codec::code_image_size(JB2Dict &)
671 {
672   last_left = 1;
673   last_row_left = 0;
674   last_row_bottom = 0;
675   last_right = 0;
676   fill_short_list(last_row_bottom);
677   gotstartrecordp = 1;
678 }
679 
680 void
code_image_size(JB2Image & jim)681 JB2Dict::JB2Codec::Decode::code_image_size(JB2Image &jim)
682 {
683   image_columns=CodeNum(0, BIGPOSITIVE, image_size_dist);
684   image_rows=CodeNum(0, BIGPOSITIVE, image_size_dist);
685   if (!image_columns || !image_rows)
686     G_THROW( ERR_MSG("JB2Image.zero_dim") );
687   jim.set_dimension(image_columns, image_rows);
688   JB2Codec::code_image_size(jim);
689 }
690 
691 void
code_image_size(JB2Image &)692 JB2Dict::JB2Codec::code_image_size(JB2Image &)
693 {
694   last_left = 1 + image_columns;
695   last_row_left = 0;
696   last_row_bottom = image_rows;
697   last_right = 0;
698   fill_short_list(last_row_bottom);
699   gotstartrecordp = 1;
700 }
701 
702 inline int
get_diff(int,NumContext & rel_loc)703 JB2Dict::JB2Codec::Decode::get_diff(int,NumContext &rel_loc)
704 {
705    return CodeNum(BIGNEGATIVE, BIGPOSITIVE, rel_loc);
706 }
707 
708 void
code_relative_location(JB2Blit * jblt,int rows,int columns)709 JB2Dict::JB2Codec::code_relative_location(JB2Blit *jblt, int rows, int columns)
710 {
711   // Check start record
712   if (!gotstartrecordp)
713     G_THROW( ERR_MSG("JB2Image.no_start") );
714   // Find location
715   int bottom=0, left=0, top=0, right=0;
716   int x_diff, y_diff;
717   if (encoding)
718     {
719       left = jblt->left + 1;
720       bottom = jblt->bottom + 1;
721       right = left + columns - 1;
722       top = bottom + rows - 1;
723     }
724   // Code offset type
725   int new_row=CodeBit((left<last_left), offset_type_dist);
726   if (new_row)
727     {
728       // Begin a new row
729       x_diff=get_diff(left-last_row_left,rel_loc_x_last);
730       y_diff=get_diff(top-last_row_bottom,rel_loc_y_last);
731       if (!encoding)
732         {
733           left = last_row_left + x_diff;
734           top = last_row_bottom + y_diff;
735           right = left + columns - 1;
736           bottom = top - rows + 1;
737         }
738       last_left = last_row_left = left;
739       last_right = right;
740       last_bottom = last_row_bottom = bottom;
741       fill_short_list(bottom);
742     }
743   else
744     {
745       // Same row
746       x_diff=get_diff(left-last_right,rel_loc_x_current);
747       y_diff=get_diff(bottom-last_bottom,rel_loc_y_current);
748       if (!encoding)
749         {
750           left = last_right + x_diff;
751           bottom = last_bottom + y_diff;
752           right = left + columns - 1;
753           top = bottom + rows - 1;
754         }
755       last_left = left;
756       last_right = right;
757       last_bottom = update_short_list(bottom);
758     }
759   // Store in blit record
760   if (!encoding)
761     {
762       jblt->bottom = bottom - 1;
763       jblt->left = left - 1;
764     }
765 }
766 
767 void
code_absolute_location(JB2Blit * jblt,int rows,int columns)768 JB2Dict::JB2Codec::Decode::code_absolute_location(JB2Blit *jblt, int rows, int columns)
769 {
770   // Check start record
771   if (!gotstartrecordp)
772     G_THROW( ERR_MSG("JB2Image.no_start") );
773   int left=CodeNum(1, image_columns, abs_loc_x);
774   int top=CodeNum(1, image_rows, abs_loc_y);
775   jblt->bottom = top - rows + 1 - 1;
776   jblt->left = left - 1;
777 }
778 
779 void
code_absolute_mark_size(GBitmap & bm,int border)780 JB2Dict::JB2Codec::Decode::code_absolute_mark_size(GBitmap &bm, int border)
781 {
782   int xsize=CodeNum(0, BIGPOSITIVE, abs_size_x);
783   int ysize=CodeNum(0, BIGPOSITIVE, abs_size_y);
784   if ((xsize!=(unsigned short)xsize) || (ysize!=(unsigned short)ysize))
785     G_THROW( ERR_MSG("JB2Image.bad_number") );
786   bm.init(ysize, xsize, border);
787 }
788 
789 void
code_relative_mark_size(GBitmap & bm,int cw,int ch,int border)790 JB2Dict::JB2Codec::Decode::code_relative_mark_size(GBitmap &bm, int cw, int ch, int border)
791 {
792   int xdiff=CodeNum(BIGNEGATIVE, BIGPOSITIVE, rel_size_x);
793   int ydiff=CodeNum(BIGNEGATIVE, BIGPOSITIVE, rel_size_y);
794   int xsize = cw + xdiff;
795   int ysize = ch + ydiff;
796   if ((xsize!=(unsigned short)xsize) || (ysize!=(unsigned short)ysize))
797     G_THROW( ERR_MSG("JB2Image.bad_number") );
798   bm.init(ysize, xsize, border);
799 }
800 
801 
802 
803 
804 // CODE BITMAP DIRECTLY
805 
806 void
code_bitmap_directly(GBitmap & bm)807 JB2Dict::JB2Codec::code_bitmap_directly (GBitmap &bm)
808 {
809   // Make sure bitmap will not be disturbed
810   GMonitorLock lock(bm.monitor());
811   // ensure borders are adequate
812   bm.minborder(3);
813   // initialize row pointers
814   int dy = bm.rows() - 1;
815   code_bitmap_directly(bm,bm.columns(),dy,bm[dy+2],bm[dy+1],bm[dy]);
816 }
817 
818 void
code_bitmap_directly(GBitmap & bm,const int dw,int dy,unsigned char * up2,unsigned char * up1,unsigned char * up0)819 JB2Dict::JB2Codec::Decode::code_bitmap_directly(
820   GBitmap &bm,const int dw, int dy,
821   unsigned char *up2, unsigned char *up1, unsigned char *up0 )
822 {
823       ZPCodec &zp=*gzp;
824       // iterate on rows (decoding)
825       while (dy >= 0)
826         {
827           int context=get_direct_context(up2, up1, up0, 0);
828           for(int dx=0;dx < dw;)
829             {
830               int n = zp.decoder(bitdist[context]);
831               up0[dx++] = n;
832               context=shift_direct_context(context, n, up2, up1, up0, dx);
833             }
834           // next row
835           dy -= 1;
836           up2 = up1;
837           up1 = up0;
838           up0 = bm[dy];
839         }
840 #ifndef NDEBUG
841       bm.check_border();
842 #endif
843 }
844 
845 
846 
847 
848 
849 // CODE BITMAP BY CROSS CODING
850 
851 void
code_bitmap_by_cross_coding(GBitmap & bm,GP<GBitmap> & cbm,const int libno)852 JB2Dict::JB2Codec::code_bitmap_by_cross_coding (GBitmap &bm, GP<GBitmap> &cbm, const int libno)
853 {
854   // Make sure bitmaps will not be disturbed
855   GP<GBitmap> copycbm=GBitmap::create();
856   if (cbm->monitor())
857     {
858       // Perform a copy when the bitmap is explicitely shared
859       GMonitorLock lock2(cbm->monitor());
860       copycbm->init(*cbm);
861       cbm = copycbm;
862     }
863   GMonitorLock lock1(bm.monitor());
864   // Center bitmaps
865   const int cw = cbm->columns();
866   const int dw = bm.columns();
867   const int dh = bm.rows();
868   const LibRect &l = libinfo[libno];
869   const int xd2c = (dw/2 - dw + 1) - ((l.right - l.left + 1)/2 - l.right);
870   const int yd2c = (dh/2 - dh + 1) - ((l.top - l.bottom + 1)/2 - l.top);
871   // Ensure borders are adequate
872   bm.minborder(2);
873   cbm->minborder(2-xd2c);
874   cbm->minborder(2+dw+xd2c-cw);
875   // Initialize row pointers
876   const int dy = dh - 1;
877   const int cy = dy + yd2c;
878 #ifndef NDEBUG
879   bm.check_border();
880   cbm->check_border();
881 #endif
882   code_bitmap_by_cross_coding (bm,*cbm, xd2c, dw, dy, cy, bm[dy+1], bm[dy],
883     (*cbm)[cy+1] + xd2c, (*cbm)[cy  ] + xd2c, (*cbm)[cy-1] + xd2c);
884 }
885 
886 void
code_bitmap_by_cross_coding(GBitmap & bm,GBitmap & cbm,const int xd2c,const int dw,int dy,int cy,unsigned char * up1,unsigned char * up0,unsigned char * xup1,unsigned char * xup0,unsigned char * xdn1)887 JB2Dict::JB2Codec::Decode::code_bitmap_by_cross_coding (GBitmap &bm, GBitmap &cbm,
888   const int xd2c, const int dw, int dy, int cy,
889   unsigned char *up1, unsigned char *up0, unsigned char *xup1,
890   unsigned char *xup0, unsigned char *xdn1 )
891 {
892       ZPCodec &zp=*gzp;
893       // iterate on rows (decoding)
894       while (dy >= 0)
895         {
896           int context=get_cross_context(
897                             up1, up0, xup1, xup0, xdn1, 0);
898           for(int dx=0;dx < dw;)
899             {
900               const int n = zp.decoder(cbitdist[context]);
901               up0[dx++] = n;
902               context=shift_cross_context(context, n,
903                                   up1, up0, xup1, xup0, xdn1, dx);
904             }
905           // next row
906           up1 = up0;
907           up0 = bm[--dy];
908           xup1 = xup0;
909           xup0 = xdn1;
910           xdn1 = cbm[(--cy)-1] + xd2c;
911 #ifndef NDEBUG
912           bm.check_border();
913 #endif
914         }
915 }
916 
917 
918 
919 
920 // CODE JB2DICT RECORD
921 
922 void
code_record(int & rectype,const GP<JB2Dict> & gjim,JB2Shape * xjshp)923 JB2Dict::JB2Codec::code_record(
924   int &rectype, const GP<JB2Dict> &gjim, JB2Shape *xjshp)
925 {
926   GP<GBitmap> cbm;
927   GP<GBitmap> bm;
928   int shapeno = -1;
929 
930   // Code record type
931   code_record_type(rectype);
932 
933   // Pre-coding actions
934   switch(rectype)
935     {
936     case NEW_MARK_LIBRARY_ONLY:
937     case MATCHED_REFINE_LIBRARY_ONLY:
938       {
939         if(!xjshp)
940         {
941           G_THROW( ERR_MSG("JB2Image.bad_number") );
942         }
943         JB2Shape &jshp=*xjshp;
944         if (!encoding)
945         {
946           jshp.bits = GBitmap::create();
947           jshp.parent = -1;
948         }
949         bm = jshp.bits;
950         break;
951       }
952     }
953   // Coding actions
954   switch (rectype)
955     {
956     case START_OF_DATA:
957       {
958         if(!gjim)
959         {
960            G_THROW( ERR_MSG("JB2Image.bad_number") );
961         }
962         JB2Dict &jim=*gjim;
963         code_image_size (jim);
964         code_eventual_lossless_refinement ();
965         if (! encoding)
966           init_library(jim);
967         break;
968       }
969     case NEW_MARK_LIBRARY_ONLY:
970       {
971         code_absolute_mark_size (*bm, 4);
972         code_bitmap_directly (*bm);
973         break;
974       }
975     case MATCHED_REFINE_LIBRARY_ONLY:
976       {
977         if(!xjshp||!gjim)
978         {
979            G_THROW( ERR_MSG("JB2Image.bad_number") );
980         }
981         JB2Dict &jim=*gjim;
982         JB2Shape &jshp=*xjshp;
983         int match = code_match_index (jshp.parent, jim);
984         cbm = jim.get_shape(jshp.parent).bits;
985         LibRect &l = libinfo[match];
986         code_relative_mark_size (*bm, l.right-l.left+1, l.top-l.bottom+1, 4);
987         code_bitmap_by_cross_coding (*bm, cbm, jshp.parent);
988         break;
989       }
990     case PRESERVED_COMMENT:
991       {
992         if(!gjim)
993         {
994            G_THROW( ERR_MSG("JB2Image.bad_number") );
995         }
996         JB2Dict &jim=*gjim;
997         code_comment(jim.comment);
998         break;
999       }
1000     case REQUIRED_DICT_OR_RESET:
1001       {
1002         if (! gotstartrecordp)
1003         {
1004 	  // Indicates need for a shape dictionary
1005           if(!gjim)
1006           {
1007              G_THROW( ERR_MSG("JB2Image.bad_number") );
1008           }
1009 	  code_inherited_shape_count(*gjim);
1010         }else
1011 	  // Reset all numerical contexts to zero
1012 	  reset_numcoder();
1013         break;
1014       }
1015     case END_OF_DATA:
1016       {
1017         break;
1018       }
1019     default:
1020       {
1021         G_THROW( ERR_MSG("JB2Image.bad_type") );
1022       }
1023     }
1024   // Post-coding action
1025   if (!encoding)
1026     {
1027       // add shape to dictionary
1028       switch(rectype)
1029         {
1030         case NEW_MARK_LIBRARY_ONLY:
1031         case MATCHED_REFINE_LIBRARY_ONLY:
1032           {
1033             if(!xjshp||!gjim)
1034             {
1035                G_THROW( ERR_MSG("JB2Image.bad_number") );
1036             }
1037             JB2Shape &jshp=*xjshp;
1038             shapeno = gjim->add_shape(jshp);
1039             add_library(shapeno, jshp);
1040             break;
1041           }
1042         }
1043       // make sure everything is compacted
1044       // decompaction will occur automatically when needed
1045       if (bm)
1046         bm->compress();
1047     }
1048 }
1049 
1050 
1051 // CODE JB2DICT
1052 
1053 void
code(const GP<JB2Dict> & gjim)1054 JB2Dict::JB2Codec::Decode::code(const GP<JB2Dict> &gjim)
1055 {
1056   if(!gjim)
1057   {
1058     G_THROW( ERR_MSG("JB2Image.bad_number") );
1059   }
1060   JB2Dict &jim=*gjim;
1061   // -------------------------
1062   // THIS IS THE DECODING PART
1063   // -------------------------
1064   int rectype;
1065   JB2Shape tmpshape;
1066   do {
1067     code_record(rectype, gjim, &tmpshape);
1068   } while(rectype != END_OF_DATA);
1069   if (!gotstartrecordp)
1070     G_THROW( ERR_MSG("JB2Image.no_start") );
1071   // cache bounding boxes
1072   int nshapes = jim.get_shape_count();
1073   int ishapes = jim.get_inherited_shape_count();
1074   jim.boxes.resize(0, nshapes-ishapes-1);
1075   for (int i = ishapes; i < nshapes; i++)
1076     jim.boxes[i-ishapes] = libinfo[i];
1077   // compress
1078   jim.compress();
1079 }
1080 
1081 
1082 
1083 // CODE JB2IMAGE RECORD
1084 
1085 void
code_record(int & rectype,const GP<JB2Image> & gjim,JB2Shape * xjshp,JB2Blit * jblt)1086 JB2Dict::JB2Codec::code_record(
1087   int &rectype, const GP<JB2Image> &gjim, JB2Shape *xjshp, JB2Blit *jblt)
1088 {
1089   GP<GBitmap> bm;
1090   GP<GBitmap> cbm;
1091   int shapeno = -1;
1092   int match;
1093 
1094   // Code record type
1095   code_record_type(rectype);
1096 
1097   // Pre-coding actions
1098   switch(rectype)
1099     {
1100     case NEW_MARK:
1101     case NEW_MARK_LIBRARY_ONLY:
1102     case NEW_MARK_IMAGE_ONLY:
1103     case MATCHED_REFINE:
1104     case MATCHED_REFINE_LIBRARY_ONLY:
1105     case MATCHED_REFINE_IMAGE_ONLY:
1106     case NON_MARK_DATA:
1107       {
1108         if(!xjshp)
1109         {
1110            G_THROW( ERR_MSG("JB2Image.bad_number") );
1111         }
1112         JB2Shape &jshp=*xjshp;
1113         if (!encoding)
1114         {
1115           jshp.bits = GBitmap::create();
1116           jshp.parent = -1;
1117           if (rectype == NON_MARK_DATA)
1118             jshp.parent = -2;
1119         }
1120         bm = jshp.bits;
1121         break;
1122       }
1123     }
1124   // Coding actions
1125   switch (rectype)
1126     {
1127     case START_OF_DATA:
1128       {
1129         if(!gjim)
1130         {
1131            G_THROW( ERR_MSG("JB2Image.bad_number") );
1132         }
1133         JB2Image &jim=*gjim;
1134         code_image_size (jim);
1135         code_eventual_lossless_refinement ();
1136         if (! encoding)
1137           init_library(jim);
1138         break;
1139       }
1140     case NEW_MARK:
1141       {
1142         code_absolute_mark_size (*bm, 4);
1143         code_bitmap_directly (*bm);
1144         code_relative_location (jblt, bm->rows(), bm->columns() );
1145         break;
1146       }
1147     case NEW_MARK_LIBRARY_ONLY:
1148       {
1149         code_absolute_mark_size (*bm, 4);
1150         code_bitmap_directly (*bm);
1151         break;
1152       }
1153     case NEW_MARK_IMAGE_ONLY:
1154       {
1155         code_absolute_mark_size (*bm, 3);
1156         code_bitmap_directly (*bm);
1157         code_relative_location (jblt, bm->rows(), bm->columns() );
1158         break;
1159       }
1160     case MATCHED_REFINE:
1161       {
1162         if(!xjshp || !gjim)
1163         {
1164            G_THROW( ERR_MSG("JB2Image.bad_number") );
1165         }
1166         JB2Shape &jshp=*xjshp;
1167         JB2Image &jim=*gjim;
1168         match = code_match_index (jshp.parent, jim);
1169         cbm = jim.get_shape(jshp.parent).bits;
1170         LibRect &l = libinfo[match];
1171         code_relative_mark_size (*bm, l.right-l.left+1, l.top-l.bottom+1, 4);
1172         code_bitmap_by_cross_coding (*bm, cbm, match);
1173         code_relative_location (jblt, bm->rows(), bm->columns() );
1174         break;
1175       }
1176     case MATCHED_REFINE_LIBRARY_ONLY:
1177       {
1178         if(!xjshp||!gjim)
1179         {
1180            G_THROW( ERR_MSG("JB2Image.bad_number") );
1181         }
1182         JB2Image &jim=*gjim;
1183         JB2Shape &jshp=*xjshp;
1184         match = code_match_index (jshp.parent, jim);
1185         cbm = jim.get_shape(jshp.parent).bits;
1186         LibRect &l = libinfo[match];
1187         code_relative_mark_size (*bm, l.right-l.left+1, l.top-l.bottom+1, 4);
1188         break;
1189       }
1190     case MATCHED_REFINE_IMAGE_ONLY:
1191       {
1192         if(!xjshp||!gjim)
1193         {
1194            G_THROW( ERR_MSG("JB2Image.bad_number") );
1195         }
1196         JB2Image &jim=*gjim;
1197         JB2Shape &jshp=*xjshp;
1198         match = code_match_index (jshp.parent, jim);
1199         cbm = jim.get_shape(jshp.parent).bits;
1200         LibRect &l = libinfo[match];
1201         code_relative_mark_size (*bm, l.right-l.left+1, l.top-l.bottom+1, 4);
1202         code_bitmap_by_cross_coding (*bm, cbm, match);
1203         code_relative_location (jblt, bm->rows(), bm->columns() );
1204         break;
1205       }
1206     case MATCHED_COPY:
1207       {
1208         int temp;
1209         if (encoding) temp = jblt->shapeno;
1210         if(!gjim)
1211         {
1212            G_THROW( ERR_MSG("JB2Image.bad_number") );
1213         }
1214         JB2Image &jim=*gjim;
1215         match = code_match_index (temp, jim);
1216         if (!encoding) jblt->shapeno = temp;
1217         bm = jim.get_shape(jblt->shapeno).bits;
1218         LibRect &l = libinfo[match];
1219         jblt->left += l.left;
1220         jblt->bottom += l.bottom;
1221         if (jim.reproduce_old_bug)
1222           code_relative_location (jblt, bm->rows(), bm->columns() );
1223         else
1224           code_relative_location (jblt, l.top-l.bottom+1, l.right-l.left+1 );
1225         jblt->left -= l.left;
1226         jblt->bottom -= l.bottom;
1227         break;
1228       }
1229     case NON_MARK_DATA:
1230       {
1231         code_absolute_mark_size (*bm, 3);
1232         code_bitmap_directly (*bm);
1233         code_absolute_location (jblt, bm->rows(), bm->columns() );
1234         break;
1235       }
1236     case PRESERVED_COMMENT:
1237       {
1238         if(!gjim)
1239         {
1240            G_THROW( ERR_MSG("JB2Image.bad_number") );
1241         }
1242         JB2Image &jim=*gjim;
1243         code_comment(jim.comment);
1244         break;
1245       }
1246     case REQUIRED_DICT_OR_RESET:
1247       {
1248         if(!gjim)
1249         {
1250            G_THROW( ERR_MSG("JB2Image.bad_number") );
1251         }
1252         JB2Image &jim=*gjim;
1253         if (! gotstartrecordp)
1254 	  // Indicates need for a shape dictionary
1255 	  code_inherited_shape_count(jim);
1256 	else
1257 	  // Reset all numerical contexts to zero
1258 	  reset_numcoder();
1259         break;
1260       }
1261     case END_OF_DATA:
1262       {
1263         break;
1264       }
1265     default:
1266       {
1267         G_THROW( ERR_MSG("JB2Image.unknown_type") );
1268       }
1269     }
1270 
1271   // Post-coding action
1272   if (!encoding)
1273     {
1274       // add shape to image
1275       switch(rectype)
1276         {
1277         case NEW_MARK:
1278         case NEW_MARK_LIBRARY_ONLY:
1279         case NEW_MARK_IMAGE_ONLY:
1280         case MATCHED_REFINE:
1281         case MATCHED_REFINE_LIBRARY_ONLY:
1282         case MATCHED_REFINE_IMAGE_ONLY:
1283         case NON_MARK_DATA:
1284           {
1285             if(!xjshp||!gjim)
1286             {
1287               G_THROW( ERR_MSG("JB2Image.bad_number") );
1288             }
1289             JB2Shape &jshp=*xjshp;
1290             shapeno = gjim->add_shape(jshp);
1291             shape2lib.touch(shapeno);
1292             shape2lib[shapeno] = -1;
1293             break;
1294           }
1295         }
1296       // add shape to library
1297       switch(rectype)
1298         {
1299         case NEW_MARK:
1300         case NEW_MARK_LIBRARY_ONLY:
1301         case MATCHED_REFINE:
1302         case MATCHED_REFINE_LIBRARY_ONLY:
1303           if(!xjshp)
1304           {
1305             G_THROW( ERR_MSG("JB2Image.bad_number") );
1306           }
1307           add_library(shapeno, *xjshp);
1308           break;
1309         }
1310       // make sure everything is compacted
1311       // decompaction will occur automatically on cross-coding bitmaps
1312       if (bm)
1313         bm->compress();
1314       // add blit to image
1315       switch (rectype)
1316         {
1317         case NEW_MARK:
1318         case NEW_MARK_IMAGE_ONLY:
1319         case MATCHED_REFINE:
1320         case MATCHED_REFINE_IMAGE_ONLY:
1321         case NON_MARK_DATA:
1322           jblt->shapeno = shapeno;
1323         case MATCHED_COPY:
1324           if(!gjim)
1325           {
1326             G_THROW( ERR_MSG("JB2Image.bad_number") );
1327           }
1328           gjim->add_blit(* jblt);
1329           break;
1330         }
1331     }
1332 }
1333 
1334 
1335 // CODE JB2IMAGE
1336 
1337 void
code(const GP<JB2Image> & gjim)1338 JB2Dict::JB2Codec::Decode::code(const GP<JB2Image> &gjim)
1339 {
1340   if(!gjim)
1341   {
1342     G_THROW( ERR_MSG("JB2Image.bad_number") );
1343   }
1344   JB2Image &jim=*gjim;
1345       // -------------------------
1346       // THIS IS THE DECODING PART
1347       // -------------------------
1348       int rectype;
1349       JB2Blit tmpblit;
1350       JB2Shape tmpshape;
1351       do
1352         {
1353           code_record(rectype, gjim, &tmpshape, &tmpblit);
1354         }
1355       while(rectype!=END_OF_DATA);
1356       if (!gotstartrecordp)
1357         G_THROW( ERR_MSG("JB2Image.no_start") );
1358       jim.compress();
1359 }
1360 
1361 
1362 
1363 ////////////////////////////////////////
1364 //// HELPERS
1365 ////////////////////////////////////////
1366 
1367 void
compute_bounding_box(const GBitmap & bm)1368 JB2Dict::LibRect::compute_bounding_box(const GBitmap &bm)
1369 {
1370   // Avoid trouble
1371   GMonitorLock lock(bm.monitor());
1372   // Get size
1373   const int w = bm.columns();
1374   const int h = bm.rows();
1375   const int s = bm.rowsize();
1376   // Right border
1377   for(right=w-1;right >= 0;--right)
1378     {
1379       unsigned char const *p = bm[0] + right;
1380       unsigned char const * const pe = p+(s*h);
1381       for (;(p<pe)&&(!*p);p+=s)
1382       	continue;
1383       if (p<pe)
1384         break;
1385     }
1386   // Top border
1387   for(top=h-1;top >= 0;--top)
1388     {
1389       unsigned char const *p = bm[top];
1390       unsigned char const * const pe = p+w;
1391       for (;(p<pe)&&(!*p); ++p)
1392       	continue;
1393       if (p<pe)
1394         break;
1395     }
1396   // Left border
1397   for (left=0;left <= right;++left)
1398     {
1399       unsigned char const *p = bm[0] + left;
1400       unsigned char const * const pe=p+(s*h);
1401       for (;(p<pe)&&(!*p);p+=s)
1402       	continue;
1403       if (p<pe)
1404         break;
1405     }
1406   // Bottom border
1407   for(bottom=0;bottom <= top;++bottom)
1408     {
1409       unsigned char const *p = bm[bottom];
1410       unsigned char const * const pe = p+w;
1411       for (;(p<pe)&&(!*p); ++p)
1412       	continue;
1413       if (p<pe)
1414         break;
1415     }
1416 }
1417 
1418 
1419 void
get_bounding_box(int shapeno,LibRect & dest)1420 JB2Dict::get_bounding_box(int shapeno, LibRect &dest)
1421 {
1422   if (shapeno < inherited_shapes && inherited_dict)
1423     {
1424       inherited_dict->get_bounding_box(shapeno, dest);
1425     }
1426   else if (shapeno >= inherited_shapes &&
1427            shapeno < inherited_shapes + boxes.size())
1428     {
1429       dest = boxes[shapeno - inherited_shapes];
1430     }
1431   else
1432     {
1433       JB2Shape &jshp = get_shape(shapeno);
1434       dest.compute_bounding_box(*(jshp.bits));
1435     }
1436 }
1437 
1438 
1439 GP<JB2Dict>
create(void)1440 JB2Dict::create(void)
1441 {
1442   return new JB2Dict();
1443 }
1444 
1445 
1446 #ifdef HAVE_NAMESPACES
1447 }
1448 # ifndef NOT_USING_DJVU_NAMESPACE
1449 using namespace DJVU;
1450 # endif
1451 #endif
1452