From 47d455dd55be855e4cc691c32f687f723d9247ee Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegraphics@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kviewshell/plugins/djvu/libdjvu/DjVuAnno.cpp | 1514 ++++++++++++++++++++++++++ 1 file changed, 1514 insertions(+) create mode 100644 kviewshell/plugins/djvu/libdjvu/DjVuAnno.cpp (limited to 'kviewshell/plugins/djvu/libdjvu/DjVuAnno.cpp') diff --git a/kviewshell/plugins/djvu/libdjvu/DjVuAnno.cpp b/kviewshell/plugins/djvu/libdjvu/DjVuAnno.cpp new file mode 100644 index 00000000..a6772e61 --- /dev/null +++ b/kviewshell/plugins/djvu/libdjvu/DjVuAnno.cpp @@ -0,0 +1,1514 @@ +//C- -*- C++ -*- +//C- ------------------------------------------------------------------- +//C- DjVuLibre-3.5 +//C- Copyright (c) 2002 Leon Bottou and Yann Le Cun. +//C- Copyright (c) 2001 AT&T +//C- +//C- This software is subject to, and may be distributed under, the +//C- GNU General Public License, Version 2. The license should have +//C- accompanied the software or you may obtain a copy of the license +//C- from the Free Software Foundation at http://www.fsf.org . +//C- +//C- This program is distributed in the hope that it will be useful, +//C- but WITHOUT ANY WARRANTY; without even the implied warranty of +//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//C- GNU General Public License for more details. +//C- +//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library +//C- distributed by Lizardtech Software. On July 19th 2002, Lizardtech +//C- Software authorized us to replace the original DjVu(r) Reference +//C- Library notice by the following text (see doc/lizard2002.djvu): +//C- +//C- ------------------------------------------------------------------ +//C- | DjVu (r) Reference Library (v. 3.5) +//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved. +//C- | The DjVu Reference Library is protected by U.S. Pat. No. +//C- | 6,058,214 and patents pending. +//C- | +//C- | This software is subject to, and may be distributed under, the +//C- | GNU General Public License, Version 2. The license should have +//C- | accompanied the software or you may obtain a copy of the license +//C- | from the Free Software Foundation at http://www.fsf.org . +//C- | +//C- | The computer code originally released by LizardTech under this +//C- | license and unmodified by other parties is deemed "the LIZARDTECH +//C- | ORIGINAL CODE." Subject to any third party intellectual property +//C- | claims, LizardTech grants recipient a worldwide, royalty-free, +//C- | non-exclusive license to make, use, sell, or otherwise dispose of +//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the +//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU +//C- | General Public License. This grant only confers the right to +//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to +//C- | the extent such infringement is reasonably necessary to enable +//C- | recipient to make, have made, practice, sell, or otherwise dispose +//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to +//C- | any greater extent that may be necessary to utilize further +//C- | modifications or combinations. +//C- | +//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY +//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF +//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +//C- +------------------------------------------------------------------ +// +// $Id: DjVuAnno.cpp,v 1.12 2004/04/17 23:56:11 leonb Exp $ +// $Name: release_3_5_15 $ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#if NEED_GNUG_PRAGMAS +# pragma implementation +#endif + +#include "DjVuAnno.h" +#include "GContainer.h" +#include "GException.h" +#include "IFFByteStream.h" +#include "BSByteStream.h" +#include "GMapAreas.h" + +#include "debug.h" + +#include + + +#ifdef HAVE_NAMESPACES +namespace DJVU { +# ifdef NOT_DEFINED // Just to fool emacs c++ mode +} +#endif +#endif + + +// GLParser.h and GLParser.cpp used to be separate files capable to decode +// that weird ANTa chunk format into C++ structures and lists. But since +// its implementation is temporary and is used only in this file (DjVuAnno.cpp) +// it appears reasonable to build it in here. + +//*************************************************************************** +//****************************** GLParser.h ********************************* +//*************************************************************************** + + +class GLObject : public GPEnabled +{ +public: + enum GLObjectType { INVALID=0, NUMBER=1, STRING=2, SYMBOL=3, LIST=4 }; + static const char * const GLObjectString[LIST+1]; + + GLObject(int _number=0); + GLObject(GLObjectType type, const char * str); + GLObject(const char * name, const GPList & list); + virtual ~GLObject(void); + + int get_number(void) const; + GUTF8String get_string(void) const; + GUTF8String get_symbol(void) const; + GPList & get_list(void); + GP operator[](int n) const; + + GLObjectType get_type(void) const; + GUTF8String get_name(void) const; + void print(ByteStream & str, int compact=1, int indent=0, int * cur_pos=0) const; +private: + GLObjectType type; + GUTF8String name; + + int number; + GUTF8String string; + GUTF8String symbol; + GPList list; + void throw_can_not_convert_to(const GLObjectType to) const; +}; + +const char * const GLObject::GLObjectString[]= + {"invalid", "number", "string", "symbol", "list"}; + +inline GLObject::GLObjectType +GLObject::get_type(void) const { return type; } + +inline +GLObject::~GLObject(void) {} + +class GLToken +{ +public: + enum GLTokenType { OPEN_PAR, CLOSE_PAR, OBJECT }; + GLTokenType type; + GP object; + + GLToken(GLTokenType type, const GP & object); +}; + +inline +GLToken::GLToken(GLTokenType xtype, const GP & xobject) : + type(xtype), object(xobject) {} + +class GLParser +{ +public: + void parse(const char * str); + GPList & get_list(void); + GP get_object(const char * name, bool last=true); + void print(ByteStream & str, int compact=1); + + GLParser(void); + GLParser(const char * str); + ~GLParser(void); +private: + GPList list; + + bool compat; + void skip_white_space(const char * & start); + void check_compat(const char *str); + GLToken get_token(const char * & start); + void parse(const char * cur_name, GPList & list, + const char * & start); +}; + +GLParser::GLParser(void) + : compat(false) +{ +} + +GLParser::~GLParser(void) +{ +} + +GPList & +GLParser::get_list(void) +{ + return list; +} + +GLParser::GLParser(const char * str) + : compat(false) +{ + parse(str); +} + + +//*************************************************************************** +//***************************** GLParser.cpp ******************************** +//*************************************************************************** + + +GLObject::GLObject(int xnumber) : type(NUMBER), number(xnumber) {} + +GLObject::GLObject(GLObjectType xtype, const char * str) : type(xtype) +{ + if (type!=STRING && type!=SYMBOL) + G_THROW( ERR_MSG("DjVuAnno.bad_type") ); + if (type==STRING) + string=str; + else symbol=str; +} + +GLObject::GLObject(const char * xname, const GPList & xlist) : + type(LIST), name(xname), list(xlist) {} + +void +GLObject::print(ByteStream & str, int compact, int indent, int * cur_pos) const +{ + int local_cur_pos = 0; + if (!cur_pos) { cur_pos = &local_cur_pos; } + + GUTF8String buffer; + const char * to_print=0; + switch(type) + { + case NUMBER: + to_print=buffer.format("%d",number); + break; + case STRING: + { + int length = string.length(); + const char *data = (const char*)string; + buffer = GUTF8String("\""); + while (*data && length>0) + { + int span = 0; + while (span=0x20 && + data[span]!=0x7f && data[span]!='"' && data[span]!='\\' ) + span++; + if (span > 0) + { + buffer = buffer + GUTF8String(data, span); + data += span; + length -= span; + } + else + { + char buf[8]; + static char *tr1 = "\"\\tnrbf"; + static char *tr2 = "\"\\\t\n\r\b\f"; + sprintf(buf,"\\%03o", (int)(((unsigned char*)data)[span])); + for (int i=0; tr2[i]; i++) + if (data[span] == tr2[i]) + buf[1] = tr1[i]; + if (buf[1]<'0' || buf[1]>'3') + buf[2] = 0; + buffer = buffer + GUTF8String(buf); + data += 1; + length -= 1; + } + } + buffer = buffer + GUTF8String("\""); + to_print = buffer; + } + break; + case SYMBOL: + to_print=buffer.format("%s",(const char *)symbol); + break; + case LIST: + to_print=buffer.format("(%s",(const char *)name); + break; + case INVALID: + break; + } + if (!compact && *cur_pos+strlen(to_print)>70) + { + char ch='\n'; + str.write(&ch, 1); + ch=' '; + for(int i=0;iprint(str, compact, indent, cur_pos); + str.write(") ", 2); + *cur_pos+=2; + } +} + +// This function constructs message names for external lookup. +// The message names are constructed to avoid the problems of concatenating +// phrases (which does not translate well into other languages). The +// message names that can be generated are (listed here to appease the +// auditing program which reads comments): +// ERR_MSG("DjVuAnno.invalid2number"), ERR_MSG("DjVuAnno.string2number"), +// ERR_MSG("DjVuAnno.symbol2number"), ERR_MSG("DjVuAnno.list2number") +// ERR_MSG("DjVuAnno.invalid2string"), ERR_MSG("DjVuAnno.number2string"), +// ERR_MSG("DjVuAnno.symbol2string"), ERR_MSG("DjVuAnno.list2string") +// ERR_MSG("DjVuAnno.invalid2symbol"), ERR_MSG("DjVuAnno.number2symbol"), +// ERR_MSG("DjVuAnno.string2symbol"), ERR_MSG("DjVuAnno.list2symbol") +// ERR_MSG("DjVuAnno.invalid2list"), ERR_MSG("DjVuAnno.number2list"), +// ERR_MSG("DjVuAnno.string2list"), ERR_MSG("DjVuAnno.symbol2list") +void +GLObject::throw_can_not_convert_to(const GLObjectType to) const +{ + static const GUTF8String two('2'); + static const GUTF8String tab('\t'); + GUTF8String mesg("DjVuAnno."); + switch(type) + { + case NUMBER: + mesg+=GLObjectString[NUMBER]+two+GLObjectString[to]+tab+GUTF8String(number); + break; + case STRING: + mesg+=GLObjectString[STRING]+two+GLObjectString[to]+tab+string; + break; + case SYMBOL: + mesg+=GLObjectString[SYMBOL]+two+GLObjectString[to]+tab+symbol; + break; + case LIST: + mesg+=GLObjectString[LIST]+two+GLObjectString[to]+tab+name; + break; + default: + mesg+=GLObjectString[INVALID]+two+GLObjectString[to]; + break; + } + G_THROW(mesg); +} + +GUTF8String +GLObject::get_string(void) const +{ + if (type!=STRING) + { + throw_can_not_convert_to(STRING); + } + return string; +} + +GUTF8String +GLObject::get_symbol(void) const +{ + if (type!=SYMBOL) + { + throw_can_not_convert_to(SYMBOL); + } + return symbol; +} + +int +GLObject::get_number(void) const +{ + if (type!=NUMBER) + { + throw_can_not_convert_to(NUMBER); + } + return number; +} + +GUTF8String +GLObject::get_name(void) const +{ + if (type!=LIST) + { + throw_can_not_convert_to(LIST); + } + return name; +} + +GP +GLObject::operator[](int n) const +{ + if (type!=LIST) + { + throw_can_not_convert_to(LIST); + } + if (n>=list.size()) G_THROW( ERR_MSG("DjVuAnno.too_few") "\t"+name); + int i; + GPosition pos; + for(i=0, pos=list;i & +GLObject::get_list(void) +{ + if (type!=LIST) + { + throw_can_not_convert_to(LIST); + } + return list; +} + +//********************************** GLParser ********************************* + +void +GLParser::skip_white_space(const char * & start) +{ + while(*start && isspace(*start)) start++; + if (!*start) + G_THROW( ByteStream::EndOfFile ); +} + +GLToken +GLParser::get_token(const char * & start) +{ + skip_white_space(start); + char c = *start; + if (c == '(') + { + start++; + return GLToken(GLToken::OPEN_PAR, 0); + } + else if (c == ')') + { + start++; + return GLToken(GLToken::CLOSE_PAR, 0); + } + else if (c=='-' || (c>='0' && c<='9')) + { + return GLToken(GLToken::OBJECT, + new GLObject(strtol(start, (char **) &start, 10))); + } + else if (c=='"') + { + GUTF8String str; + start++; + while(1) + { + int span = 0; + while (start[span] && start[span]!='\\' && start[span]!='\"') + span++; + if (span > 0) + { + str = str + GUTF8String(start,span); + start += span; + } + else if (start[0]=='\"') + { + start += 1; + break; + } + else if (start[0]=='\\' && compat) + { + char c = start[1]; + if (c == '\"') + { + start += 2; + str += '\"'; + } + else + { + start += 1; + str += '\\'; + } + } + else if (start[0]=='\\' && start[1]) + { + char c = *++start; + if (c>='0' && c<='7') + { + int x = 0; + for (int i=0; i<3 && c>='0' && c<='7'; i++) + { + x = x * 8 + c - '0'; + c = *++start; + } + str += (char)(x & 0xff); + } + else + { + static char *tr1 = "tnrbfva"; + static char *tr2 = "\t\n\r\b\f\013\007"; + for (int i=0; tr1[i]; i++) + if (c == tr1[i]) + c = tr2[i]; + start += 1; + str += c; + } + } + else + { + G_THROW( ByteStream::EndOfFile ); + } + } + return GLToken(GLToken::OBJECT, + new GLObject(GLObject::STRING, str)); + } + else + { + GUTF8String str; + while(1) + { + char ch=*start++; + if (!ch) + G_THROW( ByteStream::EndOfFile ); + if (ch==')') { start--; break; } + if (isspace(ch)) break; + str+=ch; + } + return GLToken(GLToken::OBJECT, new GLObject(GLObject::SYMBOL, str)); + } +} + +void +GLParser::parse(const char * cur_name, GPList & list, + const char * & start) +{ + DEBUG_MSG("GLParse::parse(): Parsing contents of object '" << cur_name << "'\n"); + DEBUG_MAKE_INDENT(3); + + while(1) + { + GLToken token=get_token(start); + if (token.type==GLToken::OPEN_PAR) + { + if (isspace(*start)) + { + GUTF8String mesg=GUTF8String( ERR_MSG("DjVuAnno.paren") "\t")+cur_name; + G_THROW(mesg); + } + + GLToken tok=get_token(start); + GP object=tok.object; // This object should be SYMBOL + // We will convert it to LIST later + if (tok.type!=GLToken::OBJECT || object->get_type()!=GLObject::SYMBOL) + { + if (tok.type==GLToken::OPEN_PAR || + tok.type==GLToken::CLOSE_PAR) + { + GUTF8String mesg=GUTF8String( ERR_MSG("DjVuAnno.no_paren") "\t")+cur_name; + G_THROW(mesg); + } + if (tok.type==GLToken::OBJECT) + { + GLObject::GLObjectType type=object->get_type(); + if (type==GLObject::NUMBER) + { + GUTF8String mesg( ERR_MSG("DjVuAnno.no_number") "\t"); + mesg += cur_name; + G_THROW(mesg); + } + else if (type==GLObject::STRING) + { + GUTF8String mesg( ERR_MSG("DjVuAnno.no_string") "\t"); + mesg += cur_name; + G_THROW(mesg); + } + } + } + + // OK. Get the object contents + GPList new_list; + G_TRY + { + parse(object->get_symbol(), new_list, start); + } + G_CATCH(exc) + { + if (exc.cmp_cause(ByteStream::EndOfFile)) + G_RETHROW; + } + G_ENDCATCH; + list.append(new GLObject(object->get_symbol(), new_list)); + continue; + } + if (token.type==GLToken::CLOSE_PAR) + return; + list.append(token.object); + } +} + +void +GLParser::check_compat(const char *s) +{ + int state = 0; + while (s && *s && !compat) + { + switch(state) + { + case 0: + if (*s == '\"') + state = '\"'; + break; + case '\"': + if (*s == '\"') + state = 0; + else if (*s == '\\') + state = '\\'; + else if ((unsigned char)(*s)<0x20 || *s==0x7f) + compat = true; + break; + case '\\': + if (!strchr("01234567tnrbfva\"\\",*s)) + compat = true; + state = '\"'; + break; + } + s += 1; + } +} + +void +GLParser::parse(const char * str) +{ + DEBUG_MSG("GLParser::parse(): parsing string contents\n"); + DEBUG_MAKE_INDENT(3); + + G_TRY + { + check_compat(str); + parse("toplevel", list, str); + } G_CATCH(exc) + { + if (exc.cmp_cause(ByteStream::EndOfFile)) + G_RETHROW; + } G_ENDCATCH; +} + +void +GLParser::print(ByteStream & str, int compact) +{ + for(GPosition pos=list;pos;++pos) + list[pos]->print(str, compact); +} + +GP +GLParser::get_object(const char * name, bool last) +{ + GP object; + for(GPosition pos=list;pos;++pos) + { + GP obj=list[pos]; + if (obj->get_type()==GLObject::LIST && + obj->get_name()==name) + { + object=obj; + if (!last) break; + } + } + return object; +} + +//*************************************************************************** +//********************************** ANT ************************************ +//*************************************************************************** + +static const char *zoom_strings[]={ + "default","page","width","one2one","stretch"}; +static const int zoom_strings_size=sizeof(zoom_strings)/sizeof(const char *); + +static const char *mode_strings[]={ + "default","color","fore","back","bw"}; +static const int mode_strings_size=sizeof(mode_strings)/sizeof(const char *); + +static const char *align_strings[]={ + "default","left","center","right","top","bottom"}; +static const int align_strings_size=sizeof(align_strings)/sizeof(const char *); + +#define PNOTE_TAG "pnote" +#define BACKGROUND_TAG "background" +#define ZOOM_TAG "zoom" +#define MODE_TAG "mode" +#define ALIGN_TAG "align" +#define HALIGN_TAG "halign" +#define VALIGN_TAG "valign" +#define METADATA_TAG "metadata" + +static const unsigned long default_bg_color=0xffffffff; + +DjVuANT::DjVuANT(void) +{ + bg_color=default_bg_color; + zoom=0; + mode=MODE_UNSPEC; + hor_align=ver_align=ALIGN_UNSPEC; +} + +DjVuANT::~DjVuANT() +{ +} + +GUTF8String +DjVuANT::get_paramtags(void) const +{ + GUTF8String retval; + if(zoom > 0) + { + retval+="\n"; + }else if(zoom && ((-zoom)\n"; + } + if((mode>0)&&(mode\n"; + } + if((hor_align>ALIGN_UNSPEC)&&(hor_align\n"; + } + if((ver_align>ALIGN_UNSPEC)&&(ver_align\n"; + } + if((bg_color&0xffffff) == bg_color) + { + retval+="\n"; + } + return retval; +} + +void +DjVuANT::writeParam(ByteStream &str_out) const +{ + str_out.writestring(get_paramtags()); +} + +GUTF8String +DjVuANT::get_xmlmap(const GUTF8String &name,const int height) const +{ + GUTF8String retval("\n"); + for(GPosition pos(map_areas);pos;++pos) + { + retval+=map_areas[pos]->get_xmltag(height); + } + return retval+"\n"; +} + +void +DjVuANT::writeMap( + ByteStream &str_out,const GUTF8String &name,const int height) const +{ + str_out.writestring("\n"); + for(GPosition pos(map_areas);pos;++pos) + { + str_out.writestring(GUTF8String(map_areas[pos]->get_xmltag(height))); + } + str_out.writestring(GUTF8String("\n")); +} + +GUTF8String +DjVuANT::read_raw(ByteStream & str) +{ + GUTF8String raw; + char buffer[1024]; + int length; + while((length=str.read(buffer, 1024))) + raw+=GUTF8String(buffer, length); + return raw; +} + +void +DjVuANT::decode(class GLParser & parser) +{ + bg_color=get_bg_color(parser); + zoom=get_zoom(parser); + mode=get_mode(parser); + hor_align=get_hor_align(parser); + ver_align=get_ver_align(parser); + map_areas=get_map_areas(parser); +#ifndef NO_METADATA_IN_ANT_CHUNK + metadata=get_metadata(parser); +#endif +} + + +void +DjVuANT::decode(ByteStream & str) +{ + GLParser parser(read_raw(str)); + decode(parser); +} + +void +DjVuANT::merge(ByteStream & str) +{ + GLParser parser(encode_raw()); + GUTF8String add_raw=read_raw(str); + parser.parse(add_raw); + decode(parser); +} + +void +DjVuANT::encode(ByteStream &bs) +{ + GUTF8String raw=encode_raw(); + bs.writall((const char*) raw, raw.length()); +} + +unsigned int +DjVuANT::get_memory_usage() const +{ + return sizeof(DjVuANT); +} + +unsigned char +DjVuANT::decode_comp(char ch1, char ch2) +{ + unsigned char dig1=0; + if (ch1) + { + ch1=toupper(ch1); + if (ch1>='0' && ch1<='9') dig1=ch1-'0'; + if (ch1>='A' && ch1<='F') dig1=10+ch1-'A'; + + unsigned char dig2=0; + if (ch2) + { + ch2=toupper(ch2); + if (ch2>='0' && ch2<='9') dig2=ch2-'0'; + if (ch2>='A' && ch2<='F') dig2=10+ch2-'A'; + return (dig1 << 4) | dig2; + } + return dig1; + } + return 0; +} + +unsigned long int +DjVuANT::cvt_color(const char * color, unsigned long int def) +{ + if (color[0]!='#') return def; + + unsigned long int color_rgb=0; + color++; + const char * start, * end; + + // Do blue + end=color+strlen(color); start=end-2; + if (startstart) + color_rgb|=decode_comp(start[0], start+1start) + color_rgb|=decode_comp(start[0], start+1start) + color_rgb|=decode_comp(start[0], start+1start) + color_rgb|=decode_comp(start[0], start+1 obj=parser.get_object(BACKGROUND_TAG); + if (obj && obj->get_list().size()==1) + { + GUTF8String color=(*obj)[0]->get_symbol(); + DEBUG_MSG("color='" << color << "'\n"); + retval=cvt_color(color, 0xffffff); + } +#ifndef NDEBUG + if(retval == default_bg_color) + { + DEBUG_MSG("can't find any.\n"); + } +#endif // NDEBUG + } G_CATCH_ALL {} G_ENDCATCH; +#ifndef NDEBUG + if(retval == default_bg_color) + { + DEBUG_MSG("resetting color to 0xffffffff (UNSPEC)\n"); + } +#endif // NDEBUG + return retval; +} + +int +DjVuANT::get_zoom(GLParser & parser) + // Returns: + // <0 - special zoom (like ZOOM_STRETCH) + // =0 - not set + // >0 - numeric zoom (%%) +{ + int retval=ZOOM_UNSPEC; + DEBUG_MSG("DjVuANT::get_zoom(): getting zoom factor ...\n"); + DEBUG_MAKE_INDENT(3); + G_TRY + { + GP obj=parser.get_object(ZOOM_TAG); + if (obj && obj->get_list().size()==1) + { + const GUTF8String zoom((*obj)[0]->get_symbol()); + DEBUG_MSG("zoom='" << zoom << "'\n"); + + for(int i=0;(i obj=parser.get_object(MODE_TAG); + if (obj && obj->get_list().size()==1) + { + const GUTF8String mode((*obj)[0]->get_symbol()); + DEBUG_MSG("mode='" << mode << "'\n"); + for(int i=0;(i obj=parser.get_object(ALIGN_TAG); + if (obj && obj->get_list().size()==2) + { + const GUTF8String align((*obj)[0]->get_symbol()); + DEBUG_MSG("hor_align='" << align << "'\n"); + + for(int i=(int)ALIGN_UNSPEC;(i obj=parser.get_object(ALIGN_TAG); + if (obj && obj->get_list().size()==2) + { + const GUTF8String align((*obj)[1]->get_symbol()); + DEBUG_MSG("ver_align='" << align << "'\n"); + for(int i=(int)ALIGN_UNSPEC;(i +DjVuANT::get_metadata(GLParser & parser) +{ + DEBUG_MSG("DjVuANT::get_map_areas(): forming and returning back list of map areas\n"); + DEBUG_MAKE_INDENT(3); + + GMap mdata; + + GPList list=parser.get_list(); + for(GPosition pos=list;pos;++pos) + { + GLObject & obj=*list[pos]; + if (obj.get_type()==GLObject::LIST && obj.get_name()==METADATA_TAG) + { + G_TRY + { + for(int obj_num=0;obj_numget_string(); + } + } + } + G_CATCH_ALL { } G_ENDCATCH; + } + } + return mdata; +} +#endif + +GPList +DjVuANT::get_map_areas(GLParser & parser) +{ + DEBUG_MSG("DjVuANT::get_map_areas(): forming and returning back list of map areas\n"); + DEBUG_MAKE_INDENT(3); + + GPList map_areas; + + GPList list=parser.get_list(); + + for(GPosition pos=list;pos;++pos) + { + GLObject & obj=*list[pos]; + const int type=obj.get_type(); + if (type == GLObject::LIST) + { + const GUTF8String name=obj.get_name(); + if(name == GMapArea::MAPAREA_TAG) + { + G_TRY { + // Getting the url + GUTF8String url; + GUTF8String target=GMapArea::TARGET_SELF; + GLObject & url_obj=*(obj[0]); + if (url_obj.get_type()==GLObject::LIST) + { + if (url_obj.get_name()!=GMapArea::URL_TAG) + G_THROW( ERR_MSG("DjVuAnno.bad_url") ); + url=(url_obj[0])->get_string(); + target=(url_obj[1])->get_string(); + } else url=url_obj.get_string(); + + // Getting the comment + GUTF8String comment=(obj[1])->get_string(); + + DEBUG_MSG("found maparea '" << comment << "' (" << + url << ":" << target << ")\n"); + + GLObject * shape=obj[2]; + GP map_area; + if (shape->get_type()==GLObject::LIST) + { + if (shape->get_name()==GMapArea::RECT_TAG) + { + DEBUG_MSG("it's a rectangle.\n"); + GRect grect((*shape)[0]->get_number(), + (*shape)[1]->get_number(), + (*shape)[2]->get_number(), + (*shape)[3]->get_number()); + GP map_rect=GMapRect::create(grect); + map_area=(GMapRect *)map_rect; + } else if (shape->get_name()==GMapArea::POLY_TAG) + { + DEBUG_MSG("it's a polygon.\n"); + int points=shape->get_list().size()/2; + GTArray xx(points-1), yy(points-1); + for(int i=0;iget_number(); + yy[i]=(*shape)[2*i+1]->get_number(); + } + GP map_poly=GMapPoly::create(xx,yy,points); + map_area=(GMapPoly *)map_poly; + } else if (shape->get_name()==GMapArea::OVAL_TAG) + { + DEBUG_MSG("it's an ellipse.\n"); + GRect grect((*shape)[0]->get_number(), + (*shape)[1]->get_number(), + (*shape)[2]->get_number(), + (*shape)[3]->get_number()); + GP map_oval=GMapOval::create(grect); + map_area=(GMapOval *)map_oval; + } + } + + if (map_area) + { + map_area->url=url; + map_area->target=target; + map_area->comment=comment; + for(int obj_num=3;obj_numget_type()==GLObject::LIST) + { + const GUTF8String & name=el->get_name(); + if (name==GMapArea::BORDER_AVIS_TAG) + map_area->border_always_visible=true; + else if (name==GMapArea::HILITE_TAG) + { + GLObject * obj=el->get_list()[el->get_list().firstpos()]; + if (obj->get_type()==GLObject::SYMBOL) + map_area->hilite_color=cvt_color(obj->get_symbol(), 0xff); + } else + { + int border_type= + name==GMapArea::NO_BORDER_TAG ? GMapArea::NO_BORDER : + name==GMapArea::XOR_BORDER_TAG ? GMapArea::XOR_BORDER : + name==GMapArea::SOLID_BORDER_TAG ? GMapArea::SOLID_BORDER : + name==GMapArea::SHADOW_IN_BORDER_TAG ? GMapArea::SHADOW_IN_BORDER : + name==GMapArea::SHADOW_OUT_BORDER_TAG ? GMapArea::SHADOW_OUT_BORDER : + name==GMapArea::SHADOW_EIN_BORDER_TAG ? GMapArea::SHADOW_EIN_BORDER : + name==GMapArea::SHADOW_EOUT_BORDER_TAG ? GMapArea::SHADOW_EOUT_BORDER : -1; + if (border_type>=0) + { + map_area->border_type=(GMapArea::BorderType) border_type; + for(GPosition pos=el->get_list();pos;++pos) + { + GLObject * obj=el->get_list()[pos]; + if (obj->get_type()==GLObject::SYMBOL) + map_area->border_color=cvt_color(obj->get_symbol(), 0xff); + if (obj->get_type()==GLObject::NUMBER) + map_area->border_width=obj->get_number(); + } + } + } + } // if (el->get_type()==...) + } // for(int obj_num=...) + map_areas.append(map_area); + } // if (map_area) ... + } G_CATCH_ALL {} G_ENDCATCH; + } + } + } // while(item==...) + + DEBUG_MSG("map area list size = " << list.size() << "\n"); + + return map_areas; +} + +void +DjVuANT::del_all_items(const char * name, GLParser & parser) +{ + GPList & list=parser.get_list(); + GPosition pos=list; + while(pos) + { + GLObject & obj=*list[pos]; + if (obj.get_type()==GLObject::LIST && + obj.get_name()==name) + { + GPosition this_pos=pos; + ++pos; + list.del(this_pos); + } else ++pos; + } +} + +GUTF8String +DjVuANT::encode_raw(void) const +{ + GUTF8String buffer; + GLParser parser; + + //*** Background color + del_all_items(BACKGROUND_TAG, parser); + if (bg_color!=default_bg_color) + { + buffer.format("(" BACKGROUND_TAG " #%02X%02X%02X)", + (unsigned int)((bg_color & 0xff0000) >> 16), + (unsigned int)((bg_color & 0xff00) >> 8), + (unsigned int)(bg_color & 0xff)); + parser.parse(buffer); + } + + //*** Zoom + del_all_items(ZOOM_TAG, parser); + if (zoom!=ZOOM_UNSPEC) + { + buffer="(" ZOOM_TAG " "; + const int i=1-zoom; + if((i>=0)&& (i=0)&& (i=align_strings_size))?ALIGN_UNSPEC:hor_align] + +" "+align_strings[((ver_align=align_strings_size))?ALIGN_UNSPEC:ver_align]+")"; + parser.parse(buffer); + } + //*** Metadata +#ifndef NO_METADATA_IN_ANT_CHUNK + del_all_items(METADATA_TAG, parser); + if (!metadata.isempty()) + { + GUTF8String mdatabuffer("("); + mdatabuffer += METADATA_TAG ; + for (GPosition pos=metadata; pos; ++pos) + mdatabuffer +=" (" + metadata.key(pos)+" \""+metadata[pos]+"\")"; + mdatabuffer += " )"; + parser.parse(mdatabuffer); + } +#endif + //*** Mapareas + del_all_items(GMapArea::MAPAREA_TAG, parser); + for(GPosition pos=map_areas;pos;++pos) + parser.parse(map_areas[pos]->print()); + + GP gstr=ByteStream::create(); + ByteStream &str=*gstr; + parser.print(str, 1); + GUTF8String ans; + int size = str.size(); + str.seek(0); + str.read(ans.getbuf(size), size); + return ans; +} + +bool +DjVuANT::is_empty(void) const +{ + GUTF8String raw=encode_raw(); + for(int i=raw.length()-1;i>=0;i--) + if (isspace(raw[i])) raw.setat(i, 0); + else break; + return raw.length()==0; +} + +GP +DjVuANT::copy(void) const +{ + GP ant=new DjVuANT(*this); + + + // Now process the list of hyperlinks. + ant->map_areas.empty(); + for(GPosition pos=map_areas;pos;++pos) + ant->map_areas.append(map_areas[pos]->get_copy()); + + return ant; +} + +//*************************************************************************** +//******************************** DjVuAnno ********************************* +//*************************************************************************** + +GUTF8String +DjVuAnno::get_xmlmap(const GUTF8String &name,const int height) const +{ + return ant + ?(ant->get_xmlmap(name,height)) + :("\n"); +} + +void +DjVuAnno::writeMap(ByteStream &str_out,const GUTF8String &name,const int height) const +{ + if(ant) + { + ant->writeMap(str_out,name,height); + }else + { + str_out.writestring(get_xmlmap(name,height)); + } +} + +GUTF8String +DjVuAnno::get_paramtags(void) const +{ + return ant + ?(ant->get_paramtags()) + :GUTF8String(); +} + +void +DjVuAnno::writeParam(ByteStream &str_out) const +{ + str_out.writestring(get_paramtags()); +} + + +void +DjVuAnno::decode(const GP &gbs) +{ + GUTF8String chkid; + GP giff=IFFByteStream::create(gbs); + IFFByteStream &iff=*giff; + while( iff.get_chunk(chkid) ) + { + if (chkid == "ANTa") + { + if (ant) { + ant->merge(*iff.get_bytestream()); + } else { + ant=DjVuANT::create(); + ant->decode(*iff.get_bytestream()); + } + } + else if (chkid == "ANTz") + { + GP gbsiff=BSByteStream::create(giff->get_bytestream()); + if (ant) { + ant->merge(*gbsiff); + } else { + ant=DjVuANT::create(); + ant->decode(*gbsiff); + } + } + // Add decoding of other chunks here + iff.close_chunk(); + } +} + +void +DjVuAnno::encode(const GP &gbs) +{ + GP giff=IFFByteStream::create(gbs); + IFFByteStream &iff=*giff; + if (ant) + { +#if 0 + iff.put_chunk("ANTa"); + ant->encode(iff); + iff.close_chunk(); +#else + iff.put_chunk("ANTz"); + { +// GP bsbinput = giff.get_bytestream(); + GP bsb = BSByteStream::create(giff->get_bytestream(), 50); + ant->encode(*bsb); + } + iff.close_chunk(); +#endif + } + // Add encoding of other chunks here +} + + +GP +DjVuAnno::copy(void) const +{ + GP anno= new DjVuAnno; + // Copy any primitives (if any) + *anno=*this; + // Copy each substructure + if (ant) anno->ant = ant->copy(); + return anno; +} + +void +DjVuAnno::merge(const GP & anno) +{ + if (anno) + { + GP gstr=ByteStream::create(); + encode(gstr); + anno->encode(gstr); + gstr->seek(0); + decode(gstr); + } +} + + +#ifdef HAVE_NAMESPACES +} +# ifndef NOT_USING_DJVU_NAMESPACE +using namespace DJVU; +# endif +#endif -- cgit v1.2.1