#ifndef PDF_H // -*- c++ -*- #define PDF_H /// // Copyright (C) 2002 - 2004, Fredrik Arnerup & Rasmus Kaj, See COPYING /// #include "fonts/fontinfo.hh" #include #include #include #include #include namespace PDF { /** * A simple base for a referece counted object to work with RefCountPtr. */ class RefCounted { protected: RefCounted() : count_(0) {} virtual ~RefCounted() {} public: /** * Increse the reference count for this object. */ void inc_refcount() const { ++count_; } /** * Decrease the reference count for this object. If the reference count * reaches zero, the object is deleted. */ void dec_refcount() const { if(--count_ == 0) delete this; } private: mutable unsigned int count_; /** undefined */ RefCounted(const RefCounted&); /** undefined */ RefCounted operator = (const RefCounted&); }; template class RefCountPtr { public: /// Create a RefCountPtr from a "raw" pointer. RefCountPtr(Obj* o) : ptr(o) { if(ptr) ptr->inc_refcount(); } /// Copy a RefCountPtr RefCountPtr(const RefCountPtr& src) : ptr(src.ptr) { if(ptr) ptr->inc_refcount(); } /// Create a null RefCountPtr RefCountPtr() : ptr(0) {} ~RefCountPtr() { if(ptr) ptr->dec_refcount(); } RefCountPtr operator = (const RefCountPtr& src) { RefCountPtr copy(src); std::swap(this->ptr, copy.ptr); return *this; } template operator RefCountPtr () { Dst* t = ptr; return RefCountPtr(t); } template RefCountPtr dyn_cast() { return RefCountPtr(dynamic_cast(ptr)); } /// Dereference. const Obj* operator -> () const { if(ptr) return ptr; else throw std::runtime_error("Tried to dreference null RefCountPtr"); } /// Dereference. Obj* operator -> () { if(ptr) return ptr; else throw std::runtime_error("Tried to dreference null RefCountPtr"); } /// Check for beeing non-null. operator bool () const { return ptr; } private: Obj* ptr; }; template std::ostream& operator << (std::ostream& out, RefCountPtr obj) { if(obj) return out << *obj.operator->(); else return out << "null"; } class Object : public RefCounted { public: typedef RefCountPtr Ptr; virtual std::ostream& write(std::ostream& out) = 0; protected: Object() {} private: Object(Object&); void operator = (Object&); }; std::ostream& operator << (std::ostream& out, Object& obj); class Name: public Object { public: typedef RefCountPtr Ptr; static Ptr create(const std::string& name) { return Ptr(new Name(name)); } bool operator < (const Name& x) const; const std::string &get_name() const; std::ostream& write(std::ostream& out); protected: explicit Name(const std::string& name_); private: std::string name; }; template class BasicObject : public Object { public: typedef RefCountPtr< BasicObject > Ptr; static Ptr create(const C& value) { return Ptr(new BasicObject(value)); } std::ostream& write(std::ostream& out) { return out << value_; } const C& get_value() const { return value_; } protected: explicit BasicObject(const C& value) : value_(value) {} private: C value_; }; typedef BasicObject Integer; typedef BasicObject Real; typedef BasicObject Boolean; typedef BasicObject String; template<> std::ostream& String::write(std::ostream& out); class Ref : public Object { public: typedef RefCountPtr Ptr; typedef unsigned Num; typedef unsigned Generation; static Ptr create(Num num, Generation generation) { return Ptr(new Ref(num, generation)); } Num get_num() const { return num_; } Generation get_generation() const { return generation_; } std::ostream& write(std::ostream& out) { return out << num_ << ' ' << generation_ << " R"; } protected: Ref(Num num, Generation generation) : num_(num), generation_(generation) {} private: Num num_; Generation generation_; }; class ReferencedObject : public Object { public: typedef RefCountPtr Ptr; static Ptr create(Ref::Ptr ref, Object::Ptr obj) { return Ptr(new ReferencedObject(ref, obj)); } Ref::Ptr get_ref() const; Object::Ptr get_obj() const { return obj_; } std::ostream& write(std::ostream& out); protected: ReferencedObject(Ref::Ptr ref, Object::Ptr obj); private: Object::Ptr obj_; Ref::Ptr ref_; }; class Array: public Object { public: typedef RefCountPtr Ptr; static Ptr create() { return Ptr(new Array()); } Object::Ptr push_back(Object::Ptr object); std::ostream& write(std::ostream& out); const Object::Ptr at(int i) const { return items.at(i); } Object::Ptr at(int i) { return items.at(i); } protected: Array() {} private: typedef std::vector Items; Items items; }; class Dictionary: public Object { typedef std::map Entries; public: typedef RefCountPtr Ptr; typedef Entries::iterator iterator; typedef Entries::const_iterator const_iterator; typedef Entries::size_type size_type; static Ptr create() { return Ptr(new Dictionary); } Object::Ptr set_entry(const std::string& name, Object::Ptr object); Object::Ptr set_entry_name(const std::string& name, const std::string& value); Object::Ptr set_entry_int(const std::string& name, int value); const Object::Ptr get_entry(const std::string& name) const; Object::Ptr get_entry(const std::string& name); iterator begin() { return entries.begin(); } const_iterator begin() const { return entries.begin(); } iterator end() { return entries.end(); } const_iterator end() const { return entries.end(); } /// Return the number of entries in this Dictionary size_type size() const { return entries.size(); } std::ostream& write(std::ostream& out); protected: Dictionary(); private: Entries entries; }; class Stream : public Dictionary { public: typedef RefCountPtr Ptr; static Ptr create() { return Ptr(new Stream); } std::ostream& data() { return data_; } std::ostream& write(std::ostream& out); std::string rawdata() const; protected: Stream(); private: std::ostringstream data_; }; class Page; class Document; typedef RefCountPtr DocumentPtr; class Resources; typedef RefCountPtr ResourcesPtr; /** * A Content Stream is where the main action is in a PDF document. Most * methods in this class corresponds to PDF operators. Note that some * operators change the state of the PDF stream, and some operators are only * legal in some states. This class does not (yet) enforce such * restrictions. */ class Content: public Stream{ // only text so far public: typedef RefCountPtr Ptr; /// Create a new Content bound to a specific page. static Ptr create(RefCountPtr page); /// Create a new Content that is a Form XObject. static Ptr create(DocumentPtr document, int width, int height); std::ostream& write(std::ostream& out); /** * Register an object for use as an XObject. The object is * given a name in the resource dictionary for XObjects. * \param object the object * \return the XObject name of the object */ std::string registerXObj(Object::Ptr object); /// Enter Text State. void beginText(); /// Leave Text State. void endText(); void selectfont(const font::FontInfo& font); void setgray(float gray); void moveto(float xpos, float ypos); void textRise(float rise); void setWordSpace(const float& w); void setCharSpace(const float& w); void show(const Glib::ustring& s); void whitespace(); void whitespace(float width); DocumentPtr getDocument(); protected: Content(DocumentPtr doc, ResourcesPtr res); private: void commitText(); bool simple_font; DocumentPtr document_; ResourcesPtr resources; float last_xpos, last_ypos, cur_charspace, cur_wordspace, cur_size; std::ostringstream textbuf; }; class XRefs: public RefCounted { friend class Ref; public: typedef RefCountPtr Ptr; static Ptr create(); Ref::Ptr add_object(Object::Ptr object); std::streampos get_xref_offset(); std::ostream& write(std::ostream& out); Ref::Num get_num_of_refs() const; protected: XRefs(); private: std::streampos xref_offset; typedef std::vector Objects; Objects objects; }; class Document: public RefCounted { public: typedef RefCountPtr Ptr; /// A font object with an associated resource name typedef std::pair FontWithName; static Ptr create() { return Ptr(new Document); } Content::Ptr add_page(int width, int height); std::ostream& write(std::ostream& out); XRefs::Ptr get_xrefs() {return xrefs;} FontWithName getFontObject(const font::FontInfo& fontname); /// returns number of characters that failed to print correctly int getNumOfFailedChars() const { return convert_failures; } protected: Document(); private: friend class Content; // access to convert_failures typedef std::vector Pages; XRefs::Ptr xrefs; Pages pages; Dictionary::Ptr page_tree_root; Ref::Ptr page_tree_root_ref; typedef std::map Fonts; Fonts used_font; int convert_failures; }; }; #endif