Blame libdjvu/JB2Image.cpp

Packit df99a1
//C-  -*- C++ -*-
Packit df99a1
//C- -------------------------------------------------------------------
Packit df99a1
//C- DjVuLibre-3.5
Packit df99a1
//C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
Packit df99a1
//C- Copyright (c) 2001  AT&T
Packit df99a1
//C-
Packit df99a1
//C- This software is subject to, and may be distributed under, the
Packit df99a1
//C- GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- or (at your option) any later version. The license should have
Packit df99a1
//C- accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C-
Packit df99a1
//C- This program is distributed in the hope that it will be useful,
Packit df99a1
//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit df99a1
//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit df99a1
//C- GNU General Public License for more details.
Packit df99a1
//C- 
Packit df99a1
//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
Packit df99a1
//C- Lizardtech Software.  Lizardtech Software has authorized us to
Packit df99a1
//C- replace the original DjVu(r) Reference Library notice by the following
Packit df99a1
//C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
Packit df99a1
//C-
Packit df99a1
//C-  ------------------------------------------------------------------
Packit df99a1
//C- | DjVu (r) Reference Library (v. 3.5)
Packit df99a1
//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
Packit df99a1
//C- | The DjVu Reference Library is protected by U.S. Pat. No.
Packit df99a1
//C- | 6,058,214 and patents pending.
Packit df99a1
//C- |
Packit df99a1
//C- | This software is subject to, and may be distributed under, the
Packit df99a1
//C- | GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- | or (at your option) any later version. The license should have
Packit df99a1
//C- | accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- | from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C- |
Packit df99a1
//C- | The computer code originally released by LizardTech under this
Packit df99a1
//C- | license and unmodified by other parties is deemed "the LIZARDTECH
Packit df99a1
//C- | ORIGINAL CODE."  Subject to any third party intellectual property
Packit df99a1
//C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
Packit df99a1
//C- | non-exclusive license to make, use, sell, or otherwise dispose of 
Packit df99a1
//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
Packit df99a1
//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
Packit df99a1
//C- | General Public License.   This grant only confers the right to 
Packit df99a1
//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
Packit df99a1
//C- | the extent such infringement is reasonably necessary to enable 
Packit df99a1
//C- | recipient to make, have made, practice, sell, or otherwise dispose 
Packit df99a1
//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
Packit df99a1
//C- | any greater extent that may be necessary to utilize further 
Packit df99a1
//C- | modifications or combinations.
Packit df99a1
//C- |
Packit df99a1
//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
Packit df99a1
//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
Packit df99a1
//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
Packit df99a1
//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Packit df99a1
//C- +------------------------------------------------------------------
Packit df99a1
Packit df99a1
#ifdef HAVE_CONFIG_H
Packit df99a1
# include "config.h"
Packit df99a1
#endif
Packit df99a1
#if NEED_GNUG_PRAGMAS
Packit df99a1
# pragma implementation
Packit df99a1
#endif
Packit df99a1
Packit df99a1
// From: Leon Bottou, 1/31/2002
Packit df99a1
// Lizardtech has split the corresponding cpp file into a decoder and an encoder.
Packit df99a1
// Only superficial changes.  The meat is mine.
Packit df99a1
Packit df99a1
#include "JB2Image.h"
Packit df99a1
#include "GThreads.h"
Packit df99a1
#include "GRect.h"
Packit df99a1
#include "GBitmap.h"
Packit df99a1
#include <string.h>
Packit df99a1
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
namespace DJVU {
Packit df99a1
# ifdef NOT_DEFINED // Just to fool emacs c++ mode
Packit df99a1
}
Packit df99a1
#endif
Packit df99a1
#endif
Packit df99a1
Packit df99a1
////////////////////////////////////////
Packit df99a1
//// CLASS JB2Codec::Decode:  DECLARATION
Packit df99a1
////////////////////////////////////////
Packit df99a1
Packit df99a1
// This class is accessed via the decode
Packit df99a1
// functions of class JB2Image
Packit df99a1
Packit df99a1
Packit df99a1
//**** Class JB2Codec
Packit df99a1
// This class implements the JB2 decoder.
Packit df99a1
// Contains all contextual information for decoding a JB2Image.
Packit df99a1
Packit df99a1
class JB2Dict::JB2Codec::Decode : public JB2Dict::JB2Codec
Packit df99a1
{
Packit df99a1
public:
Packit df99a1
  Decode(void);
Packit df99a1
  void init(const GP<ByteStream> &gbs;;
Packit df99a1
// virtual
Packit df99a1
  void code(const GP<JB2Image> &jim);
Packit df99a1
  void code(JB2Image *jim) {const GP<JB2Image> gjim(jim);code(gjim);}
Packit df99a1
  void code(const GP<JB2Dict> &jim);
Packit df99a1
  void code(JB2Dict *jim) {const GP<JB2Dict> gjim(jim);code(gjim);}
Packit df99a1
  void set_dict_callback(JB2DecoderCallback *cb, void *arg);
Packit df99a1
protected:
Packit df99a1
  int CodeNum(const int lo, const int hi, NumContext &ctx;;
Packit df99a1
Packit df99a1
// virtual
Packit df99a1
  bool CodeBit(const bool bit, BitContext &ctx;;
Packit df99a1
  void code_comment(GUTF8String &comment);
Packit df99a1
  void code_record_type(int &rectype);
Packit df99a1
  int code_match_index(int &index, JB2Dict &jim);
Packit df99a1
  void code_inherited_shape_count(JB2Dict &jim);
Packit df99a1
  void code_image_size(JB2Dict &jim);
Packit df99a1
  void code_image_size(JB2Image &jim);
Packit df99a1
  void code_absolute_location(JB2Blit *jblt,  int rows, int columns);
Packit df99a1
  void code_absolute_mark_size(GBitmap &bm, int border=0);
Packit df99a1
  void code_relative_mark_size(GBitmap &bm, int cw, int ch, int border=0);
Packit df99a1
  void code_bitmap_directly(GBitmap &bm,const int dw, int dy,
Packit df99a1
    unsigned char *up2, unsigned char *up1, unsigned char *up0 );
Packit df99a1
  void code_bitmap_by_cross_coding (GBitmap &bm, GBitmap &cbm,
Packit df99a1
    const int xd2c, const int dw, int dy, int cy,
Packit df99a1
    unsigned char *up1, unsigned char *up0, unsigned char *xup1, 
Packit df99a1
    unsigned char *xup0, unsigned char *xdn1 );
Packit df99a1
  int get_diff(const int x_diff,NumContext &rel_loc);
Packit df99a1
Packit df99a1
private:
Packit df99a1
  GP<ZPCodec> gzp;
Packit df99a1
  JB2DecoderCallback *cbfunc;
Packit df99a1
  void *cbarg;
Packit df99a1
};
Packit df99a1
Packit df99a1
////////////////////////////////////////
Packit df99a1
//// CLASS JB2DICT: IMPLEMENTATION
Packit df99a1
////////////////////////////////////////
Packit df99a1
Packit df99a1
Packit df99a1
JB2Dict::JB2Dict()
Packit df99a1
  : inherited_shapes(0)
Packit df99a1
{
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
JB2Dict::init()
Packit df99a1
{
Packit df99a1
  inherited_shapes = 0;
Packit df99a1
  inherited_dict = 0;
Packit df99a1
  shapes.empty();
Packit df99a1
}
Packit df99a1
Packit df99a1
JB2Shape &
Packit df99a1
JB2Dict::get_shape(const int shapeno)
Packit df99a1
{
Packit df99a1
  JB2Shape *retval;
Packit df99a1
  if(shapeno >= inherited_shapes)
Packit df99a1
  {
Packit df99a1
    retval=&shapes[shapeno - inherited_shapes];
Packit df99a1
  }else if(inherited_dict)
Packit df99a1
  {
Packit df99a1
    retval=&(inherited_dict->get_shape(shapeno));
Packit df99a1
  }else
Packit df99a1
  {
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
  }
Packit df99a1
  return *retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
const JB2Shape &
Packit df99a1
JB2Dict::get_shape(const int shapeno) const
Packit df99a1
{
Packit df99a1
  const JB2Shape *retval;
Packit df99a1
  if(shapeno >= inherited_shapes)
Packit df99a1
  {
Packit df99a1
    retval=&shapes[shapeno - inherited_shapes];
Packit df99a1
  }else if(inherited_dict)
Packit df99a1
  {
Packit df99a1
    retval=&(inherited_dict->get_shape(shapeno));
Packit df99a1
  }else
Packit df99a1
  {
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
  }
Packit df99a1
  return *retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::set_inherited_dict(const GP<JB2Dict> &dict)
Packit df99a1
{
Packit df99a1
  if (shapes.size() > 0)
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.cant_set") );
Packit df99a1
  if (inherited_dict)
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.cant_change") );
Packit df99a1
  inherited_dict = dict; 
Packit df99a1
  inherited_shapes = dict->get_shape_count();
Packit df99a1
  // Make sure that inherited bitmaps are marked as shared
Packit df99a1
  for (int i=0; i
Packit df99a1
    {
Packit df99a1
      JB2Shape &jshp = dict->get_shape(i);
Packit df99a1
      if (jshp.bits) jshp.bits->share();
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
JB2Dict::compress()
Packit df99a1
{
Packit df99a1
  for (int i=shapes.lbound(); i<=shapes.hbound(); i++)
Packit df99a1
    shapes[i].bits->compress();
Packit df99a1
}
Packit df99a1
Packit df99a1
unsigned int
Packit df99a1
JB2Dict::get_memory_usage() const
Packit df99a1
{
Packit df99a1
  unsigned int usage = sizeof(JB2Dict);
Packit df99a1
  usage += sizeof(JB2Shape) * shapes.size();
Packit df99a1
  for (int i=shapes.lbound(); i<=shapes.hbound(); i++)
Packit df99a1
    if (shapes[i].bits)
Packit df99a1
      usage += shapes[i].bits->get_memory_usage();
Packit df99a1
  return usage;
Packit df99a1
}
Packit df99a1
Packit df99a1
int  
Packit df99a1
JB2Dict::add_shape(const JB2Shape &shape)
Packit df99a1
{
Packit df99a1
  if (shape.parent >= get_shape_count())
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.bad_parent_shape") );
Packit df99a1
  int index = shapes.size();
Packit df99a1
  shapes.touch(index);
Packit df99a1
  shapes[index] = shape;
Packit df99a1
  return index + inherited_shapes;
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::decode(const GP<ByteStream> &gbs, JB2DecoderCallback *cb, void *arg)
Packit df99a1
{
Packit df99a1
  init();
Packit df99a1
  JB2Codec::Decode codec;
Packit df99a1
  codec.init(gbs);
Packit df99a1
  codec.set_dict_callback(cb,arg);
Packit df99a1
  codec.code(this);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
////////////////////////////////////////
Packit df99a1
//// CLASS JB2IMAGE: IMPLEMENTATION
Packit df99a1
////////////////////////////////////////
Packit df99a1
Packit df99a1
Packit df99a1
JB2Image::JB2Image(void)
Packit df99a1
  : width(0), height(0), reproduce_old_bug(false)
Packit df99a1
{
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
JB2Image::init(void)
Packit df99a1
{
Packit df99a1
  width = height = 0;
Packit df99a1
  blits.empty();
Packit df99a1
  JB2Dict::init();
Packit df99a1
}
Packit df99a1
Packit df99a1
unsigned int
Packit df99a1
JB2Image::get_memory_usage() const
Packit df99a1
{
Packit df99a1
  unsigned int usage = JB2Dict::get_memory_usage();
Packit df99a1
  usage += sizeof(JB2Image) - sizeof(JB2Dict);
Packit df99a1
  usage += sizeof(JB2Blit) * blits.size();
Packit df99a1
  return usage;
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Image::set_dimension(int awidth, int aheight)
Packit df99a1
{
Packit df99a1
  width = awidth;
Packit df99a1
  height = aheight;
Packit df99a1
}
Packit df99a1
Packit df99a1
int  
Packit df99a1
JB2Image::add_blit(const JB2Blit &blit)
Packit df99a1
{
Packit df99a1
  if (blit.shapeno >= (unsigned int)get_shape_count())
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.bad_shape") );
Packit df99a1
  int index = blits.size();
Packit df99a1
  blits.touch(index);
Packit df99a1
  blits[index] = blit;
Packit df99a1
  return index;
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<GBitmap>
Packit df99a1
JB2Image::get_bitmap(int subsample, int align) const
Packit df99a1
{
Packit df99a1
  if (width==0 || height==0)
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.cant_create") );
Packit df99a1
  int swidth = (width + subsample - 1) / subsample;
Packit df99a1
  int sheight = (height + subsample - 1) / subsample;
Packit df99a1
  int border = ((swidth + align - 1) & ~(align - 1)) - swidth;
Packit df99a1
  GP<GBitmap> bm = GBitmap::create(sheight, swidth, border);
Packit df99a1
  bm->set_grays(1+subsample*subsample);
Packit df99a1
  for (int blitno = 0; blitno < get_blit_count(); blitno++)
Packit df99a1
    {
Packit df99a1
      const JB2Blit *pblit = get_blit(blitno);
Packit df99a1
      const JB2Shape  &pshape = get_shape(pblit->shapeno);
Packit df99a1
      if (pshape.bits)
Packit df99a1
        bm->blit(pshape.bits, pblit->left, pblit->bottom, subsample);
Packit df99a1
    }
Packit df99a1
  return bm;
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<GBitmap>
Packit df99a1
JB2Image::get_bitmap(const GRect &rect, int subsample, int align, int dispy) const
Packit df99a1
{
Packit df99a1
  if (width==0 || height==0)
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.cant_create") );
Packit df99a1
  int rxmin = rect.xmin * subsample;
Packit df99a1
  int rymin = rect.ymin * subsample;
Packit df99a1
  int swidth = rect.width();
Packit df99a1
  int sheight = rect.height();
Packit df99a1
  int border = ((swidth + align - 1) & ~(align - 1)) - swidth;
Packit df99a1
  GP<GBitmap> bm = GBitmap::create(sheight, swidth, border);
Packit df99a1
  bm->set_grays(1+subsample*subsample);
Packit df99a1
  for (int blitno = 0; blitno < get_blit_count(); blitno++)
Packit df99a1
    {
Packit df99a1
      const JB2Blit *pblit = get_blit(blitno);
Packit df99a1
      const JB2Shape  &pshape = get_shape(pblit->shapeno);
Packit df99a1
      if (pshape.bits)
Packit df99a1
        bm->blit(pshape.bits, pblit->left-rxmin, pblit->bottom-rymin+dispy, subsample);
Packit df99a1
    }
Packit df99a1
  return bm;
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Image::decode(const GP<ByteStream> &gbs, JB2DecoderCallback *cb, void *arg)
Packit df99a1
{
Packit df99a1
  init();
Packit df99a1
  JB2Codec::Decode codec;
Packit df99a1
  codec.init(gbs);
Packit df99a1
  codec.set_dict_callback(cb,arg);
Packit df99a1
  codec.code(this);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
////////////////////////////////////////
Packit df99a1
//// CLASS JB2CODEC : IMPLEMENTATION
Packit df99a1
////////////////////////////////////////
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
#define START_OF_DATA                   (0)
Packit df99a1
#define NEW_MARK                        (1)
Packit df99a1
#define NEW_MARK_LIBRARY_ONLY           (2)
Packit df99a1
#define NEW_MARK_IMAGE_ONLY             (3)
Packit df99a1
#define MATCHED_REFINE                  (4)
Packit df99a1
#define MATCHED_REFINE_LIBRARY_ONLY     (5)
Packit df99a1
#define MATCHED_REFINE_IMAGE_ONLY       (6)
Packit df99a1
#define MATCHED_COPY                    (7)
Packit df99a1
#define NON_MARK_DATA                   (8)
Packit df99a1
#define REQUIRED_DICT_OR_RESET          (9)
Packit df99a1
#define PRESERVED_COMMENT               (10)
Packit df99a1
#define END_OF_DATA                     (11)
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// STATIC DATA MEMBERS
Packit df99a1
Packit df99a1
static const int BIGPOSITIVE = 262142;
Packit df99a1
static const int BIGNEGATIVE = -262143;
Packit df99a1
static const int CELLCHUNK = 20000;
Packit df99a1
static const int CELLEXTRA =   500;
Packit df99a1
Packit df99a1
Packit df99a1
// CONSTRUCTOR
Packit df99a1
Packit df99a1
JB2Dict::JB2Codec::Decode::Decode(void)
Packit df99a1
: JB2Dict::JB2Codec(0), cbfunc(0), cbarg(0) {}
Packit df99a1
Packit df99a1
void
Packit df99a1
JB2Dict::JB2Codec::Decode::init(const GP<ByteStream> &gbs)
Packit df99a1
{
Packit df99a1
  gzp=ZPCodec::create(gbs,false,true);
Packit df99a1
}
Packit df99a1
Packit df99a1
JB2Dict::JB2Codec::JB2Codec(const bool xencoding)
Packit df99a1
  : encoding(xencoding),
Packit df99a1
    cur_ncell(0),
Packit df99a1
    gbitcells(bitcells,CELLCHUNK+CELLEXTRA),
Packit df99a1
    gleftcell(leftcell,CELLCHUNK+CELLEXTRA),
Packit df99a1
    grightcell(rightcell,CELLCHUNK+CELLEXTRA),
Packit df99a1
    refinementp(false),
Packit df99a1
    gotstartrecordp(0),
Packit df99a1
    dist_comment_byte(0),
Packit df99a1
    dist_comment_length(0),
Packit df99a1
    dist_record_type(0),
Packit df99a1
    dist_match_index(0),
Packit df99a1
    dist_refinement_flag(0),
Packit df99a1
    abs_loc_x(0),
Packit df99a1
    abs_loc_y(0),
Packit df99a1
    abs_size_x(0),
Packit df99a1
    abs_size_y(0),
Packit df99a1
    image_size_dist(0),
Packit df99a1
    inherited_shape_count_dist(0),
Packit df99a1
    offset_type_dist(0),
Packit df99a1
    rel_loc_x_current(0),
Packit df99a1
    rel_loc_x_last(0),
Packit df99a1
    rel_loc_y_current(0),
Packit df99a1
    rel_loc_y_last(0),
Packit df99a1
    rel_size_x(0),
Packit df99a1
    rel_size_y(0)
Packit df99a1
{
Packit df99a1
  memset(bitdist, 0, sizeof(bitdist));
Packit df99a1
  memset(cbitdist, 0, sizeof(cbitdist));
Packit df99a1
  // Initialize numcoder
Packit df99a1
  bitcells[0] = 0; // dummy cell
Packit df99a1
  leftcell[0] = rightcell[0] = 0;
Packit df99a1
  cur_ncell = 1;
Packit df99a1
}
Packit df99a1
Packit df99a1
JB2Dict::JB2Codec::~JB2Codec() {}
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::JB2Codec::reset_numcoder()
Packit df99a1
{
Packit df99a1
  dist_comment_byte = 0;
Packit df99a1
  dist_comment_length = 0;
Packit df99a1
  dist_record_type = 0;
Packit df99a1
  dist_match_index = 0;
Packit df99a1
  abs_loc_x = 0;
Packit df99a1
  abs_loc_y = 0;
Packit df99a1
  abs_size_x = 0;
Packit df99a1
  abs_size_y = 0;
Packit df99a1
  image_size_dist = 0;
Packit df99a1
  inherited_shape_count_dist = 0;
Packit df99a1
  rel_loc_x_current = 0;
Packit df99a1
  rel_loc_x_last = 0;
Packit df99a1
  rel_loc_y_current = 0;
Packit df99a1
  rel_loc_y_last = 0;
Packit df99a1
  rel_size_x = 0;
Packit df99a1
  rel_size_y = 0;
Packit df99a1
  gbitcells.clear();
Packit df99a1
  gleftcell.clear();
Packit df99a1
  grightcell.clear();
Packit df99a1
  cur_ncell = 1;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::JB2Codec::Decode::set_dict_callback(JB2DecoderCallback *cb, void *arg)
Packit df99a1
{
Packit df99a1
  cbfunc = cb;
Packit df99a1
  cbarg = arg;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
// CODE NUMBERS
Packit df99a1
Packit df99a1
inline bool
Packit df99a1
JB2Dict::JB2Codec::Decode::CodeBit(const bool, BitContext &ctx)
Packit df99a1
{
Packit df99a1
  return gzp->decoder(ctx)?true:false;
Packit df99a1
}
Packit df99a1
Packit df99a1
int
Packit df99a1
JB2Dict::JB2Codec::Decode::CodeNum(int low, int high, NumContext &ctx)
Packit df99a1
{
Packit df99a1
  return JB2Codec::CodeNum(low,high,&ctx,0);
Packit df99a1
}
Packit df99a1
Packit df99a1
int
Packit df99a1
JB2Dict::JB2Codec::CodeNum(int low, int high, NumContext *pctx, int v)
Packit df99a1
{
Packit df99a1
  bool negative=false;
Packit df99a1
  int cutoff;
Packit df99a1
  // Check
Packit df99a1
  if (!pctx || ((int)*pctx >= cur_ncell))
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.bad_numcontext") );
Packit df99a1
  // Start all phases
Packit df99a1
  cutoff = 0;
Packit df99a1
  for(int phase=1,range=0xffffffff;range != 1;)
Packit df99a1
    {
Packit df99a1
      if (! *pctx)
Packit df99a1
        {
Packit df99a1
          const int max_ncell=gbitcells;
Packit df99a1
          if (cur_ncell >= max_ncell)
Packit df99a1
            {
Packit df99a1
              const int nmax_ncell = max_ncell+CELLCHUNK;
Packit df99a1
              gbitcells.resize(nmax_ncell);
Packit df99a1
              gleftcell.resize(nmax_ncell);
Packit df99a1
              grightcell.resize(nmax_ncell);
Packit df99a1
            }
Packit df99a1
          *pctx = cur_ncell ++;
Packit df99a1
          bitcells[*pctx] = 0;
Packit df99a1
          leftcell[*pctx] = rightcell[*pctx] = 0;
Packit df99a1
        }
Packit df99a1
      // encode
Packit df99a1
      const bool decision = encoding
Packit df99a1
        ? ((low < cutoff && high >= cutoff)
Packit df99a1
          ? CodeBit((v>=cutoff),bitcells[*pctx])
Packit df99a1
          : (v >= cutoff))
Packit df99a1
        : ((low>=cutoff)||((high>=cutoff)&&CodeBit(false,bitcells[*pctx])));
Packit df99a1
      // context for new bit
Packit df99a1
      pctx = decision?(&rightcell[*pctx]):(&leftcell[*pctx]);
Packit df99a1
      // phase dependent part
Packit df99a1
      switch (phase) 
Packit df99a1
        {
Packit df99a1
	case 1:
Packit df99a1
          negative = !decision;
Packit df99a1
          if (negative) 
Packit df99a1
            {
Packit df99a1
              if (encoding)
Packit df99a1
                v = - v - 1;
Packit df99a1
              const int temp = - low - 1; 
Packit df99a1
              low = - high - 1; 
Packit df99a1
              high = temp;
Packit df99a1
	    }
Packit df99a1
          phase = 2; cutoff =  1;
Packit df99a1
          break;
Packit df99a1
          
Packit df99a1
	case 2:
Packit df99a1
          if (!decision) 
Packit df99a1
            {
Packit df99a1
              phase = 3;
Packit df99a1
              range = (cutoff + 1) / 2;
Packit df99a1
              if (range == 1)
Packit df99a1
                cutoff = 0;
Packit df99a1
              else
Packit df99a1
                cutoff -= range / 2;
Packit df99a1
	    }
Packit df99a1
          else 
Packit df99a1
            { 
Packit df99a1
              cutoff += cutoff + 1; 
Packit df99a1
            }
Packit df99a1
          break;
Packit df99a1
Packit df99a1
	case 3:
Packit df99a1
          range /= 2;
Packit df99a1
          if (range != 1) 
Packit df99a1
            {
Packit df99a1
              if (!decision)
Packit df99a1
                cutoff -= range / 2;
Packit df99a1
              else               
Packit df99a1
                cutoff += range / 2;
Packit df99a1
	    }
Packit df99a1
          else if (!decision) 
Packit df99a1
            {
Packit df99a1
                cutoff --;
Packit df99a1
	    }
Packit df99a1
          break;
Packit df99a1
	}
Packit df99a1
    }
Packit df99a1
    return (negative)?(- cutoff - 1):cutoff;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// CODE COMMENTS
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::JB2Codec::Decode::code_comment(GUTF8String &comment)
Packit df99a1
{
Packit df99a1
      int size=CodeNum(0, BIGPOSITIVE, dist_comment_length);
Packit df99a1
      comment.empty();
Packit df99a1
      char *combuf = comment.getbuf(size);
Packit df99a1
      for (int i=0; i
Packit df99a1
        {
Packit df99a1
          combuf[i]=CodeNum(0, 255, dist_comment_byte);
Packit df99a1
        }
Packit df99a1
      comment.getbuf();
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
// LIBRARY
Packit df99a1
Packit df99a1
Packit df99a1
void
Packit df99a1
JB2Dict::JB2Codec::init_library(JB2Dict &jim)
Packit df99a1
{
Packit df99a1
  int nshape = jim.get_inherited_shape_count();
Packit df99a1
  shape2lib.resize(0,nshape-1);
Packit df99a1
  lib2shape.resize(0,nshape-1);
Packit df99a1
  libinfo.resize(0,nshape-1);
Packit df99a1
  for (int i=0; i
Packit df99a1
    {
Packit df99a1
      shape2lib[i] = i;
Packit df99a1
      lib2shape[i] = i;
Packit df99a1
      jim.get_bounding_box(i, libinfo[i]);
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
int 
Packit df99a1
JB2Dict::JB2Codec::add_library(const int shapeno, JB2Shape &jshp)
Packit df99a1
{
Packit df99a1
  const int libno = lib2shape.hbound() + 1;
Packit df99a1
  lib2shape.touch(libno);
Packit df99a1
  lib2shape[libno] = shapeno;
Packit df99a1
  shape2lib.touch(shapeno);
Packit df99a1
  shape2lib[shapeno] = libno;
Packit df99a1
  libinfo.touch(libno);
Packit df99a1
  libinfo[libno].compute_bounding_box(*(jshp.bits));
Packit df99a1
  return libno;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
// CODE SIMPLE VALUES
Packit df99a1
Packit df99a1
inline void 
Packit df99a1
JB2Dict::JB2Codec::Decode::code_record_type(int &rectype)
Packit df99a1
{
Packit df99a1
  rectype=CodeNum( START_OF_DATA, END_OF_DATA, dist_record_type);
Packit df99a1
}
Packit df99a1
Packit df99a1
int 
Packit df99a1
JB2Dict::JB2Codec::Decode::code_match_index(int &index, JB2Dict &)
Packit df99a1
{
Packit df99a1
    int match=CodeNum(0, lib2shape.hbound(), dist_match_index);
Packit df99a1
    index = lib2shape[match];
Packit df99a1
    return match;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
// HANDLE SHORT LIST
Packit df99a1
Packit df99a1
int 
Packit df99a1
JB2Dict::JB2Codec::update_short_list(const int v)
Packit df99a1
{
Packit df99a1
  if (++ short_list_pos == 3)
Packit df99a1
    short_list_pos = 0;
Packit df99a1
  int * const s = short_list;
Packit df99a1
  s[short_list_pos] = v;
Packit df99a1
Packit df99a1
  return (s[0] >= s[1])
Packit df99a1
    ?((s[0] > s[2])?((s[1] >= s[2])?s[1]:s[2]):s[0])
Packit df99a1
    :((s[0] < s[2])?((s[1] >= s[2])?s[2]:s[1]):s[0]);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// CODE PAIRS
Packit df99a1
Packit df99a1
Packit df99a1
void
Packit df99a1
JB2Dict::JB2Codec::Decode::code_inherited_shape_count(JB2Dict &jim)
Packit df99a1
{
Packit df99a1
  int size=CodeNum(0, BIGPOSITIVE, inherited_shape_count_dist);
Packit df99a1
    {
Packit df99a1
      GP<JB2Dict> dict = jim.get_inherited_dict();
Packit df99a1
      if (!dict && size>0)
Packit df99a1
        {
Packit df99a1
          // Call callback function to obtain dictionary
Packit df99a1
          if (cbfunc)
Packit df99a1
            dict = (*cbfunc)(cbarg);
Packit df99a1
          if (dict)
Packit df99a1
            jim.set_inherited_dict(dict);
Packit df99a1
        }
Packit df99a1
      if (!dict && size>0)
Packit df99a1
        G_THROW( ERR_MSG("JB2Image.need_dict") );
Packit df99a1
      if (dict && size!=dict->get_shape_count())
Packit df99a1
        G_THROW( ERR_MSG("JB2Image.bad_dict") );
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::JB2Codec::Decode::code_image_size(JB2Dict &jim)
Packit df99a1
{
Packit df99a1
  int w=CodeNum(0, BIGPOSITIVE, image_size_dist);
Packit df99a1
  int h=CodeNum(0, BIGPOSITIVE, image_size_dist);
Packit df99a1
  if (w || h)
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.bad_dict2") );
Packit df99a1
  JB2Codec::code_image_size(jim);
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::JB2Codec::code_image_size(JB2Dict &)
Packit df99a1
{
Packit df99a1
  last_left = 1;
Packit df99a1
  last_row_left = 0;
Packit df99a1
  last_row_bottom = 0;
Packit df99a1
  last_right = 0;
Packit df99a1
  fill_short_list(last_row_bottom);
Packit df99a1
  gotstartrecordp = 1;
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::JB2Codec::Decode::code_image_size(JB2Image &jim)
Packit df99a1
{
Packit df99a1
  image_columns=CodeNum(0, BIGPOSITIVE, image_size_dist);
Packit df99a1
  image_rows=CodeNum(0, BIGPOSITIVE, image_size_dist);
Packit df99a1
  if (!image_columns || !image_rows)
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.zero_dim") );
Packit df99a1
  jim.set_dimension(image_columns, image_rows);
Packit df99a1
  JB2Codec::code_image_size(jim);
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::JB2Codec::code_image_size(JB2Image &)
Packit df99a1
{
Packit df99a1
  last_left = 1 + image_columns;
Packit df99a1
  last_row_left = 0;
Packit df99a1
  last_row_bottom = image_rows;
Packit df99a1
  last_right = 0;
Packit df99a1
  fill_short_list(last_row_bottom);
Packit df99a1
  gotstartrecordp = 1;
Packit df99a1
}
Packit df99a1
Packit df99a1
inline int
Packit df99a1
JB2Dict::JB2Codec::Decode::get_diff(int,NumContext &rel_loc)
Packit df99a1
{
Packit df99a1
   return CodeNum(BIGNEGATIVE, BIGPOSITIVE, rel_loc);
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::JB2Codec::code_relative_location(JB2Blit *jblt, int rows, int columns)
Packit df99a1
{
Packit df99a1
  // Check start record
Packit df99a1
  if (!gotstartrecordp)
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.no_start") );
Packit df99a1
  // Find location
Packit df99a1
  int bottom=0, left=0, top=0, right=0;
Packit df99a1
  int x_diff, y_diff;
Packit df99a1
  if (encoding)
Packit df99a1
    {
Packit df99a1
      left = jblt->left + 1;
Packit df99a1
      bottom = jblt->bottom + 1;
Packit df99a1
      right = left + columns - 1;
Packit df99a1
      top = bottom + rows - 1;
Packit df99a1
    }
Packit df99a1
  // Code offset type
Packit df99a1
  int new_row=CodeBit((left
Packit df99a1
  if (new_row)
Packit df99a1
    {
Packit df99a1
      // Begin a new row
Packit df99a1
      x_diff=get_diff(left-last_row_left,rel_loc_x_last);
Packit df99a1
      y_diff=get_diff(top-last_row_bottom,rel_loc_y_last);
Packit df99a1
      if (!encoding)
Packit df99a1
        {
Packit df99a1
          left = last_row_left + x_diff;
Packit df99a1
          top = last_row_bottom + y_diff;
Packit df99a1
          right = left + columns - 1;
Packit df99a1
          bottom = top - rows + 1;
Packit df99a1
        }
Packit df99a1
      last_left = last_row_left = left;
Packit df99a1
      last_right = right;
Packit df99a1
      last_bottom = last_row_bottom = bottom;
Packit df99a1
      fill_short_list(bottom);
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    {
Packit df99a1
      // Same row
Packit df99a1
      x_diff=get_diff(left-last_right,rel_loc_x_current);
Packit df99a1
      y_diff=get_diff(bottom-last_bottom,rel_loc_y_current);
Packit df99a1
      if (!encoding)
Packit df99a1
        {
Packit df99a1
          left = last_right + x_diff;
Packit df99a1
          bottom = last_bottom + y_diff;
Packit df99a1
          right = left + columns - 1;
Packit df99a1
          top = bottom + rows - 1;
Packit df99a1
        }
Packit df99a1
      last_left = left;
Packit df99a1
      last_right = right;
Packit df99a1
      last_bottom = update_short_list(bottom);
Packit df99a1
    }
Packit df99a1
  // Store in blit record
Packit df99a1
  if (!encoding)
Packit df99a1
    {
Packit df99a1
      jblt->bottom = bottom - 1;
Packit df99a1
      jblt->left = left - 1;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::JB2Codec::Decode::code_absolute_location(JB2Blit *jblt, int rows, int columns)
Packit df99a1
{
Packit df99a1
  // Check start record
Packit df99a1
  if (!gotstartrecordp)
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.no_start") );
Packit df99a1
  int left=CodeNum(1, image_columns, abs_loc_x);
Packit df99a1
  int top=CodeNum(1, image_rows, abs_loc_y);
Packit df99a1
  jblt->bottom = top - rows + 1 - 1;
Packit df99a1
  jblt->left = left - 1;
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::JB2Codec::Decode::code_absolute_mark_size(GBitmap &bm, int border)
Packit df99a1
{
Packit df99a1
  int xsize=CodeNum(0, BIGPOSITIVE, abs_size_x);
Packit df99a1
  int ysize=CodeNum(0, BIGPOSITIVE, abs_size_y);
Packit df99a1
  if ((xsize!=(unsigned short)xsize) || (ysize!=(unsigned short)ysize))
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
  bm.init(ysize, xsize, border);
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::JB2Codec::Decode::code_relative_mark_size(GBitmap &bm, int cw, int ch, int border)
Packit df99a1
{
Packit df99a1
  int xdiff=CodeNum(BIGNEGATIVE, BIGPOSITIVE, rel_size_x);
Packit df99a1
  int ydiff=CodeNum(BIGNEGATIVE, BIGPOSITIVE, rel_size_y);
Packit df99a1
  int xsize = cw + xdiff;
Packit df99a1
  int ysize = ch + ydiff;
Packit df99a1
  if ((xsize!=(unsigned short)xsize) || (ysize!=(unsigned short)ysize))
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
  bm.init(ysize, xsize, border);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// CODE BITMAP DIRECTLY
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::JB2Codec::code_bitmap_directly (GBitmap &bm)
Packit df99a1
{
Packit df99a1
  // Make sure bitmap will not be disturbed
Packit df99a1
  GMonitorLock lock(bm.monitor());
Packit df99a1
  // ensure borders are adequate
Packit df99a1
  bm.minborder(3);
Packit df99a1
  // initialize row pointers
Packit df99a1
  int dy = bm.rows() - 1;
Packit df99a1
  code_bitmap_directly(bm,bm.columns(),dy,bm[dy+2],bm[dy+1],bm[dy]);
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::JB2Codec::Decode::code_bitmap_directly(
Packit df99a1
  GBitmap &bm,const int dw, int dy,
Packit df99a1
  unsigned char *up2, unsigned char *up1, unsigned char *up0 )
Packit df99a1
{
Packit df99a1
      ZPCodec &zp=*gzp;
Packit df99a1
      // iterate on rows (decoding)      
Packit df99a1
      while (dy >= 0)
Packit df99a1
        {
Packit df99a1
          int context=get_direct_context(up2, up1, up0, 0);
Packit df99a1
          for(int dx=0;dx < dw;)
Packit df99a1
            {
Packit df99a1
              int n = zp.decoder(bitdist[context]);
Packit df99a1
              up0[dx++] = n;
Packit df99a1
              context=shift_direct_context(context, n, up2, up1, up0, dx);
Packit df99a1
            }
Packit df99a1
          // next row
Packit df99a1
          dy -= 1;
Packit df99a1
          up2 = up1;
Packit df99a1
          up1 = up0;
Packit df99a1
          up0 = bm[dy];
Packit df99a1
        }
Packit df99a1
#ifndef NDEBUG
Packit df99a1
      bm.check_border();
Packit df99a1
#endif
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// CODE BITMAP BY CROSS CODING
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::JB2Codec::code_bitmap_by_cross_coding (GBitmap &bm, GP<GBitmap> &cbm, const int libno)
Packit df99a1
{
Packit df99a1
  // Make sure bitmaps will not be disturbed
Packit df99a1
  GP<GBitmap> copycbm=GBitmap::create();
Packit df99a1
  if (cbm->monitor())
Packit df99a1
    {
Packit df99a1
      // Perform a copy when the bitmap is explicitely shared
Packit df99a1
      GMonitorLock lock2(cbm->monitor());
Packit df99a1
      copycbm->init(*cbm);
Packit df99a1
      cbm = copycbm;
Packit df99a1
    }
Packit df99a1
  GMonitorLock lock1(bm.monitor());
Packit df99a1
  // Center bitmaps
Packit df99a1
  const int cw = cbm->columns();
Packit df99a1
  const int dw = bm.columns();
Packit df99a1
  const int dh = bm.rows();
Packit df99a1
  const LibRect &l = libinfo[libno];
Packit df99a1
  const int xd2c = (dw/2 - dw + 1) - ((l.right - l.left + 1)/2 - l.right);
Packit df99a1
  const int yd2c = (dh/2 - dh + 1) - ((l.top - l.bottom + 1)/2 - l.top);
Packit df99a1
  // Ensure borders are adequate
Packit df99a1
  bm.minborder(2);
Packit df99a1
  cbm->minborder(2-xd2c);
Packit df99a1
  cbm->minborder(2+dw+xd2c-cw);
Packit df99a1
  // Initialize row pointers
Packit df99a1
  const int dy = dh - 1;
Packit df99a1
  const int cy = dy + yd2c;
Packit df99a1
#ifndef NDEBUG
Packit df99a1
  bm.check_border();
Packit df99a1
  cbm->check_border();
Packit df99a1
#endif
Packit df99a1
  code_bitmap_by_cross_coding (bm,*cbm, xd2c, dw, dy, cy, bm[dy+1], bm[dy],
Packit df99a1
    (*cbm)[cy+1] + xd2c, (*cbm)[cy  ] + xd2c, (*cbm)[cy-1] + xd2c);
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::JB2Codec::Decode::code_bitmap_by_cross_coding (GBitmap &bm, GBitmap &cbm,
Packit df99a1
  const int xd2c, const int dw, int dy, int cy,
Packit df99a1
  unsigned char *up1, unsigned char *up0, unsigned char *xup1, 
Packit df99a1
  unsigned char *xup0, unsigned char *xdn1 )
Packit df99a1
{
Packit df99a1
      ZPCodec &zp=*gzp;
Packit df99a1
      // iterate on rows (decoding)      
Packit df99a1
      while (dy >= 0)
Packit df99a1
        {
Packit df99a1
          int context=get_cross_context(
Packit df99a1
                            up1, up0, xup1, xup0, xdn1, 0);
Packit df99a1
          for(int dx=0;dx < dw;)
Packit df99a1
            {
Packit df99a1
              const int n = zp.decoder(cbitdist[context]);
Packit df99a1
              up0[dx++] = n;
Packit df99a1
              context=shift_cross_context(context, n,  
Packit df99a1
                                  up1, up0, xup1, xup0, xdn1, dx);
Packit df99a1
            }
Packit df99a1
          // next row
Packit df99a1
          up1 = up0;
Packit df99a1
          up0 = bm[--dy];
Packit df99a1
          xup1 = xup0;
Packit df99a1
          xup0 = xdn1;
Packit df99a1
          xdn1 = cbm[(--cy)-1] + xd2c;
Packit df99a1
#ifndef NDEBUG
Packit df99a1
          bm.check_border();
Packit df99a1
#endif
Packit df99a1
        }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// CODE JB2DICT RECORD
Packit df99a1
Packit df99a1
void
Packit df99a1
JB2Dict::JB2Codec::code_record(
Packit df99a1
  int &rectype, const GP<JB2Dict> &gjim, JB2Shape *xjshp)
Packit df99a1
{
Packit df99a1
  GP<GBitmap> cbm;
Packit df99a1
  GP<GBitmap> bm;
Packit df99a1
  int shapeno = -1;
Packit df99a1
Packit df99a1
  // Code record type
Packit df99a1
  code_record_type(rectype);
Packit df99a1
  
Packit df99a1
  // Pre-coding actions
Packit df99a1
  switch(rectype)
Packit df99a1
    {
Packit df99a1
    case NEW_MARK_LIBRARY_ONLY:
Packit df99a1
    case MATCHED_REFINE_LIBRARY_ONLY:
Packit df99a1
      {
Packit df99a1
        if(!xjshp)
Packit df99a1
        {
Packit df99a1
          G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
        }
Packit df99a1
        JB2Shape &jshp=*xjshp;
Packit df99a1
        if (!encoding) 
Packit df99a1
        {
Packit df99a1
          jshp.bits = GBitmap::create();
Packit df99a1
          jshp.parent = -1;
Packit df99a1
        }
Packit df99a1
        bm = jshp.bits;
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
  // Coding actions
Packit df99a1
  switch (rectype)
Packit df99a1
    {
Packit df99a1
    case START_OF_DATA:
Packit df99a1
      {
Packit df99a1
        if(!gjim)
Packit df99a1
        {
Packit df99a1
           G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
        }
Packit df99a1
        JB2Dict &jim=*gjim;
Packit df99a1
        code_image_size (jim);
Packit df99a1
        code_eventual_lossless_refinement ();
Packit df99a1
        if (! encoding)
Packit df99a1
          init_library(jim);
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    case NEW_MARK_LIBRARY_ONLY:
Packit df99a1
      {
Packit df99a1
        code_absolute_mark_size (*bm, 4);
Packit df99a1
        code_bitmap_directly (*bm);
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    case MATCHED_REFINE_LIBRARY_ONLY:
Packit df99a1
      {
Packit df99a1
        if(!xjshp||!gjim)
Packit df99a1
        {
Packit df99a1
           G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
        }
Packit df99a1
        JB2Dict &jim=*gjim;
Packit df99a1
        JB2Shape &jshp=*xjshp;
Packit df99a1
        int match = code_match_index (jshp.parent, jim);
Packit df99a1
        cbm = jim.get_shape(jshp.parent).bits;
Packit df99a1
        LibRect &l = libinfo[match];
Packit df99a1
        code_relative_mark_size (*bm, l.right-l.left+1, l.top-l.bottom+1, 4);
Packit df99a1
        code_bitmap_by_cross_coding (*bm, cbm, jshp.parent);
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    case PRESERVED_COMMENT:
Packit df99a1
      {
Packit df99a1
        if(!gjim)
Packit df99a1
        {
Packit df99a1
           G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
        }
Packit df99a1
        JB2Dict &jim=*gjim;
Packit df99a1
        code_comment(jim.comment);
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    case REQUIRED_DICT_OR_RESET:
Packit df99a1
      {
Packit df99a1
        if (! gotstartrecordp)
Packit df99a1
        {
Packit df99a1
	  // Indicates need for a shape dictionary
Packit df99a1
          if(!gjim)
Packit df99a1
          {
Packit df99a1
             G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
          }
Packit df99a1
	  code_inherited_shape_count(*gjim);
Packit df99a1
        }else
Packit df99a1
	  // Reset all numerical contexts to zero
Packit df99a1
	  reset_numcoder();
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    case END_OF_DATA:
Packit df99a1
      {
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    default:
Packit df99a1
      {
Packit df99a1
        G_THROW( ERR_MSG("JB2Image.bad_type") );
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
  // Post-coding action
Packit df99a1
  if (!encoding)
Packit df99a1
    {
Packit df99a1
      // add shape to dictionary
Packit df99a1
      switch(rectype)
Packit df99a1
        {
Packit df99a1
        case NEW_MARK_LIBRARY_ONLY:
Packit df99a1
        case MATCHED_REFINE_LIBRARY_ONLY:
Packit df99a1
          {
Packit df99a1
            if(!xjshp||!gjim)
Packit df99a1
            {
Packit df99a1
               G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
            }
Packit df99a1
            JB2Shape &jshp=*xjshp;
Packit df99a1
            shapeno = gjim->add_shape(jshp);
Packit df99a1
            add_library(shapeno, jshp);
Packit df99a1
            break;
Packit df99a1
          }
Packit df99a1
        }
Packit df99a1
      // make sure everything is compacted
Packit df99a1
      // decompaction will occur automatically when needed
Packit df99a1
      if (bm)
Packit df99a1
        bm->compress();
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
// CODE JB2DICT
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::JB2Codec::Decode::code(const GP<JB2Dict> &gjim)
Packit df99a1
{
Packit df99a1
  if(!gjim)
Packit df99a1
  {
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
  }
Packit df99a1
  JB2Dict &jim=*gjim;
Packit df99a1
  // -------------------------
Packit df99a1
  // THIS IS THE DECODING PART
Packit df99a1
  // -------------------------
Packit df99a1
  int rectype;
Packit df99a1
  JB2Shape tmpshape;
Packit df99a1
  do {
Packit df99a1
    code_record(rectype, gjim, &tmpshape);        
Packit df99a1
  } while(rectype != END_OF_DATA);
Packit df99a1
  if (!gotstartrecordp)
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.no_start") );
Packit df99a1
  // cache bounding boxes
Packit df99a1
  int nshapes = jim.get_shape_count();
Packit df99a1
  int ishapes = jim.get_inherited_shape_count();
Packit df99a1
  jim.boxes.resize(0, nshapes-ishapes-1);
Packit df99a1
  for (int i = ishapes; i < nshapes; i++)
Packit df99a1
    jim.boxes[i-ishapes] = libinfo[i];
Packit df99a1
  // compress
Packit df99a1
  jim.compress();
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
// CODE JB2IMAGE RECORD
Packit df99a1
Packit df99a1
void
Packit df99a1
JB2Dict::JB2Codec::code_record(
Packit df99a1
  int &rectype, const GP<JB2Image> &gjim, JB2Shape *xjshp, JB2Blit *jblt)
Packit df99a1
{
Packit df99a1
  GP<GBitmap> bm;
Packit df99a1
  GP<GBitmap> cbm;
Packit df99a1
  int shapeno = -1;
Packit df99a1
  int match;
Packit df99a1
Packit df99a1
  // Code record type
Packit df99a1
  code_record_type(rectype);
Packit df99a1
  
Packit df99a1
  // Pre-coding actions
Packit df99a1
  switch(rectype)
Packit df99a1
    {
Packit df99a1
    case NEW_MARK:
Packit df99a1
    case NEW_MARK_LIBRARY_ONLY:
Packit df99a1
    case NEW_MARK_IMAGE_ONLY:
Packit df99a1
    case MATCHED_REFINE:
Packit df99a1
    case MATCHED_REFINE_LIBRARY_ONLY:
Packit df99a1
    case MATCHED_REFINE_IMAGE_ONLY:
Packit df99a1
    case NON_MARK_DATA:
Packit df99a1
      {
Packit df99a1
        if(!xjshp)
Packit df99a1
        {
Packit df99a1
           G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
        }
Packit df99a1
        JB2Shape &jshp=*xjshp;
Packit df99a1
        if (!encoding) 
Packit df99a1
        {
Packit df99a1
          jshp.bits = GBitmap::create();
Packit df99a1
          jshp.parent = -1;
Packit df99a1
          if (rectype == NON_MARK_DATA)
Packit df99a1
            jshp.parent = -2;
Packit df99a1
        }
Packit df99a1
        bm = jshp.bits;
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
  // Coding actions
Packit df99a1
  switch (rectype)
Packit df99a1
    {
Packit df99a1
    case START_OF_DATA:
Packit df99a1
      {
Packit df99a1
        if(!gjim)
Packit df99a1
        {
Packit df99a1
           G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
        }
Packit df99a1
        JB2Image &jim=*gjim;
Packit df99a1
        code_image_size (jim);
Packit df99a1
        code_eventual_lossless_refinement ();
Packit df99a1
        if (! encoding)
Packit df99a1
          init_library(jim);
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    case NEW_MARK:
Packit df99a1
      {
Packit df99a1
        code_absolute_mark_size (*bm, 4);
Packit df99a1
        code_bitmap_directly (*bm);
Packit df99a1
        code_relative_location (jblt, bm->rows(), bm->columns() );
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    case NEW_MARK_LIBRARY_ONLY:
Packit df99a1
      {
Packit df99a1
        code_absolute_mark_size (*bm, 4);
Packit df99a1
        code_bitmap_directly (*bm);
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    case NEW_MARK_IMAGE_ONLY:
Packit df99a1
      {
Packit df99a1
        code_absolute_mark_size (*bm, 3);
Packit df99a1
        code_bitmap_directly (*bm);
Packit df99a1
        code_relative_location (jblt, bm->rows(), bm->columns() );
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    case MATCHED_REFINE:
Packit df99a1
      {
Packit df99a1
        if(!xjshp || !gjim)
Packit df99a1
        {
Packit df99a1
           G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
        }
Packit df99a1
        JB2Shape &jshp=*xjshp;
Packit df99a1
        JB2Image &jim=*gjim;
Packit df99a1
        match = code_match_index (jshp.parent, jim);
Packit df99a1
        cbm = jim.get_shape(jshp.parent).bits;
Packit df99a1
        LibRect &l = libinfo[match];
Packit df99a1
        code_relative_mark_size (*bm, l.right-l.left+1, l.top-l.bottom+1, 4); 
Packit df99a1
        code_bitmap_by_cross_coding (*bm, cbm, match);
Packit df99a1
        code_relative_location (jblt, bm->rows(), bm->columns() );
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    case MATCHED_REFINE_LIBRARY_ONLY:
Packit df99a1
      {
Packit df99a1
        if(!xjshp||!gjim)
Packit df99a1
        {
Packit df99a1
           G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
        }
Packit df99a1
        JB2Image &jim=*gjim;
Packit df99a1
        JB2Shape &jshp=*xjshp;
Packit df99a1
        match = code_match_index (jshp.parent, jim);
Packit df99a1
        cbm = jim.get_shape(jshp.parent).bits;
Packit df99a1
        LibRect &l = libinfo[match];
Packit df99a1
        code_relative_mark_size (*bm, l.right-l.left+1, l.top-l.bottom+1, 4);
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    case MATCHED_REFINE_IMAGE_ONLY:
Packit df99a1
      {
Packit df99a1
        if(!xjshp||!gjim)
Packit df99a1
        {
Packit df99a1
           G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
        }
Packit df99a1
        JB2Image &jim=*gjim;
Packit df99a1
        JB2Shape &jshp=*xjshp;
Packit df99a1
        match = code_match_index (jshp.parent, jim);
Packit df99a1
        cbm = jim.get_shape(jshp.parent).bits;
Packit df99a1
        LibRect &l = libinfo[match];
Packit df99a1
        code_relative_mark_size (*bm, l.right-l.left+1, l.top-l.bottom+1, 4);
Packit df99a1
        code_bitmap_by_cross_coding (*bm, cbm, match);
Packit df99a1
        code_relative_location (jblt, bm->rows(), bm->columns() );
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    case MATCHED_COPY:
Packit df99a1
      {
Packit df99a1
        int temp;
Packit df99a1
        if (encoding) temp = jblt->shapeno;
Packit df99a1
        if(!gjim)
Packit df99a1
        {
Packit df99a1
           G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
        }
Packit df99a1
        JB2Image &jim=*gjim;
Packit df99a1
        match = code_match_index (temp, jim);
Packit df99a1
        if (!encoding) jblt->shapeno = temp;
Packit df99a1
        bm = jim.get_shape(jblt->shapeno).bits;
Packit df99a1
        LibRect &l = libinfo[match];
Packit df99a1
        jblt->left += l.left;
Packit df99a1
        jblt->bottom += l.bottom;
Packit df99a1
        if (jim.reproduce_old_bug)
Packit df99a1
          code_relative_location (jblt, bm->rows(), bm->columns() );
Packit df99a1
        else
Packit df99a1
          code_relative_location (jblt, l.top-l.bottom+1, l.right-l.left+1 );
Packit df99a1
        jblt->left -= l.left;
Packit df99a1
        jblt->bottom -= l.bottom; 
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    case NON_MARK_DATA:
Packit df99a1
      {
Packit df99a1
        code_absolute_mark_size (*bm, 3);
Packit df99a1
        code_bitmap_directly (*bm);
Packit df99a1
        code_absolute_location (jblt, bm->rows(), bm->columns() );
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    case PRESERVED_COMMENT:
Packit df99a1
      {
Packit df99a1
        if(!gjim)
Packit df99a1
        {
Packit df99a1
           G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
        }
Packit df99a1
        JB2Image &jim=*gjim;
Packit df99a1
        code_comment(jim.comment);
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    case REQUIRED_DICT_OR_RESET:
Packit df99a1
      {
Packit df99a1
        if(!gjim)
Packit df99a1
        {
Packit df99a1
           G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
        }
Packit df99a1
        JB2Image &jim=*gjim;
Packit df99a1
        if (! gotstartrecordp)
Packit df99a1
	  // Indicates need for a shape dictionary
Packit df99a1
	  code_inherited_shape_count(jim);
Packit df99a1
	else
Packit df99a1
	  // Reset all numerical contexts to zero
Packit df99a1
	  reset_numcoder();
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    case END_OF_DATA:
Packit df99a1
      {
Packit df99a1
        break;
Packit df99a1
      }
Packit df99a1
    default:
Packit df99a1
      {
Packit df99a1
        G_THROW( ERR_MSG("JB2Image.unknown_type") );
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
  
Packit df99a1
  // Post-coding action
Packit df99a1
  if (!encoding)
Packit df99a1
    {
Packit df99a1
      // add shape to image
Packit df99a1
      switch(rectype)
Packit df99a1
        {
Packit df99a1
        case NEW_MARK:
Packit df99a1
        case NEW_MARK_LIBRARY_ONLY:
Packit df99a1
        case NEW_MARK_IMAGE_ONLY:
Packit df99a1
        case MATCHED_REFINE:
Packit df99a1
        case MATCHED_REFINE_LIBRARY_ONLY:
Packit df99a1
        case MATCHED_REFINE_IMAGE_ONLY:
Packit df99a1
        case NON_MARK_DATA:
Packit df99a1
          {
Packit df99a1
            if(!xjshp||!gjim)
Packit df99a1
            {
Packit df99a1
              G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
            }
Packit df99a1
            JB2Shape &jshp=*xjshp;
Packit df99a1
            shapeno = gjim->add_shape(jshp);
Packit df99a1
            shape2lib.touch(shapeno);
Packit df99a1
            shape2lib[shapeno] = -1;
Packit df99a1
            break;
Packit df99a1
          }
Packit df99a1
        }
Packit df99a1
      // add shape to library
Packit df99a1
      switch(rectype)
Packit df99a1
        {
Packit df99a1
        case NEW_MARK:
Packit df99a1
        case NEW_MARK_LIBRARY_ONLY:
Packit df99a1
        case MATCHED_REFINE:
Packit df99a1
        case MATCHED_REFINE_LIBRARY_ONLY:
Packit df99a1
          if(!xjshp)
Packit df99a1
          {
Packit df99a1
            G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
          }
Packit df99a1
          add_library(shapeno, *xjshp);
Packit df99a1
          break;
Packit df99a1
        }
Packit df99a1
      // make sure everything is compacted
Packit df99a1
      // decompaction will occur automatically on cross-coding bitmaps
Packit df99a1
      if (bm)
Packit df99a1
        bm->compress();
Packit df99a1
      // add blit to image
Packit df99a1
      switch (rectype)
Packit df99a1
        {
Packit df99a1
        case NEW_MARK:
Packit df99a1
        case NEW_MARK_IMAGE_ONLY:
Packit df99a1
        case MATCHED_REFINE:
Packit df99a1
        case MATCHED_REFINE_IMAGE_ONLY:
Packit df99a1
        case NON_MARK_DATA:
Packit df99a1
          jblt->shapeno = shapeno;
Packit df99a1
        case MATCHED_COPY:
Packit df99a1
          if(!gjim)
Packit df99a1
          {
Packit df99a1
            G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
          }
Packit df99a1
          gjim->add_blit(* jblt);
Packit df99a1
          break;
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
// CODE JB2IMAGE
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::JB2Codec::Decode::code(const GP<JB2Image> &gjim)
Packit df99a1
{
Packit df99a1
  if(!gjim)
Packit df99a1
  {
Packit df99a1
    G_THROW( ERR_MSG("JB2Image.bad_number") );
Packit df99a1
  }
Packit df99a1
  JB2Image &jim=*gjim;
Packit df99a1
      // -------------------------
Packit df99a1
      // THIS IS THE DECODING PART
Packit df99a1
      // -------------------------
Packit df99a1
      int rectype;
Packit df99a1
      JB2Blit tmpblit;
Packit df99a1
      JB2Shape tmpshape;
Packit df99a1
      do
Packit df99a1
        {
Packit df99a1
          code_record(rectype, gjim, &tmpshape, &tmpblit);        
Packit df99a1
        } 
Packit df99a1
      while(rectype!=END_OF_DATA);
Packit df99a1
      if (!gotstartrecordp)
Packit df99a1
        G_THROW( ERR_MSG("JB2Image.no_start") );
Packit df99a1
      jim.compress();
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
////////////////////////////////////////
Packit df99a1
//// HELPERS
Packit df99a1
////////////////////////////////////////
Packit df99a1
Packit df99a1
void 
Packit df99a1
JB2Dict::LibRect::compute_bounding_box(const GBitmap &bm)
Packit df99a1
{
Packit df99a1
  // Avoid trouble
Packit df99a1
  GMonitorLock lock(bm.monitor());
Packit df99a1
  // Get size
Packit df99a1
  const int w = bm.columns();
Packit df99a1
  const int h = bm.rows();
Packit df99a1
  const int s = bm.rowsize();
Packit df99a1
  // Right border
Packit df99a1
  for(right=w-1;right >= 0;--right)
Packit df99a1
    {
Packit df99a1
      unsigned char const *p = bm[0] + right;
Packit df99a1
      unsigned char const * const pe = p+(s*h);
Packit df99a1
      for (;(p
Packit df99a1
      	continue;
Packit df99a1
      if (p
Packit df99a1
        break;
Packit df99a1
    }
Packit df99a1
  // Top border
Packit df99a1
  for(top=h-1;top >= 0;--top)
Packit df99a1
    {
Packit df99a1
      unsigned char const *p = bm[top];
Packit df99a1
      unsigned char const * const pe = p+w;
Packit df99a1
      for (;(p
Packit df99a1
      	continue;
Packit df99a1
      if (p
Packit df99a1
        break;
Packit df99a1
    }
Packit df99a1
  // Left border
Packit df99a1
  for (left=0;left <= right;++left)
Packit df99a1
    {
Packit df99a1
      unsigned char const *p = bm[0] + left;
Packit df99a1
      unsigned char const * const pe=p+(s*h);
Packit df99a1
      for (;(p
Packit df99a1
      	continue;
Packit df99a1
      if (p
Packit df99a1
        break;
Packit df99a1
    }
Packit df99a1
  // Bottom border
Packit df99a1
  for(bottom=0;bottom <= top;++bottom)
Packit df99a1
    {
Packit df99a1
      unsigned char const *p = bm[bottom];
Packit df99a1
      unsigned char const * const pe = p+w;
Packit df99a1
      for (;(p
Packit df99a1
      	continue;
Packit df99a1
      if (p
Packit df99a1
        break;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void
Packit df99a1
JB2Dict::get_bounding_box(int shapeno, LibRect &dest)
Packit df99a1
{
Packit df99a1
  if (shapeno < inherited_shapes && inherited_dict)
Packit df99a1
    {
Packit df99a1
      inherited_dict->get_bounding_box(shapeno, dest);
Packit df99a1
    }
Packit df99a1
  else if (shapeno >= inherited_shapes &&
Packit df99a1
           shapeno < inherited_shapes + boxes.size())
Packit df99a1
    {
Packit df99a1
      dest = boxes[shapeno - inherited_shapes];
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    {
Packit df99a1
      JB2Shape &jshp = get_shape(shapeno);
Packit df99a1
      dest.compute_bounding_box(*(jshp.bits));
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
GP<JB2Dict>
Packit df99a1
JB2Dict::create(void)
Packit df99a1
{
Packit df99a1
  return new JB2Dict();
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
}
Packit df99a1
# ifndef NOT_USING_DJVU_NAMESPACE
Packit df99a1
using namespace DJVU;
Packit df99a1
# endif
Packit df99a1
#endif