Logo Search packages:      
Sourcecode: passepartout version File versions  Download package

pdf.h

#ifndef PDF_H                 // -*- c++ -*-
#define PDF_H
///
// Copyright (C) 2002 - 2004, Fredrik Arnerup & Rasmus Kaj, See COPYING
///
#include "fonts/fontinfo.hh"
#include <glibmm/ustring.h>
#include <sstream>
#include <vector>
#include <map>
#include <stdexcept>

namespace PDF {
  
  /**
   * A simple base for a referece counted object to work with RefCountPtr.
   */
00018   class RefCounted {
  protected:
    RefCounted() : count_(0) {}
    virtual ~RefCounted() {}
  public:
    /** 
     * Increse the reference count for this object.
     */
00026     void inc_refcount() const { ++count_; }
    
    /**
     * Decrease the reference count for this object.  If the reference count
     * reaches zero, the object is deleted.
     */
00032     void dec_refcount() const { if(--count_ == 0) delete this; }
    
  private:
    mutable unsigned int count_;
    
    /** undefined */
    RefCounted(const RefCounted&);
    /** undefined */
    RefCounted operator = (const RefCounted&);
  };
  
  template<typename Obj>
  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<Obj>& src)
      : ptr(src.ptr)
      { if(ptr) ptr->inc_refcount(); }
    
    /// Create a null RefCountPtr
    RefCountPtr() : ptr(0) {}
    
    ~RefCountPtr() {
      if(ptr) ptr->dec_refcount();
    }
    
    RefCountPtr<Obj> operator = (const RefCountPtr<Obj>& src) {
      RefCountPtr<Obj> copy(src);
      std::swap(this->ptr, copy.ptr);
      return *this;
    }
    
    template<typename Dst>
    operator RefCountPtr<Dst> () {
      Dst* t = ptr;
      return RefCountPtr<Dst>(t);
    }
    
    template<typename Dst>
    RefCountPtr<Dst> dyn_cast() {
      return RefCountPtr<Dst>(dynamic_cast<Dst*>(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<typename Obj>
  std::ostream& operator << (std::ostream& out, RefCountPtr<Obj> obj) {
    if(obj)
      return out << *obj.operator->();
    else
      return out << "null";
  }
  
  class Object : public RefCounted {
  public:
    typedef RefCountPtr<Object> 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<Name> 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<typename C>
  class BasicObject : public Object {
  public:
    typedef RefCountPtr< BasicObject<C> > Ptr;
    
    static Ptr create(const C& value) {
      return Ptr(new BasicObject<C>(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<int> Integer;
  typedef BasicObject<float> Real;
  typedef BasicObject<bool> Boolean;
  typedef BasicObject<std::string> String;

  template<> std::ostream& String::write(std::ostream& out);
  
  class Ref : public Object {
  public:
    typedef RefCountPtr<Ref> 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<ReferencedObject> 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<Array> 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<Object::Ptr> Items;
    Items items;
  };
  
  class Dictionary: public Object {
    typedef std::map<std::string, Object::Ptr> Entries;
  public:
    typedef RefCountPtr<Dictionary> 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<Stream> 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<Document> DocumentPtr;
  class Resources;
  typedef RefCountPtr<Resources> 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.
   */
00306   class Content: public Stream{ // only text so far
  public:
    typedef RefCountPtr<Content> Ptr;
    
    /// Create a new Content bound to a specific page.
    static Ptr create(RefCountPtr<Page> 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<XRefs> 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<ReferencedObject::Ptr> Objects;
    Objects objects;  
  };

  class Document: public RefCounted {
  public:
    typedef RefCountPtr<Document> Ptr;
    /// A font object with an associated resource name
    typedef std::pair<Ref::Ptr, const std::string> 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<Ref::Ptr> Pages;
    XRefs::Ptr xrefs;
    Pages pages;
    
    Dictionary::Ptr page_tree_root;
    Ref::Ptr page_tree_root_ref;
    
    typedef std::map<std::string, FontWithName> Fonts;
    Fonts used_font;
    int convert_failures;
  };

};

#endif

Generated by  Doxygen 1.6.0   Back to index