static void display_chunks(ByteStream & out_str, IFFByteStream &iff, const GUTF8String &head, DjVmInfo djvminfo) { size_t size; GUTF8String id, fullid; GUTF8String head2 = head + " "; GPMap<int,DjVmDir::File> djvmmap; int rawoffset; GMap<GUTF8String, int> counters; while ((size = iff.get_chunk(id, &rawoffset))) { if (!counters.contains(id)) counters[id]=0; else counters[id]++; GUTF8String msg; msg.format("%s%s [%d] ", (const char *)head, (const char *)id, size); out_str.format( "%s", (const char *)msg); // Display DJVM is when adequate if (djvminfo.dir) { GP<DjVmDir::File> rec = djvminfo.map[rawoffset]; if (rec) { GUTF8String id = rec->get_load_name(); GUTF8String title = rec->get_title(); out_str.format( "{%s}", (const char*) id); if (rec->is_include()) out_str.format(" [I]"); if (rec->is_thumbnails()) out_str.format(" [T]"); if (rec->is_shared_anno()) out_str.format(" [S]"); if (rec->is_page()) out_str.format(" [P%d]", rec->get_page_num()+1); if (id != title) out_str.format(" (%s)", (const char*)title); } } // Test chunk type iff.full_id(fullid); for (int i=0; disproutines[i].id; i++) if (fullid == disproutines[i].id || id == disproutines[i].id) { int n = msg.length(); while (n++ < 14+(int) head.length()) putchar(out_str, ' '); if (!iff.composite()) out_str.format( " "); (*disproutines[i].subr)(out_str, iff, head2, size, djvminfo, counters[id]); break; } // Default display of composite chunk out_str.format( "\n"); if (iff.composite()) display_chunks(out_str, iff, head2, djvminfo); // Terminate iff.close_chunk(); } }
void lt_XMLParser::Impl::parse_anno( const int width, const int height, const lt_XMLTags &GObject, GMap<GUTF8String,GP<lt_XMLTags> > &Maps, DjVuFile &dfile ) { GP<lt_XMLTags> map; { GPosition usemappos=GObject.get_args().contains("usemap"); if(usemappos) { const GUTF8String mapname(GObject.get_args()[usemappos]); GPosition mappos=Maps.contains(mapname); if(!mappos) { G_THROW((ERR_MSG("XMLAnno.map_find") "\t")+mapname ); }else { map=Maps[mappos]; } } } if(map) { ChangeAnno(width,height,dfile,*map); } }
// -- Helper for merge_and_split_ccs static int makeccid(const Grid_x_Color &x, GMap<Grid_x_Color,int> &map, int &ncc) { GPosition p = map.contains(x); if (p) return map[p]; return map[x] = ncc++; }
static void appendPath(const GURL &url, GMap<GUTF8String,void *> &map, GList<GURL> &list) { if( !url.is_empty() && !map.contains(url.get_string()) ) { map[url.get_string()]=0; list.append(url); } }
void DjVuPortcaster::add_to_closure(GMap<const void *, void *> & set, const DjVuPort * dst, int distance) { // Assuming that the map's already locked // GCriticalSectionLock lock(&map_lock); set[dst]= (void*) (unsigned long) distance; if (route_map.contains(dst)) { GList<void *> & list=*(GList<void *> *) route_map[dst]; for(GPosition pos=list;pos;++pos) { DjVuPort * new_dst=(DjVuPort *) list[pos]; if (!set.contains(new_dst)) add_to_closure(set, new_dst, distance+1); } } }
GURL getExecDir(void) { // This is the same as GetModulePath in DjVuMessage.cpp GURL retval; GUTF8String &xprogramname=DjVuMessage::programname(); if(xprogramname.length()) { if(xprogramname[1]=='/' ||!xprogramname.cmp("../",3) ||!xprogramname.cmp("./",2)) { retval=GURL::Filename::UTF8(xprogramname); } if(retval.is_empty() || !retval.is_file()) { GList<GURL> paths(parsePATH()); GMap<GUTF8String,void *> pathMAP; for(GPosition pos=paths;pos;++pos) { retval=GURL::UTF8(xprogramname,paths[pos]); const GUTF8String path(retval.get_string()); if(!pathMAP.contains(path)) { if(retval.is_file()) break; pathMAP[path]=0; } } } if (! retval.is_empty() ) retval = retval.follow_symlinks(); if (! retval.is_empty() ) retval = retval.base(); } return retval; }
static GUTF8String getbodies( GList<GURL> &paths, const GUTF8String &MessageFileName, GPList<lt_XMLTags> &body, GMap<GUTF8String, void *> & map ) { GUTF8String errors; bool isdone=false; GPosition firstpathpos=paths; for(GPosition pathpos=firstpathpos;!isdone && pathpos;++pathpos) { const GURL::UTF8 url(MessageFileName,paths[pathpos]); if(url.is_file()) { map[MessageFileName]=0; GP<lt_XMLTags> gtags; { GP<ByteStream> bs=ByteStream::create(url,"rb"); G_TRY { gtags=lt_XMLTags::create(bs); } G_CATCH(ex) { GUTF8String mesg(failed_to_parse_XML+("\t"+url.get_string())); if(errors.length()) { errors+="\n"+mesg; }else { errors=mesg; } errors+="\n"+GUTF8String(ex.get_cause()); } G_ENDCATCH; } if(gtags) { lt_XMLTags &tags=*gtags; GPList<lt_XMLTags> Bodies=tags.get_Tags(bodystring); if(! Bodies.isempty()) { isdone=true; for(GPosition pos=Bodies;pos;++pos) { body.append(Bodies[pos]); } } GPList<lt_XMLTags> Head=tags.get_Tags(headstring); if(! Head.isempty()) { isdone=true; GMap<GUTF8String, GP<lt_XMLTags> > includes; lt_XMLTags::get_Maps(includestring,namestring,Head,includes); for(GPosition pos=includes;pos;++pos) { const GUTF8String file=includes.key(pos); if(! map.contains(file)) { GList<GURL> xpaths; xpaths.append(url.base()); const GUTF8String err2(getbodies(xpaths,file,body,map)); if(err2.length()) { if(errors.length()) { errors+="\n"+err2; }else { errors=err2; } } } } } } } }
void lt_XMLParser::Impl::parse(const lt_XMLTags &tags, GURL *pdjvufile) { const GPList<lt_XMLTags> Body(tags.get_Tags(bodytag)); GPosition pos=Body; if(!pos || (pos != Body.lastpos())) { G_THROW( ERR_MSG("XMLAnno.extra_body") ); } const GP<lt_XMLTags> GBody(Body[pos]); if(!GBody) { G_THROW( ERR_MSG("XMLAnno.no_body") ); } GMap<GUTF8String,GP<lt_XMLTags> > Maps; lt_XMLTags::get_Maps(maptag,"name",Body,Maps); const GPList<lt_XMLTags> Objects(GBody->get_Tags(objecttag)); lt_XMLTags::get_Maps(maptag,"name",Objects,Maps); for(GPosition Objpos=Objects;Objpos;++Objpos) { lt_XMLTags &GObject=*Objects[Objpos]; // Map of attributes to value (e.g. "width" --> "500") const GMap<GUTF8String,GUTF8String> &args=GObject.get_args(); GURL codebase; { DEBUG_MSG("Setting up codebase... m_codebase = " << m_codebase << "\n"); GPosition codebasePos=args.contains("codebase"); // If user specified a codebase attribute, assume it is correct (absolute URL): // the GURL constructor will throw an exception if it isn't if(codebasePos) { codebase=GURL::UTF8(args[codebasePos]); }else if (m_codebase.is_dir()) { codebase=m_codebase; }else { codebase=GURL::Filename::UTF8(GOS::cwd()); } DEBUG_MSG("codebase = " << codebase << "\n"); } // the data attribute specifies the input file. This can be // either an absolute URL (starts with file:/) or a relative // URL (for now, just a path and file name). If it's absolute, // our GURL will adequately wrap it. If it's relative, we need // to use the codebase attribute to form an absolute URL first. GPosition datapos=args.contains("data"); if(datapos) { bool isDjVuType=false; GPosition typePos(args.contains("type")); if(typePos) { if(args[typePos] != mimetype) { // DjVuPrintErrorUTF8("Ignoring %s Object tag\n",mimetype); continue; } isDjVuType=true; } const GURL url = (pdjvufile) ? *pdjvufile : GURL::UTF8(args[datapos], (args[datapos][0] == '/') ? codebase.base() : codebase); int width; { GPosition widthPos=args.contains("width"); width=(widthPos)?args[widthPos].toInt():0; } int height; { GPosition heightPos=args.contains("height"); height=(heightPos)?args[heightPos].toInt():0; } GUTF8String gamma; GUTF8String dpi; GUTF8String page; GUTF8String do_ocr; { GPosition paramPos(GObject.contains(paramtag)); if(paramPos) { const GPList<lt_XMLTags> Params(GObject[paramPos]); for(GPosition loc=Params;loc;++loc) { const GMap<GUTF8String,GUTF8String> &pargs=Params[loc]->get_args(); GPosition namepos=pargs.contains("name"); if(namepos) { GPosition valuepos=pargs.contains("value"); if(valuepos) { const GUTF8String name=pargs[namepos].downcase(); const GUTF8String &value=pargs[valuepos]; if(name == "flags") { GMap<GUTF8String,GUTF8String> args; lt_XMLTags::ParseValues(value,args,true); if(args.contains("page")) { page=args["page"]; } if(args.contains("dpi")) { dpi=args["dpi"]; } if(args.contains("gamma")) { gamma=args["gamma"]; } if(args.contains("ocr")) { do_ocr=args["ocr"]; } }else if(name == "page") { page=value; }else if(name == "dpi") { dpi=value; }else if(name == "gamma") { gamma=value; }else if(name == "ocr") { do_ocr=value; } } } } } } const GP<DjVuFile> dfile(get_file(url,page)); if(dpi.is_int() || gamma.is_float()) { int pos=0; ChangeInfo(*dfile,dpi.toInt(),gamma.toDouble(pos,pos)); } parse_anno(width,height,GObject,Maps,*dfile); parse_meta(GObject,*dfile); parse_text(width,height,GObject,*dfile); ChangeTextOCR(do_ocr,width,height,dfile); } } }
void lt_XMLParser::Impl::ChangeAnno( const int width, const int height, DjVuFile &dfile, const lt_XMLTags &map ) { dfile.resume_decode(true); const GP<DjVuInfo> info(dfile.info); const GP<DjVuAnno> ganno(DjVuAnno::create()); DjVuAnno &anno=*ganno; GPosition map_pos; map_pos=map.contains(areatag); if(dfile.contains_anno()) { GP<ByteStream> annobs=dfile.get_merged_anno(); if(annobs) { anno.decode(annobs); if(anno.ant && info) { anno.ant->map_areas.empty(); } } // dfile.remove_anno(); } if(info && map_pos) { const int h=info->height; const int w=info->width; double ws=1.0; double hs=1.0; if(width && width != w) { ws=((double)w)/((double)width); } if(height && height != h) { hs=((double)h)/((double)height); } if(!anno.ant) { anno.ant=DjVuANT::create(); } GPList<GMapArea> &map_areas=anno.ant->map_areas; map_areas.empty(); GPList<lt_XMLTags> gareas=map[map_pos]; for(GPosition pos=gareas;pos;++pos) { if(gareas[pos]) { lt_XMLTags &areas=*(gareas[pos]); GMap<GUTF8String,GUTF8String> args(areas.get_args()); GList<int> coords; // ****************************************************** // Parse the coords attribute: first read the raw data into // a list, then scale the x, y data into another list. For // circles, you also get a radius element with (looks like an x // with no matching y). // ****************************************************** { GPosition coords_pos=args.contains("coords"); if(coords_pos) { GList<int> raw_coords; intList(args[coords_pos],raw_coords); for(GPosition raw_pos=raw_coords;raw_pos;++raw_pos) { const int r=raw_coords[raw_pos]; const int x=(int)(ws*(double)r+0.5); coords.append(x); int y=h-1; if(! ++raw_pos) { y-=(int)(hs*(double)r+0.5); }else { y-=(int)(hs*(double)raw_coords[raw_pos]+0.5); } coords.append(y); // DjVuPrintMessage("Coords (%d,%d)\n",x,y); } } } GUTF8String shape; { GPosition shape_pos=args.contains("shape"); if(shape_pos) { shape=args[shape_pos]; } } GP<GMapArea> a; if(shape == "default") { GRect rect(0,0,w,h); a=GMapRect::create(rect); }else if(!shape.length() || shape == "rect") { int xx[4]; int i=0; for(GPosition rect_pos=coords;(rect_pos)&&(i<4);++rect_pos,++i) { xx[i]=coords[rect_pos]; } if(i!=4) { G_THROW( ERR_MSG("XMLAnno.bad_rect") ); } int xmin,xmax; if(xx[0]>xx[2]) { xmax=xx[0]; xmin=xx[2]; }else { xmin=xx[0]; xmax=xx[2]; } int ymin,ymax; if(xx[1]>xx[3]) { ymax=xx[1]; ymin=xx[3]; }else { ymin=xx[1]; ymax=xx[3]; } GRect rect(xmin,ymin,xmax-xmin,ymax-ymin); a=GMapRect::create(rect); }else if(shape == "circle") { int xx[4]; int i=0; GPosition rect_pos=coords.lastpos(); if(rect_pos) { coords.append(coords[rect_pos]); for(rect_pos=coords;(rect_pos)&&(i<4);++rect_pos) { xx[i++]=coords[rect_pos]; } } if(i!=4) { G_THROW( ERR_MSG("XMLAnno.bad_circle") ); } int x=xx[0],y=xx[1],rx=xx[2],ry=(h-xx[3])-1; GRect rect(x-rx,y-ry,2*rx,2*ry); a=GMapOval::create(rect); }else if(shape == "oval") { int xx[4]; int i=0; for(GPosition rect_pos=coords;(rect_pos)&&(i<4);++rect_pos,++i) { xx[i]=coords[rect_pos]; } if(i!=4) { G_THROW( ERR_MSG("XMLAnno.bad_oval") ); } int xmin,xmax; if(xx[0]>xx[2]) { xmax=xx[0]; xmin=xx[2]; }else { xmin=xx[0]; xmax=xx[2]; } int ymin,ymax; if(xx[1]>xx[3]) { ymax=xx[1]; ymin=xx[3]; }else { ymin=xx[1]; ymax=xx[3]; } GRect rect(xmin,ymin,xmax-xmin,ymax-ymin); a=GMapOval::create(rect); }else if(shape == "poly") { GP<GMapPoly> p=GMapPoly::create(); for(GPosition poly_pos=coords;poly_pos;++poly_pos) { int x=coords[poly_pos]; if(! ++poly_pos) break; int y=coords[poly_pos]; p->add_vertex(x,y); } p->close_poly(); a=p; }else { G_THROW( ( ERR_MSG("XMLAnno.unknown_shape") "\t")+shape ); } if(a) { GPosition pos; if((pos=args.contains("href"))) { a->url=args[pos]; } if((pos=args.contains("target"))) { a->target=args[pos]; } if((pos=args.contains("alt"))) { a->comment=args[pos]; } if((pos=args.contains("bordertype"))) { GUTF8String b=args[pos]; static const GMap<GUTF8String,GMapArea::BorderType> typeMap=BorderTypeMap(); if((pos=typeMap.contains(b))) { a->border_type=typeMap[pos]; }else { G_THROW( (ERR_MSG("XMLAnno.unknown_border") "\t")+b ); } } a->border_always_visible=!!args.contains("visible"); if((pos=args.contains("bordercolor"))) { a->border_color=convertToColor(args[pos]); } if((pos=args.contains("highlight"))) { a->hilite_color=convertToColor(args[pos]); } if((pos=args.contains("border"))) { a->border_width=args[pos].toInt(); //atoi(args[pos]); } map_areas.append(a); } } } } dfile.set_modified(true); dfile.anno=ByteStream::create(); anno.encode(dfile.anno); }