• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kviewshell

DjVuAnno.cpp

Go to the documentation of this file.
00001 //C-  -*- C++ -*-
00002 //C- -------------------------------------------------------------------
00003 //C- DjVuLibre-3.5
00004 //C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
00005 //C- Copyright (c) 2001  AT&T
00006 //C-
00007 //C- This software is subject to, and may be distributed under, the
00008 //C- GNU General Public License, Version 2. The license should have
00009 //C- accompanied the software or you may obtain a copy of the license
00010 //C- from the Free Software Foundation at http://www.fsf.org .
00011 //C-
00012 //C- This program is distributed in the hope that it will be useful,
00013 //C- but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //C- GNU General Public License for more details.
00016 //C- 
00017 //C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library
00018 //C- distributed by Lizardtech Software.  On July 19th 2002, Lizardtech 
00019 //C- Software authorized us to replace the original DjVu(r) Reference 
00020 //C- Library notice by the following text (see doc/lizard2002.djvu):
00021 //C-
00022 //C-  ------------------------------------------------------------------
00023 //C- | DjVu (r) Reference Library (v. 3.5)
00024 //C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
00025 //C- | The DjVu Reference Library is protected by U.S. Pat. No.
00026 //C- | 6,058,214 and patents pending.
00027 //C- |
00028 //C- | This software is subject to, and may be distributed under, the
00029 //C- | GNU General Public License, Version 2. The license should have
00030 //C- | accompanied the software or you may obtain a copy of the license
00031 //C- | from the Free Software Foundation at http://www.fsf.org .
00032 //C- |
00033 //C- | The computer code originally released by LizardTech under this
00034 //C- | license and unmodified by other parties is deemed "the LIZARDTECH
00035 //C- | ORIGINAL CODE."  Subject to any third party intellectual property
00036 //C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
00037 //C- | non-exclusive license to make, use, sell, or otherwise dispose of 
00038 //C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
00039 //C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
00040 //C- | General Public License.   This grant only confers the right to 
00041 //C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
00042 //C- | the extent such infringement is reasonably necessary to enable 
00043 //C- | recipient to make, have made, practice, sell, or otherwise dispose 
00044 //C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
00045 //C- | any greater extent that may be necessary to utilize further 
00046 //C- | modifications or combinations.
00047 //C- |
00048 //C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
00049 //C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
00050 //C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
00051 //C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
00052 //C- +------------------------------------------------------------------
00053 // 
00054 // $Id: DjVuAnno.cpp,v 1.12 2004/04/17 23:56:11 leonb Exp $
00055 // $Name: release_3_5_15 $
00056 
00057 #ifdef HAVE_CONFIG_H
00058 # include "config.h"
00059 #endif
00060 #if NEED_GNUG_PRAGMAS
00061 # pragma implementation
00062 #endif
00063 
00064 #include "DjVuAnno.h"
00065 #include "GContainer.h"
00066 #include "GException.h"
00067 #include "IFFByteStream.h"
00068 #include "BSByteStream.h"
00069 #include "GMapAreas.h"
00070 
00071 #include "debug.h"
00072 
00073 #include <ctype.h>
00074 
00075 
00076 #ifdef HAVE_NAMESPACES
00077 namespace DJVU {
00078 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
00079 }
00080 #endif
00081 #endif
00082 
00083 
00084 // GLParser.h and GLParser.cpp used to be separate files capable to decode
00085 // that weird ANTa chunk format into C++ structures and lists. But since
00086 // its implementation is temporary and is used only in this file (DjVuAnno.cpp)
00087 // it appears reasonable to build it in here.
00088 
00089 //***************************************************************************
00090 //****************************** GLParser.h *********************************
00091 //***************************************************************************
00092 
00093 
00094 class GLObject : public GPEnabled
00095 {
00096 public:
00097    enum GLObjectType { INVALID=0, NUMBER=1, STRING=2, SYMBOL=3, LIST=4 };
00098    static const char * const GLObjectString[LIST+1];
00099 
00100    GLObject(int _number=0);
00101    GLObject(GLObjectType type, const char * str);
00102    GLObject(const char * name, const GPList<GLObject> & list);
00103    virtual ~GLObject(void);
00104    
00105    int      get_number(void) const;
00106    GUTF8String  get_string(void) const;
00107    GUTF8String  get_symbol(void) const;
00108    GPList<GLObject> & get_list(void);
00109    GP<GLObject> operator[](int n) const;
00110    
00111    GLObjectType get_type(void) const;
00112    GUTF8String  get_name(void) const;
00113    void     print(ByteStream & str, int compact=1, int indent=0, int * cur_pos=0) const;
00114 private:
00115    GLObjectType type;
00116    GUTF8String  name;
00117    
00118    int      number;
00119    GUTF8String  string;
00120    GUTF8String  symbol;
00121    GPList<GLObject> list;
00122    void throw_can_not_convert_to(const GLObjectType to) const;
00123 };
00124 
00125 const char * const GLObject::GLObjectString[]=
00126   {"invalid", "number", "string", "symbol", "list"};
00127 
00128 inline GLObject::GLObjectType
00129 GLObject::get_type(void) const { return type; }
00130 
00131 inline
00132 GLObject::~GLObject(void) {}
00133 
00134 class GLToken
00135 {
00136 public:
00137    enum GLTokenType { OPEN_PAR, CLOSE_PAR, OBJECT };
00138    GLTokenType  type;
00139    GP<GLObject> object;
00140    
00141    GLToken(GLTokenType type, const GP<GLObject> & object);
00142 };
00143 
00144 inline
00145 GLToken::GLToken(GLTokenType xtype, const GP<GLObject> & xobject) :
00146       type(xtype), object(xobject) {}
00147 
00148 class GLParser
00149 {
00150 public:
00151    void     parse(const char * str);
00152    GPList<GLObject> & get_list(void);
00153    GP<GLObject>     get_object(const char * name, bool last=true);
00154    void     print(ByteStream & str, int compact=1);
00155 
00156    GLParser(void);
00157    GLParser(const char * str);
00158    ~GLParser(void);
00159 private:
00160    GPList<GLObject> list;
00161 
00162    bool     compat;
00163    void     skip_white_space(const char * & start);
00164    void     check_compat(const char *str);
00165    GLToken  get_token(const char * & start);
00166    void     parse(const char * cur_name, GPList<GLObject> & list,
00167               const char * & start);
00168 };
00169 
00170 GLParser::GLParser(void) 
00171   : compat(false)
00172 {
00173 }
00174 
00175 GLParser::~GLParser(void) 
00176 {
00177 }
00178 
00179 GPList<GLObject> &
00180 GLParser::get_list(void) 
00181 { 
00182   return list; 
00183 }
00184 
00185 GLParser::GLParser(const char * str) 
00186   : compat(false)
00187 {
00188   parse(str); 
00189 }
00190 
00191 
00192 //***************************************************************************
00193 //***************************** GLParser.cpp ********************************
00194 //***************************************************************************
00195 
00196 
00197 GLObject::GLObject(int xnumber) : type(NUMBER), number(xnumber) {}
00198 
00199 GLObject::GLObject(GLObjectType xtype, const char * str) : type(xtype)
00200 {
00201    if (type!=STRING && type!=SYMBOL)
00202       G_THROW( ERR_MSG("DjVuAnno.bad_type") );
00203    if (type==STRING) 
00204       string=str;
00205    else symbol=str;
00206 }
00207 
00208 GLObject::GLObject(const char * xname, const GPList<GLObject> & xlist) :
00209       type(LIST), name(xname), list(xlist) {}
00210 
00211 void
00212 GLObject::print(ByteStream & str, int compact, int indent, int * cur_pos) const
00213 {
00214   int local_cur_pos = 0;
00215   if (!cur_pos) { cur_pos = &local_cur_pos; }
00216   
00217   GUTF8String buffer;
00218   const char * to_print=0;
00219   switch(type)
00220   {
00221   case NUMBER:
00222     to_print=buffer.format("%d",number);
00223     break;
00224   case STRING:
00225     {
00226        int length = string.length();
00227        const char *data = (const char*)string;
00228        buffer = GUTF8String("\"");
00229        while (*data && length>0) 
00230          {
00231            int span = 0;
00232            while (span<length && (unsigned char)(data[span])>=0x20 && 
00233                   data[span]!=0x7f && data[span]!='"' && data[span]!='\\' )
00234              span++;
00235            if (span > 0) 
00236              {  
00237                buffer = buffer + GUTF8String(data, span);
00238                data += span;
00239                length -= span;
00240              }  
00241            else 
00242              {
00243                char buf[8];
00244                static char *tr1 = "\"\\tnrbf";
00245                static char *tr2 = "\"\\\t\n\r\b\f";
00246                sprintf(buf,"\\%03o", (int)(((unsigned char*)data)[span]));
00247                for (int i=0; tr2[i]; i++)
00248                  if (data[span] == tr2[i])
00249                    buf[1] = tr1[i];
00250                if (buf[1]<'0' || buf[1]>'3')
00251                  buf[2] = 0;
00252                buffer = buffer + GUTF8String(buf);
00253                data += 1;
00254                length -= 1;
00255              }
00256          }
00257        buffer = buffer + GUTF8String("\"");
00258        to_print = buffer;
00259     }
00260     break;
00261   case SYMBOL:
00262     to_print=buffer.format("%s",(const char *)symbol);
00263     break;
00264   case LIST:
00265     to_print=buffer.format("(%s",(const char *)name);
00266     break;
00267   case INVALID:
00268     break;
00269   }
00270   if (!compact && *cur_pos+strlen(to_print)>70)
00271   {
00272     char ch='\n';
00273     str.write(&ch, 1);
00274     ch=' ';
00275     for(int i=0;i<indent;i++) str.write(&ch, 1);
00276     *cur_pos=indent;
00277   }
00278   str.write(to_print, strlen(to_print));
00279   char ch=' ';
00280   str.write(&ch, 1);
00281   *cur_pos+=strlen(to_print)+1;
00282   if (type==LIST)
00283   {
00284     int indent=*cur_pos-strlen(to_print);
00285     for(GPosition pos=list;pos;++pos)
00286       list[pos]->print(str, compact, indent, cur_pos);
00287     str.write(") ", 2);
00288     *cur_pos+=2;
00289   }
00290 }
00291 
00292 //  This function constructs message names for external lookup.
00293 //  The message names are constructed to avoid the problems of concatenating
00294 //  phrases (which does not translate well into other languages). The
00295 //  message names that can be generated are (listed here to appease the
00296 //  auditing program which reads comments):
00297 //    ERR_MSG("DjVuAnno.invalid2number"), ERR_MSG("DjVuAnno.string2number"),
00298 //    ERR_MSG("DjVuAnno.symbol2number"), ERR_MSG("DjVuAnno.list2number")
00299 //    ERR_MSG("DjVuAnno.invalid2string"), ERR_MSG("DjVuAnno.number2string"),
00300 //    ERR_MSG("DjVuAnno.symbol2string"), ERR_MSG("DjVuAnno.list2string")
00301 //    ERR_MSG("DjVuAnno.invalid2symbol"), ERR_MSG("DjVuAnno.number2symbol"),
00302 //    ERR_MSG("DjVuAnno.string2symbol"), ERR_MSG("DjVuAnno.list2symbol")
00303 //    ERR_MSG("DjVuAnno.invalid2list"), ERR_MSG("DjVuAnno.number2list"),
00304 //    ERR_MSG("DjVuAnno.string2list"), ERR_MSG("DjVuAnno.symbol2list")
00305 void
00306 GLObject::throw_can_not_convert_to(const GLObjectType to) const
00307 {
00308   static const GUTF8String two('2');
00309   static const GUTF8String tab('\t');
00310   GUTF8String mesg("DjVuAnno.");
00311   switch(type)
00312   {
00313     case NUMBER:
00314       mesg+=GLObjectString[NUMBER]+two+GLObjectString[to]+tab+GUTF8String(number);
00315       break;
00316     case STRING:
00317       mesg+=GLObjectString[STRING]+two+GLObjectString[to]+tab+string;
00318       break;
00319     case SYMBOL:
00320       mesg+=GLObjectString[SYMBOL]+two+GLObjectString[to]+tab+symbol;
00321       break;
00322     case LIST:
00323       mesg+=GLObjectString[LIST]+two+GLObjectString[to]+tab+name;
00324       break;
00325     default:
00326       mesg+=GLObjectString[INVALID]+two+GLObjectString[to];
00327       break;
00328   }
00329   G_THROW(mesg);
00330 }
00331 
00332 GUTF8String
00333 GLObject::get_string(void) const
00334 {
00335    if (type!=STRING)
00336    {
00337       throw_can_not_convert_to(STRING);
00338    }
00339    return string;
00340 }
00341 
00342 GUTF8String
00343 GLObject::get_symbol(void) const
00344 {
00345    if (type!=SYMBOL)
00346    {
00347       throw_can_not_convert_to(SYMBOL);
00348    }
00349    return symbol;
00350 }
00351 
00352 int
00353 GLObject::get_number(void) const
00354 {
00355    if (type!=NUMBER)
00356    {
00357       throw_can_not_convert_to(NUMBER);
00358    }
00359    return number;
00360 }
00361 
00362 GUTF8String
00363 GLObject::get_name(void) const
00364 {
00365    if (type!=LIST)
00366    {
00367       throw_can_not_convert_to(LIST);
00368    }
00369    return name;
00370 }
00371 
00372 GP<GLObject>
00373 GLObject::operator[](int n) const
00374 {
00375    if (type!=LIST)
00376    {
00377       throw_can_not_convert_to(LIST);
00378    }
00379    if (n>=list.size()) G_THROW( ERR_MSG("DjVuAnno.too_few") "\t"+name);
00380    int i;
00381    GPosition pos;
00382    for(i=0, pos=list;i<n && pos;i++, ++pos)
00383         continue;
00384    return list[pos];
00385 }
00386 
00387 GPList<GLObject> &
00388 GLObject::get_list(void)
00389 {
00390    if (type!=LIST)
00391    {
00392       throw_can_not_convert_to(LIST);
00393    }
00394    return list;
00395 }
00396 
00397 //********************************** GLParser *********************************
00398 
00399 void
00400 GLParser::skip_white_space(const char * & start)
00401 {
00402    while(*start && isspace(*start)) start++;
00403    if (!*start) 
00404        G_THROW( ByteStream::EndOfFile );
00405 }
00406 
00407 GLToken
00408 GLParser::get_token(const char * & start)
00409 {
00410    skip_white_space(start);
00411    char c = *start;
00412    if (c == '(')
00413      {
00414        start++;
00415        return GLToken(GLToken::OPEN_PAR, 0);
00416      }
00417    else if (c == ')')
00418      {
00419        start++;
00420        return GLToken(GLToken::CLOSE_PAR, 0);
00421      }
00422    else if (c=='-' || (c>='0' && c<='9'))
00423      {
00424        return GLToken(GLToken::OBJECT,
00425                       new GLObject(strtol(start, (char **) &start, 10)));
00426      }
00427    else if (c=='"')
00428      {
00429        GUTF8String str;
00430        start++;
00431        while(1)
00432      {
00433            int span = 0;
00434            while (start[span] && start[span]!='\\' && start[span]!='\"')
00435              span++;
00436            if (span > 0)
00437              {
00438                str = str + GUTF8String(start,span);
00439                start += span;
00440              }
00441            else if (start[0]=='\"')
00442              {
00443                start += 1;
00444                break;
00445              }
00446            else if (start[0]=='\\' && compat)
00447              {
00448                char c = start[1];
00449                if (c == '\"')
00450                  {
00451                    start += 2;
00452                    str += '\"';
00453                  }
00454                else
00455                  {
00456                    start += 1;
00457                    str += '\\';
00458                  }
00459              }
00460            else if (start[0]=='\\' && start[1])
00461              {
00462                char c = *++start;
00463                if (c>='0' && c<='7')
00464                  {
00465                    int x = 0;
00466                    for (int i=0; i<3 && c>='0' && c<='7'; i++) 
00467                      {
00468                        x = x * 8 + c - '0';
00469                        c = *++start;
00470                      }
00471                    str += (char)(x & 0xff);
00472                  }
00473                else
00474                  {
00475                    static char *tr1 = "tnrbfva";
00476                    static char *tr2 = "\t\n\r\b\f\013\007";
00477                    for (int i=0; tr1[i]; i++)
00478                      if (c == tr1[i])
00479                        c = tr2[i];
00480                    start += 1;
00481                    str += c;
00482                  }
00483              }
00484            else 
00485              {
00486                G_THROW( ByteStream::EndOfFile );
00487              }
00488          }
00489        return GLToken(GLToken::OBJECT, 
00490                       new GLObject(GLObject::STRING, str));
00491      }
00492    else
00493      {
00494        GUTF8String str;
00495        while(1)
00496      {
00497            char ch=*start++;
00498            if (!ch)
00499              G_THROW( ByteStream::EndOfFile );
00500            if (ch==')') { start--; break; }
00501            if (isspace(ch)) break;
00502            str+=ch;
00503      }
00504        return GLToken(GLToken::OBJECT, new GLObject(GLObject::SYMBOL, str));
00505      }
00506 } 
00507 
00508 void
00509 GLParser::parse(const char * cur_name, GPList<GLObject> & list,
00510         const char * & start)
00511 {
00512   DEBUG_MSG("GLParse::parse(): Parsing contents of object '" << cur_name << "'\n");
00513   DEBUG_MAKE_INDENT(3);
00514   
00515   while(1)
00516   {
00517     GLToken token=get_token(start);
00518     if (token.type==GLToken::OPEN_PAR)
00519     {
00520       if (isspace(*start))
00521       {
00522         GUTF8String mesg=GUTF8String( ERR_MSG("DjVuAnno.paren") "\t")+cur_name;
00523         G_THROW(mesg);
00524       }
00525       
00526       GLToken tok=get_token(start);
00527       GP<GLObject> object=tok.object;   // This object should be SYMBOL
00528       // We will convert it to LIST later
00529       if (tok.type!=GLToken::OBJECT || object->get_type()!=GLObject::SYMBOL)
00530       {
00531         if (tok.type==GLToken::OPEN_PAR ||
00532           tok.type==GLToken::CLOSE_PAR)
00533         {
00534           GUTF8String mesg=GUTF8String( ERR_MSG("DjVuAnno.no_paren") "\t")+cur_name;
00535           G_THROW(mesg);
00536         }
00537         if (tok.type==GLToken::OBJECT)
00538         {
00539           GLObject::GLObjectType type=object->get_type();
00540           if (type==GLObject::NUMBER)
00541           {
00542             GUTF8String mesg( ERR_MSG("DjVuAnno.no_number") "\t");
00543             mesg += cur_name;
00544             G_THROW(mesg);
00545           }
00546           else if (type==GLObject::STRING)
00547           {
00548             GUTF8String mesg( ERR_MSG("DjVuAnno.no_string") "\t");
00549             mesg += cur_name;
00550             G_THROW(mesg);
00551           }
00552         }
00553       }
00554       
00555       // OK. Get the object contents
00556       GPList<GLObject> new_list;
00557       G_TRY
00558       {
00559         parse(object->get_symbol(), new_list, start);
00560       } 
00561       G_CATCH(exc)
00562       {
00563         if (exc.cmp_cause(ByteStream::EndOfFile))
00564           G_RETHROW;
00565       } 
00566       G_ENDCATCH;
00567       list.append(new GLObject(object->get_symbol(), new_list));
00568       continue;
00569     }
00570     if (token.type==GLToken::CLOSE_PAR) 
00571       return;
00572     list.append(token.object);
00573   }
00574 }
00575 
00576 void 
00577 GLParser::check_compat(const char *s)
00578 {
00579   int state = 0;
00580   while (s && *s && !compat)
00581     {
00582       switch(state)
00583         {
00584         case 0:
00585           if (*s == '\"')
00586             state = '\"';
00587           break;
00588         case '\"':
00589           if (*s == '\"')
00590             state = 0;
00591           else if (*s == '\\')
00592             state = '\\';
00593           else if ((unsigned char)(*s)<0x20 || *s==0x7f)
00594             compat = true;
00595           break;
00596         case '\\':
00597           if (!strchr("01234567tnrbfva\"\\",*s))
00598             compat = true;
00599           state = '\"';
00600           break;
00601         }
00602       s += 1;
00603     }
00604 }
00605 
00606 void
00607 GLParser::parse(const char * str)
00608 {
00609    DEBUG_MSG("GLParser::parse(): parsing string contents\n");
00610    DEBUG_MAKE_INDENT(3);
00611    
00612    G_TRY
00613    {
00614       check_compat(str);
00615       parse("toplevel", list, str);
00616    } G_CATCH(exc)
00617    {
00618       if (exc.cmp_cause(ByteStream::EndOfFile))
00619         G_RETHROW;
00620    } G_ENDCATCH;
00621 }
00622 
00623 void
00624 GLParser::print(ByteStream & str, int compact)
00625 {
00626    for(GPosition pos=list;pos;++pos)
00627       list[pos]->print(str, compact);
00628 }
00629 
00630 GP<GLObject>
00631 GLParser::get_object(const char * name, bool last)
00632 {
00633    GP<GLObject> object;
00634    for(GPosition pos=list;pos;++pos)
00635    {
00636       GP<GLObject> obj=list[pos];
00637       if (obj->get_type()==GLObject::LIST &&
00638       obj->get_name()==name)
00639       {
00640      object=obj;
00641      if (!last) break;
00642       }
00643    }
00644    return object;
00645 }
00646 
00647 //***************************************************************************
00648 //********************************** ANT ************************************
00649 //***************************************************************************
00650 
00651 static const char *zoom_strings[]={
00652   "default","page","width","one2one","stretch"};
00653 static const int zoom_strings_size=sizeof(zoom_strings)/sizeof(const char *);
00654 
00655 static const char *mode_strings[]={
00656   "default","color","fore","back","bw"};
00657 static const int mode_strings_size=sizeof(mode_strings)/sizeof(const char *);
00658 
00659 static const char *align_strings[]={
00660   "default","left","center","right","top","bottom"};
00661 static const int align_strings_size=sizeof(align_strings)/sizeof(const char *);
00662 
00663 #define PNOTE_TAG   "pnote"
00664 #define BACKGROUND_TAG  "background"
00665 #define ZOOM_TAG    "zoom"
00666 #define MODE_TAG    "mode"
00667 #define ALIGN_TAG   "align"
00668 #define HALIGN_TAG  "halign"
00669 #define VALIGN_TAG  "valign"
00670 #define METADATA_TAG    "metadata"
00671 
00672 static const unsigned long default_bg_color=0xffffffff;
00673 
00674 DjVuANT::DjVuANT(void)
00675 {
00676    bg_color=default_bg_color;
00677    zoom=0;
00678    mode=MODE_UNSPEC;
00679    hor_align=ver_align=ALIGN_UNSPEC;
00680 }
00681 
00682 DjVuANT::~DjVuANT()
00683 {
00684 }
00685 
00686 GUTF8String
00687 DjVuANT::get_paramtags(void) const
00688 {
00689   GUTF8String retval;
00690   if(zoom > 0)
00691   {
00692     retval+="<PARAM name=\"" ZOOM_TAG "\" value=\""+GUTF8String(zoom)+="\" />\n";
00693   }else if(zoom && ((-zoom)<zoom_strings_size))
00694   {
00695     retval+="<PARAM name=\"" ZOOM_TAG "\" value=\""+GUTF8String(zoom_strings[-zoom])+"\" />\n";
00696   }
00697   if((mode>0)&&(mode<mode_strings_size))
00698   {
00699     retval+="<PARAM name=\"" MODE_TAG "\" value=\""+GUTF8String(mode_strings[mode])+"\" />\n";
00700   }
00701   if((hor_align>ALIGN_UNSPEC)&&(hor_align<align_strings_size))
00702   {
00703     retval+="<PARAM name=\"" HALIGN_TAG "\" value=\""+GUTF8String(align_strings[hor_align])+"\" />\n";
00704   }
00705   if((ver_align>ALIGN_UNSPEC)&&(ver_align<align_strings_size))
00706   {
00707     retval+="<PARAM name=\"" VALIGN_TAG "\" value=\""+GUTF8String(align_strings[ver_align])+"\" />\n";
00708   }
00709   if((bg_color&0xffffff) == bg_color)
00710   {
00711     retval+="<PARAM name=\"" BACKGROUND_TAG "\" value=\""+GUTF8String().format("#%06lX",bg_color)+"\" />\n";
00712   }
00713   return retval;
00714 }
00715 
00716 void
00717 DjVuANT::writeParam(ByteStream &str_out) const
00718 {
00719   str_out.writestring(get_paramtags());
00720 }
00721 
00722 GUTF8String
00723 DjVuANT::get_xmlmap(const GUTF8String &name,const int height) const
00724 {
00725   GUTF8String retval("<MAP name=\""+name.toEscaped()+"\" >\n");
00726   for(GPosition pos(map_areas);pos;++pos)
00727   {
00728     retval+=map_areas[pos]->get_xmltag(height);
00729   }
00730   return retval+"</MAP>\n";
00731 }
00732 
00733 void
00734 DjVuANT::writeMap(
00735   ByteStream &str_out,const GUTF8String &name,const int height) const
00736 {
00737   str_out.writestring("<MAP name=\""+name.toEscaped()+"\" >\n");
00738   for(GPosition pos(map_areas);pos;++pos)
00739   {
00740     str_out.writestring(GUTF8String(map_areas[pos]->get_xmltag(height)));
00741   }
00742   str_out.writestring(GUTF8String("</MAP>\n"));
00743 }
00744 
00745 GUTF8String
00746 DjVuANT::read_raw(ByteStream & str)
00747 {
00748    GUTF8String raw;
00749    char buffer[1024];
00750    int length;
00751    while((length=str.read(buffer, 1024)))
00752       raw+=GUTF8String(buffer, length);
00753    return raw;
00754 }
00755 
00756 void
00757 DjVuANT::decode(class GLParser & parser)
00758 {
00759    bg_color=get_bg_color(parser);
00760    zoom=get_zoom(parser);
00761    mode=get_mode(parser);
00762    hor_align=get_hor_align(parser);
00763    ver_align=get_ver_align(parser);
00764    map_areas=get_map_areas(parser);
00765 #ifndef NO_METADATA_IN_ANT_CHUNK
00766    metadata=get_metadata(parser); 
00767 #endif
00768 }
00769 
00770 
00771 void 
00772 DjVuANT::decode(ByteStream & str)
00773 {
00774    GLParser parser(read_raw(str));
00775    decode(parser);
00776 }
00777 
00778 void
00779 DjVuANT::merge(ByteStream & str)
00780 {
00781    GLParser parser(encode_raw());
00782    GUTF8String add_raw=read_raw(str);
00783    parser.parse(add_raw);
00784    decode(parser);
00785 }
00786 
00787 void
00788 DjVuANT::encode(ByteStream &bs)
00789 {
00790   GUTF8String raw=encode_raw();
00791   bs.writall((const char*) raw, raw.length());
00792 }
00793 
00794 unsigned int 
00795 DjVuANT::get_memory_usage() const
00796 {
00797   return sizeof(DjVuANT);
00798 }
00799 
00800 unsigned char
00801 DjVuANT::decode_comp(char ch1, char ch2)
00802 {
00803    unsigned char dig1=0;
00804    if (ch1)
00805    {
00806       ch1=toupper(ch1);
00807       if (ch1>='0' && ch1<='9') dig1=ch1-'0';
00808       if (ch1>='A' && ch1<='F') dig1=10+ch1-'A';
00809       
00810       unsigned char dig2=0;
00811       if (ch2)
00812       {
00813      ch2=toupper(ch2);
00814      if (ch2>='0' && ch2<='9') dig2=ch2-'0';
00815      if (ch2>='A' && ch2<='F') dig2=10+ch2-'A';
00816      return (dig1 << 4) | dig2;
00817       }
00818       return dig1;
00819    }
00820    return 0;
00821 }
00822 
00823 unsigned long int
00824 DjVuANT::cvt_color(const char * color, unsigned long int def)
00825 {
00826    if (color[0]!='#') return def;
00827 
00828    unsigned long int color_rgb=0;
00829    color++;
00830    const char * start, * end;
00831    
00832       // Do blue
00833    end=color+strlen(color); start=end-2;
00834    if (start<color) start=color;
00835    if (end>start)
00836       color_rgb|=decode_comp(start[0], start+1<end ? start[1] : 0);
00837    
00838       // Do green
00839    end=color+strlen(color)-2; start=end-2;
00840    if (start<color) start=color;
00841    if (end>start)
00842       color_rgb|=decode_comp(start[0], start+1<end ? start[1] : 0) << 8;
00843    
00844       // Do red
00845    end=color+strlen(color)-4; start=end-2;
00846    if (start<color) start=color;
00847    if (end>start)
00848       color_rgb|=decode_comp(start[0], start+1<end ? start[1] : 0) << 16;
00849 
00850       // Do the fourth byte
00851    end=color+strlen(color)-6; start=end-2;
00852    if (start<color) start=color;
00853    if (end>start)
00854       color_rgb|=decode_comp(start[0], start+1<end ? start[1] : 0) << 24;
00855    
00856    return color_rgb;
00857 }
00858 
00859 unsigned long int
00860 DjVuANT::get_bg_color(GLParser & parser)
00861 {
00862   unsigned long retval=default_bg_color;
00863   DEBUG_MSG("DjVuANT::get_bg_color(): getting background color ...\n");
00864   DEBUG_MAKE_INDENT(3);
00865   G_TRY
00866   {
00867     GP<GLObject> obj=parser.get_object(BACKGROUND_TAG);
00868     if (obj && obj->get_list().size()==1)
00869     {
00870       GUTF8String color=(*obj)[0]->get_symbol();
00871       DEBUG_MSG("color='" << color << "'\n");
00872       retval=cvt_color(color, 0xffffff);
00873     }
00874 #ifndef NDEBUG
00875     if(retval == default_bg_color)
00876     {
00877       DEBUG_MSG("can't find any.\n");
00878     }
00879 #endif // NDEBUG
00880   } G_CATCH_ALL {} G_ENDCATCH;
00881 #ifndef NDEBUG
00882   if(retval == default_bg_color)
00883   {
00884     DEBUG_MSG("resetting color to 0xffffffff (UNSPEC)\n");
00885   }
00886 #endif // NDEBUG
00887   return retval;
00888 }
00889 
00890 int
00891 DjVuANT::get_zoom(GLParser & parser)
00892       // Returns:
00893       //   <0 - special zoom (like ZOOM_STRETCH)
00894       //   =0 - not set
00895       //   >0 - numeric zoom (%%)
00896 {
00897   int retval=ZOOM_UNSPEC;
00898   DEBUG_MSG("DjVuANT::get_zoom(): getting zoom factor ...\n");
00899   DEBUG_MAKE_INDENT(3);
00900   G_TRY
00901   {
00902     GP<GLObject> obj=parser.get_object(ZOOM_TAG);
00903     if (obj && obj->get_list().size()==1)
00904     {
00905       const GUTF8String zoom((*obj)[0]->get_symbol());
00906       DEBUG_MSG("zoom='" << zoom << "'\n");
00907      
00908       for(int i=0;(i<zoom_strings_size);++i)
00909       {
00910         if(zoom == zoom_strings[i])
00911         {
00912           retval=(-i);
00913           break;
00914         }
00915       }
00916       if(retval == ZOOM_UNSPEC)
00917       {
00918         if (zoom[0]!='d')
00919         {
00920           G_THROW( ERR_MSG("DjVuAnno.bad_zoom") );
00921         }else
00922         {
00923           retval=zoom.substr(1, zoom.length()).toInt(); //atoi((const char *) zoom+1);
00924         }
00925       }
00926     }
00927 #ifndef NDEBUG
00928     if(retval == ZOOM_UNSPEC)
00929     {
00930       DEBUG_MSG("can't find any.\n");
00931     }
00932 #endif // NDEBUG
00933   } G_CATCH_ALL {} G_ENDCATCH;
00934 #ifndef NDEBUG
00935   if(retval == ZOOM_UNSPEC)
00936   {
00937     DEBUG_MSG("resetting zoom to 0 (UNSPEC)\n");
00938   }
00939 #endif // NDEBUG
00940   return retval;
00941 }
00942 
00943 int
00944 DjVuANT::get_mode(GLParser & parser)
00945 {
00946   int retval=MODE_UNSPEC;
00947   DEBUG_MSG("DjVuAnt::get_mode(): getting default mode ...\n");
00948   DEBUG_MAKE_INDENT(3);
00949   G_TRY
00950   {
00951     GP<GLObject> obj=parser.get_object(MODE_TAG);
00952     if (obj && obj->get_list().size()==1)
00953     {
00954       const GUTF8String mode((*obj)[0]->get_symbol());
00955       DEBUG_MSG("mode='" << mode << "'\n");
00956       for(int i=0;(i<mode_strings_size);++i)
00957       {
00958         if(mode == mode_strings[i])
00959         {
00960           retval=i;
00961           break;
00962         }
00963       }
00964     }
00965 #ifndef NDEBUG
00966     if(retval == MODE_UNSPEC)
00967     {
00968       DEBUG_MSG("can't find any.\n");
00969     }
00970 #endif // NDEBUG
00971   } G_CATCH_ALL {} G_ENDCATCH;
00972 #ifndef NDEBUG
00973   if(retval == MODE_UNSPEC)
00974   {
00975     DEBUG_MSG("resetting mode to MODE_UNSPEC\n");
00976   }
00977 #endif // NDEBUG
00978   return retval;
00979 }
00980 
00981 static inline DjVuANT::alignment
00982 legal_halign(const int i)
00983 {
00984   DjVuANT::alignment retval;
00985   switch((DjVuANT::alignment)i)
00986   {
00987   case DjVuANT::ALIGN_LEFT:
00988   case DjVuANT::ALIGN_CENTER:
00989   case DjVuANT::ALIGN_RIGHT:
00990     retval=(DjVuANT::alignment)i;
00991     break;
00992   default:
00993     retval=DjVuANT::ALIGN_UNSPEC;
00994     break;
00995   }
00996   return retval;
00997 }
00998 
00999 static inline DjVuANT::alignment
01000 legal_valign(const int i)
01001 {
01002   DjVuANT::alignment retval;
01003   switch((DjVuANT::alignment)i)
01004   {
01005   case DjVuANT::ALIGN_CENTER:
01006   case DjVuANT::ALIGN_TOP:
01007   case DjVuANT::ALIGN_BOTTOM:
01008     retval=(DjVuANT::alignment)i;
01009     break;
01010   default:
01011     retval=DjVuANT::ALIGN_UNSPEC;
01012     break;
01013   }
01014   return retval;
01015 }
01016 
01017 DjVuANT::alignment
01018 DjVuANT::get_hor_align(GLParser & parser)
01019 {
01020   DEBUG_MSG("DjVuAnt::get_hor_align(): getting hor page alignemnt ...\n");
01021   DEBUG_MAKE_INDENT(3);
01022   alignment retval=ALIGN_UNSPEC;
01023   G_TRY
01024   {
01025     GP<GLObject> obj=parser.get_object(ALIGN_TAG);
01026     if (obj && obj->get_list().size()==2)
01027     {
01028       const GUTF8String align((*obj)[0]->get_symbol());
01029       DEBUG_MSG("hor_align='" << align << "'\n");
01030       
01031       for(int i=(int)ALIGN_UNSPEC;(i<align_strings_size);++i)
01032       {
01033         const alignment j=legal_halign(i);
01034         if((i == (int)j)&&(align == align_strings[i]))
01035         {
01036           retval=j;
01037           break;
01038         }
01039       }
01040     }
01041 #ifndef NDEBUG
01042     if(retval == ALIGN_UNSPEC)
01043     {
01044       DEBUG_MSG("can't find any.\n");
01045     }
01046 #endif // NDEBUG
01047   } G_CATCH_ALL {} G_ENDCATCH;
01048 #ifndef NDEBUG
01049   if(retval == ALIGN_UNSPEC)
01050   {
01051     DEBUG_MSG("resetting alignment to ALIGN_UNSPEC\n");
01052   }
01053 #endif // NDEBUG
01054   return retval;
01055 }
01056 
01057 DjVuANT::alignment
01058 DjVuANT::get_ver_align(GLParser & parser)
01059 {
01060   DEBUG_MSG("DjVuAnt::get_ver_align(): getting vert page alignemnt ...\n");
01061   DEBUG_MAKE_INDENT(3);
01062   alignment retval=ALIGN_UNSPEC;
01063   G_TRY
01064   {
01065     GP<GLObject> obj=parser.get_object(ALIGN_TAG);
01066     if (obj && obj->get_list().size()==2)
01067     {
01068       const GUTF8String align((*obj)[1]->get_symbol());
01069       DEBUG_MSG("ver_align='" << align << "'\n");
01070       for(int i=(int)ALIGN_UNSPEC;(i<align_strings_size);++i)
01071       {
01072         const alignment j=legal_valign(i);
01073         if((i == (int)j)&&(align == align_strings[i]))
01074         {
01075           retval=j;
01076           break;
01077         }
01078       }
01079     }
01080 #ifndef NDEBUG
01081     if(retval == ALIGN_UNSPEC)
01082     {
01083       DEBUG_MSG("can't find any.\n");
01084     }
01085 #endif // NDEBUG
01086   } G_CATCH_ALL {} G_ENDCATCH;
01087 #ifndef NDEBUG
01088   if(retval == ALIGN_UNSPEC)
01089   {
01090     DEBUG_MSG("resetting alignment to ALIGN_UNSPEC\n");
01091   }
01092 #endif // NDEBUG
01093   return retval;
01094 }
01095 
01096 #ifndef NO_METADATA_IN_ANT_CHUNK
01097 GMap<GUTF8String, GUTF8String>
01098 DjVuANT::get_metadata(GLParser & parser)
01099 {
01100   DEBUG_MSG("DjVuANT::get_map_areas(): forming and returning back list of map areas\n");
01101   DEBUG_MAKE_INDENT(3);
01102   
01103   GMap<GUTF8String, GUTF8String> mdata;
01104   
01105   GPList<GLObject> list=parser.get_list();
01106   for(GPosition pos=list;pos;++pos)
01107     {
01108       GLObject & obj=*list[pos];
01109       if (obj.get_type()==GLObject::LIST && obj.get_name()==METADATA_TAG)  
01110         { 
01111           G_TRY 
01112             {
01113               for(int obj_num=0;obj_num<obj.get_list().size();obj_num++)
01114                 {
01115                   GLObject & el=*obj[obj_num];
01116                   const int type = el.get_type();
01117                   if (type == GLObject::LIST)
01118                     { 
01119                       const GUTF8String & name=el.get_name();  
01120                       mdata[name]=(el[0])->get_string();
01121                     }
01122                 }
01123             } 
01124           G_CATCH_ALL { } G_ENDCATCH;
01125         }
01126     }
01127   return mdata;
01128 }
01129 #endif
01130 
01131 GPList<GMapArea>
01132 DjVuANT::get_map_areas(GLParser & parser)
01133 {
01134   DEBUG_MSG("DjVuANT::get_map_areas(): forming and returning back list of map areas\n");
01135   DEBUG_MAKE_INDENT(3);
01136   
01137   GPList<GMapArea> map_areas;
01138   
01139   GPList<GLObject> list=parser.get_list();
01140 
01141   for(GPosition pos=list;pos;++pos)
01142   {
01143     GLObject & obj=*list[pos];
01144     const int type=obj.get_type();
01145     if (type == GLObject::LIST)
01146     {
01147       const GUTF8String name=obj.get_name();
01148       if(name == GMapArea::MAPAREA_TAG)
01149       {
01150         G_TRY {
01151            // Getting the url
01152           GUTF8String url;
01153           GUTF8String target=GMapArea::TARGET_SELF;
01154           GLObject & url_obj=*(obj[0]);
01155           if (url_obj.get_type()==GLObject::LIST)
01156           {
01157             if (url_obj.get_name()!=GMapArea::URL_TAG)
01158               G_THROW( ERR_MSG("DjVuAnno.bad_url") );
01159             url=(url_obj[0])->get_string();
01160             target=(url_obj[1])->get_string();
01161           } else url=url_obj.get_string();
01162         
01163            // Getting the comment
01164           GUTF8String comment=(obj[1])->get_string();
01165         
01166           DEBUG_MSG("found maparea '" << comment << "' (" <<
01167             url << ":" << target << ")\n");
01168         
01169           GLObject * shape=obj[2];
01170           GP<GMapArea> map_area;
01171           if (shape->get_type()==GLObject::LIST)
01172           {
01173             if (shape->get_name()==GMapArea::RECT_TAG)
01174             {
01175               DEBUG_MSG("it's a rectangle.\n");
01176               GRect grect((*shape)[0]->get_number(),
01177                           (*shape)[1]->get_number(),
01178                           (*shape)[2]->get_number(),
01179                           (*shape)[3]->get_number());
01180               GP<GMapRect> map_rect=GMapRect::create(grect);
01181               map_area=(GMapRect *)map_rect;
01182             } else if (shape->get_name()==GMapArea::POLY_TAG)
01183             {
01184               DEBUG_MSG("it's a polygon.\n");
01185               int points=shape->get_list().size()/2;
01186               GTArray<int> xx(points-1), yy(points-1);
01187               for(int i=0;i<points;i++)
01188               {
01189                 xx[i]=(*shape)[2*i]->get_number();
01190                 yy[i]=(*shape)[2*i+1]->get_number();
01191               }
01192               GP<GMapPoly> map_poly=GMapPoly::create(xx,yy,points);
01193               map_area=(GMapPoly *)map_poly;
01194             } else if (shape->get_name()==GMapArea::OVAL_TAG)
01195             {
01196               DEBUG_MSG("it's an ellipse.\n");
01197               GRect grect((*shape)[0]->get_number(),
01198                           (*shape)[1]->get_number(),
01199                           (*shape)[2]->get_number(),
01200                           (*shape)[3]->get_number());
01201               GP<GMapOval> map_oval=GMapOval::create(grect);
01202               map_area=(GMapOval *)map_oval;
01203             }
01204           }
01205         
01206           if (map_area)
01207           {
01208             map_area->url=url;
01209             map_area->target=target;
01210             map_area->comment=comment;
01211             for(int obj_num=3;obj_num<obj.get_list().size();obj_num++)
01212             {
01213               GLObject * el=obj[obj_num];
01214               if (el->get_type()==GLObject::LIST)
01215               {
01216                 const GUTF8String & name=el->get_name();
01217                 if (name==GMapArea::BORDER_AVIS_TAG)
01218                   map_area->border_always_visible=true;
01219                 else if (name==GMapArea::HILITE_TAG)
01220                 {
01221                   GLObject * obj=el->get_list()[el->get_list().firstpos()];
01222                   if (obj->get_type()==GLObject::SYMBOL)
01223                     map_area->hilite_color=cvt_color(obj->get_symbol(), 0xff);
01224                 } else
01225                 {
01226                   int border_type=
01227                     name==GMapArea::NO_BORDER_TAG ? GMapArea::NO_BORDER :
01228                     name==GMapArea::XOR_BORDER_TAG ? GMapArea::XOR_BORDER :
01229                     name==GMapArea::SOLID_BORDER_TAG ? GMapArea::SOLID_BORDER :
01230                     name==GMapArea::SHADOW_IN_BORDER_TAG ? GMapArea::SHADOW_IN_BORDER :
01231                     name==GMapArea::SHADOW_OUT_BORDER_TAG ? GMapArea::SHADOW_OUT_BORDER :
01232                     name==GMapArea::SHADOW_EIN_BORDER_TAG ? GMapArea::SHADOW_EIN_BORDER :
01233                     name==GMapArea::SHADOW_EOUT_BORDER_TAG ? GMapArea::SHADOW_EOUT_BORDER : -1;
01234                   if (border_type>=0)
01235                   {
01236                     map_area->border_type=(GMapArea::BorderType) border_type;
01237                     for(GPosition pos=el->get_list();pos;++pos)
01238                     {
01239                       GLObject * obj=el->get_list()[pos];
01240                       if (obj->get_type()==GLObject::SYMBOL)
01241                         map_area->border_color=cvt_color(obj->get_symbol(), 0xff);
01242                       if (obj->get_type()==GLObject::NUMBER)
01243                         map_area->border_width=obj->get_number();
01244                     }
01245                   }
01246                 }       
01247               } // if (el->get_type()==...)
01248             } // for(int obj_num=...)
01249             map_areas.append(map_area);
01250           } // if (map_area) ...
01251         } G_CATCH_ALL {} G_ENDCATCH;
01252       }
01253     }
01254   } // while(item==...)
01255    
01256   DEBUG_MSG("map area list size = " << list.size() << "\n");
01257   
01258   return map_areas;
01259 }
01260 
01261 void
01262 DjVuANT::del_all_items(const char * name, GLParser & parser)
01263 {
01264    GPList<GLObject> & list=parser.get_list();
01265    GPosition pos=list;
01266    while(pos)
01267    {
01268       GLObject & obj=*list[pos];
01269       if (obj.get_type()==GLObject::LIST &&
01270       obj.get_name()==name)
01271       {
01272      GPosition this_pos=pos;
01273      ++pos;
01274      list.del(this_pos);
01275       } else ++pos;
01276    }
01277 }
01278 
01279 GUTF8String
01280 DjVuANT::encode_raw(void) const
01281 {
01282    GUTF8String buffer;
01283    GLParser parser;
01284 
01285       //*** Background color
01286    del_all_items(BACKGROUND_TAG, parser);
01287    if (bg_color!=default_bg_color)
01288    {
01289       buffer.format("(" BACKGROUND_TAG " #%02X%02X%02X)",
01290           (unsigned int)((bg_color & 0xff0000) >> 16),
01291           (unsigned int)((bg_color & 0xff00) >> 8),
01292           (unsigned int)(bg_color & 0xff));
01293       parser.parse(buffer);
01294    }
01295 
01296       //*** Zoom
01297    del_all_items(ZOOM_TAG, parser);
01298    if (zoom!=ZOOM_UNSPEC)
01299    {
01300       buffer="(" ZOOM_TAG " ";
01301       const int i=1-zoom;
01302       if((i>=0)&& (i<zoom_strings_size))
01303       {
01304         buffer+=zoom_strings[i];
01305       }else
01306       {
01307         buffer+="d"+GUTF8String(zoom);
01308       }
01309       buffer+=")";
01310       parser.parse(buffer);
01311    }
01312 
01313       //*** Mode
01314    del_all_items(MODE_TAG, parser);
01315    if (mode!=MODE_UNSPEC)
01316    {
01317       const int i=mode-1;
01318       if((i>=0)&& (i<mode_strings_size))
01319       { 
01320         buffer="(" MODE_TAG " " + GUTF8String(mode_strings[mode]) + ")";
01321       }
01322       parser.parse(buffer);
01323    }
01324 
01325       //*** Alignment
01326    del_all_items(ALIGN_TAG, parser);
01327    if (hor_align!=ALIGN_UNSPEC || ver_align!=ALIGN_UNSPEC)
01328    {
01329       buffer= GUTF8String("(" ALIGN_TAG " ")
01330         +align_strings[((hor_align<ALIGN_UNSPEC)||
01331                         (hor_align>=align_strings_size))?ALIGN_UNSPEC:hor_align]
01332         +" "+align_strings[((ver_align<ALIGN_UNSPEC)||
01333                             (ver_align>=align_strings_size))?ALIGN_UNSPEC:ver_align]+")";
01334       parser.parse(buffer);
01335    }
01336       //*** Metadata
01337 #ifndef NO_METADATA_IN_ANT_CHUNK
01338    del_all_items(METADATA_TAG, parser);
01339    if (!metadata.isempty())
01340      {
01341        GUTF8String mdatabuffer("(");
01342        mdatabuffer +=  METADATA_TAG ;
01343        for (GPosition pos=metadata; pos; ++pos)
01344          mdatabuffer +=" (" + metadata.key(pos)+" \""+metadata[pos]+"\")";
01345        mdatabuffer += " )";
01346        parser.parse(mdatabuffer);
01347      }
01348 #endif   
01349      //*** Mapareas
01350    del_all_items(GMapArea::MAPAREA_TAG, parser);
01351    for(GPosition pos=map_areas;pos;++pos)
01352       parser.parse(map_areas[pos]->print());
01353 
01354    GP<ByteStream> gstr=ByteStream::create();
01355    ByteStream &str=*gstr;
01356    parser.print(str, 1);
01357    GUTF8String ans;
01358    int size = str.size();
01359    str.seek(0);
01360    str.read(ans.getbuf(size), size);
01361    return ans;
01362 }
01363 
01364 bool
01365 DjVuANT::is_empty(void) const
01366 {
01367    GUTF8String raw=encode_raw();
01368    for(int i=raw.length()-1;i>=0;i--)
01369       if (isspace(raw[i])) raw.setat(i, 0);
01370       else break;
01371    return raw.length()==0;
01372 }
01373 
01374 GP<DjVuANT>
01375 DjVuANT::copy(void) const
01376 {
01377    GP<DjVuANT> ant=new DjVuANT(*this);
01378 
01379 
01380       // Now process the list of hyperlinks.
01381    ant->map_areas.empty();
01382    for(GPosition pos=map_areas;pos;++pos)
01383       ant->map_areas.append(map_areas[pos]->get_copy());
01384 
01385    return ant;
01386 }
01387 
01388 //***************************************************************************
01389 //******************************** DjVuAnno *********************************
01390 //***************************************************************************
01391 
01392 GUTF8String
01393 DjVuAnno::get_xmlmap(const GUTF8String &name,const int height) const
01394 {
01395   return ant
01396     ?(ant->get_xmlmap(name,height))
01397     :("<MAP name=\""+name.toEscaped()+"\"/>\n");
01398 }
01399 
01400 void
01401 DjVuAnno::writeMap(ByteStream &str_out,const GUTF8String &name,const int height) const
01402 {
01403   if(ant)
01404   {
01405     ant->writeMap(str_out,name,height);
01406   }else
01407   {
01408     str_out.writestring(get_xmlmap(name,height));
01409   }
01410 }
01411 
01412 GUTF8String
01413 DjVuAnno::get_paramtags(void) const
01414 {
01415   return ant
01416     ?(ant->get_paramtags())
01417     :GUTF8String();
01418 }
01419 
01420 void
01421 DjVuAnno::writeParam(ByteStream &str_out) const
01422 {
01423   str_out.writestring(get_paramtags());
01424 }
01425 
01426 
01427 void
01428 DjVuAnno::decode(const GP<ByteStream> &gbs)
01429 {
01430   GUTF8String chkid;
01431   GP<IFFByteStream> giff=IFFByteStream::create(gbs);
01432   IFFByteStream &iff=*giff;
01433   while( iff.get_chunk(chkid) )
01434   {
01435     if (chkid == "ANTa")
01436     {
01437       if (ant) {
01438         ant->merge(*iff.get_bytestream());
01439       } else {
01440         ant=DjVuANT::create();
01441         ant->decode(*iff.get_bytestream());
01442       }
01443     }
01444     else if (chkid == "ANTz")
01445     {
01446       GP<ByteStream> gbsiff=BSByteStream::create(giff->get_bytestream());
01447       if (ant) {
01448         ant->merge(*gbsiff);
01449       } else {
01450         ant=DjVuANT::create();
01451         ant->decode(*gbsiff);
01452       }
01453     }
01454     // Add decoding of other chunks here
01455     iff.close_chunk();
01456   }
01457 }
01458 
01459 void
01460 DjVuAnno::encode(const GP<ByteStream> &gbs)
01461 {
01462   GP<IFFByteStream> giff=IFFByteStream::create(gbs);
01463   IFFByteStream &iff=*giff;
01464   if (ant)
01465     {
01466 #if 0
01467       iff.put_chunk("ANTa");
01468       ant->encode(iff);
01469       iff.close_chunk();
01470 #else
01471       iff.put_chunk("ANTz");
01472       {
01473 //   GP<ByteStream> bsbinput = giff.get_bytestream();
01474      GP<ByteStream> bsb = BSByteStream::create(giff->get_bytestream(), 50);
01475      ant->encode(*bsb);
01476       }
01477       iff.close_chunk();
01478 #endif
01479     }
01480   // Add encoding of other chunks here
01481 }
01482 
01483 
01484 GP<DjVuAnno>
01485 DjVuAnno::copy(void) const
01486 {
01487    GP<DjVuAnno> anno= new DjVuAnno;
01488       // Copy any primitives (if any)
01489    *anno=*this;
01490       // Copy each substructure
01491    if (ant) anno->ant = ant->copy();
01492    return anno;
01493 }
01494 
01495 void
01496 DjVuAnno::merge(const GP<DjVuAnno> & anno)
01497 {
01498    if (anno)
01499    {
01500       GP<ByteStream> gstr=ByteStream::create();
01501       encode(gstr);
01502       anno->encode(gstr);
01503       gstr->seek(0);
01504       decode(gstr);
01505    }
01506 }
01507 
01508 
01509 #ifdef HAVE_NAMESPACES
01510 }
01511 # ifndef NOT_USING_DJVU_NAMESPACE
01512 using namespace DJVU;
01513 # endif
01514 #endif

kviewshell

Skip menu "kviewshell"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • kviewshell
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal