Alphabetical Class Index  Class Hierarchy   File Members   Compound Members   File List  

ezpdf.h

00001 //
00002 // Copyright (c) 2000 by Tech Soft 3D, LLC.
00003 // The information contained herein is confidential and proprietary to
00004 // Tech Soft 3D, LLC., and considered a trade secret as defined under
00005 // civil and criminal statutes.  Tech Soft 3D shall pursue its civil
00006 // and criminal remedies in the event of unauthorized use or misappropriation
00007 // of its trade secrets.  Use of this information by anyone other than
00008 // authorized employees of Tech Soft 3D, LLC. is granted only under a
00009 // written non-disclosure agreement, expressly prescribing the scope and
00010 // manner of such use.
00011 //
00012 // $Id: 5e6725485197209deca45114c5206af1dc71a722 $
00013 //
00014 
00015 #if 1
00016 
00017 #ifndef _EZPDF_H
00018 #define _EZPDF_H
00019 
00020 #include <locale>
00021 #include <iostream>
00022 #include <fstream>
00023 #include <sstream>
00024 #include <iomanip>
00025 #include <map>
00026 #include <vector>
00027 #include <string>
00028 #include <cstdlib>
00029 #include <assert.h>
00030 #include "zlib.h"
00031 #include "utf_utils.h"
00032 
00033 #ifdef H_PACK_8
00034 #pragma pack(push)
00035 #pragma pack(8)
00036 #endif
00037 
00038 namespace ezpdf
00039 {
00040     using namespace std;
00041 
00042     int const EZPDF_BUFFER_SIZE = 1024*64;
00043 
00044     class File;
00045     class Dict;
00046     class Array;
00047 
00048     namespace common {
00049         bool LittleEndian(){
00050             unsigned short lebom = 0xfffe;
00051             unsigned char const * const first_byte = (unsigned char const * const)&lebom;
00052             return *first_byte == 0xfe;
00053         }
00054 
00055         void escape_char(ostream & out, char const c)
00056         {
00057             if(c == '\\' || c == '(' || c == ')')
00058                 out << '\\';
00059         }
00060     }
00061 
00062     using namespace common;
00063 
00064     void write_string(ostream & out, wstring const & s)
00065     {
00066         H_UTF16 utf16(s.c_str());
00067         /* Write out big endian UTF16 BOM. */
00068         out << '(' << (char)-2 << (char)-1;
00069         utf16_char const * next = utf16.encodedText();
00070         while(*next != 0){
00071             char const upper = (char)((*next >> 8) & 0xff);
00072             escape_char(out, upper);
00073             out << upper;
00074 
00075             char const lower = (char)(*next & 0xff);
00076             escape_char(out, lower);
00077             out << lower;
00078 
00079             ++next;
00080         }
00081         out << ')';
00082     }
00083 
00084     void write_string(ostream & out, string const & s)
00085     {
00086         out << '(';
00087         char const * next = s.c_str();
00088         while(*next != 0){
00089             escape_char(out, *next);
00090             out << *next;
00091             ++next;
00092         }
00093         out << ')';
00094     }
00095 
00096 
00097 
00098     class BaseObject
00099     {
00100     public:
00101         BaseObject ()
00102         {
00103         };
00104 
00105         virtual ~ BaseObject ()
00106         {
00107         };
00108 
00109         friend class File;
00110         friend class Dict;
00111         friend class Array;
00112 
00113     private:
00114         virtual void release ()
00115         {
00116         };
00117 
00118         virtual bool managed () const
00119         {
00120             return false;
00121         };
00122 
00123         virtual void write (ostream & out) const = 0;
00124         virtual BaseObject *clone () const = 0;
00125     };
00126 
00127     class Boolean:public BaseObject
00128     {
00129     private:
00130         bool m_bool;
00131 
00132         void write (ostream & out) const
00133         {
00134             out << (m_bool ? "true" : "false");
00135         };
00136 
00137         void release ()
00138         {
00139             delete this;
00140         };
00141 
00142         BaseObject *clone () const
00143         {
00144             return static_cast < BaseObject * >(new Boolean (m_bool));
00145         };
00146 
00147     public:
00148         friend class Dict;
00149 
00150         Boolean (bool b):m_bool (b)
00151         {
00152         };
00153 
00154         operator bool () const
00155         {
00156             return m_bool;
00157         };
00158     };
00159 
00160     class Int:public BaseObject
00161     {
00162     private:
00163         long m_int;
00164 
00165         void write (ostream & out) const
00166         {
00167             out << m_int;
00168         };
00169 
00170         void release ()
00171         {
00172             delete this;
00173         };
00174 
00175         BaseObject *clone () const
00176         {
00177             return static_cast < BaseObject * >(new Int (m_int));
00178         };
00179 
00180     public:
00181         friend class Dict;
00182 
00183         Int (long i):m_int (i)
00184         {
00185         };
00186 
00187         operator int () const
00188         {
00189             return static_cast<int>(m_int);
00190         };
00191 
00192         operator long () const
00193         {
00194             return m_int;
00195         };
00196 
00197         operator size_t () const
00198         {
00199             return static_cast<size_t>(m_int);
00200         };
00201     };
00202 
00203     class Float:public BaseObject
00204     {
00205     private:
00206         double m_float;
00207 
00208         void write (ostream & out) const
00209         {
00210             out << fixed << setprecision(6) << m_float;
00211         };
00212 
00213         void release ()
00214         {
00215             delete this;
00216         };
00217 
00218         BaseObject *clone () const
00219         {
00220             return static_cast < BaseObject * >(new Float (m_float));
00221         };
00222 
00223     public:
00224         friend class Dict;
00225 
00226         Float (double f):m_float (f)
00227         {
00228         };
00229 
00230         operator float () const
00231         {
00232             return static_cast<float>(m_float);
00233         };
00234 
00235         operator double () const
00236         {
00237             return m_float;
00238         };
00239 
00240     };
00241 
00242     class Name:public BaseObject
00243     {
00244     private:
00245         string m_name;
00246 
00247         void write (ostream & out) const
00248         {
00249             out << '/' << m_name;
00250         };
00251 
00252         void release ()
00253         {
00254             delete this;
00255         };
00256 
00257         BaseObject *clone () const
00258         {
00259             return static_cast < BaseObject * >(new Name (m_name));
00260         };
00261 
00262     public:
00263         friend class Dict;
00264         friend class Graphics;
00265 
00266         Name (string const &s):m_name (s)
00267         {
00268         };
00269 
00270         Name (char const * s):m_name (s)
00271         {
00272         };
00273 
00274         bool operator < (Name const &rhs) const
00275         {
00276             return m_name < rhs.m_name;
00277         };
00278 
00279         bool operator == (Name const &rhs) const
00280         {
00281             return m_name == rhs.m_name;
00282         };
00283 
00284         bool operator != (Name const &rhs) const
00285         {
00286             return m_name != rhs.m_name;
00287         };
00288 
00289         operator string () const
00290         {
00291             return m_name;
00292         };
00293 
00294     };
00295 
00296     class WString : public BaseObject
00297     {
00298     private:
00299         wstring m_string;
00300 
00301         void write (ostream & out) const
00302         {
00303             write_string(out, m_string);
00304         };
00305 
00306         void release ()
00307         {
00308             delete this;
00309         };
00310 
00311         BaseObject *clone () const
00312         {
00313             return static_cast < BaseObject * >(new WString (m_string));
00314         };
00315     public:
00316         friend class Dict;
00317 
00318         explicit WString (string const &s):m_string (H_WCS(s.c_str()).encodedText())
00319         {
00320         };
00321 
00322         explicit WString (wstring const &s):m_string(s)
00323         {
00324         };
00325 
00326         operator wstring () const
00327         {
00328             return m_string;
00329         };
00330 
00331     };
00332 
00333     class String : public BaseObject
00334     {
00335     private:
00336         string m_string;
00337 
00338         void write (ostream & out) const
00339         {
00340             write_string(out, m_string);
00341         };
00342 
00343         void release ()
00344         {
00345             delete this;
00346         };
00347 
00348         BaseObject *clone () const
00349         {
00350             return static_cast < BaseObject * >(new String (m_string));
00351         };
00352     public:
00353         friend class Dict;
00354 
00355         explicit String (string const &s):m_string (s)
00356         {
00357         };
00358 
00359         operator string () const
00360         {
00361             return m_string;
00362         };
00363 
00364     };
00365 
00366 
00367 
00368     class Graphics
00369     {
00370     private:
00371         stringstream m_stream;
00372 
00373         void Font(Name const & font_name, double const points) {
00374             font_name.write(m_stream);
00375             m_stream << ' ' << points << " Tf" << endl;
00376         };
00377 
00378     public:
00379 
00380         /*****************************
00381         * PDF Drawing commands
00382         ****************************
00383 
00384         * B - Fill and stroke the path using nonzero winding number rule
00385         * B* - Fill and stroke the path using even-odd rule
00386         * b - Close, fill and stroke the path using nonzero winding number rule
00387         * b* - Close, fill and stroke the path using even-odd rule
00388         * c - curve
00389         * cs - color space
00390         * d - dash pattern
00391         * f - fill path using nonzero winding number rule
00392         * f* - fill path using even-odd rule
00393         * h - connect last point to first point in path (complete path)
00394         * J - Line Cap
00395         * j - Line Join
00396         * l - line to (from last point in path)
00397         * m - move to (begin new path)
00398         * n - end the path without filling or stroking
00399         * Q - pop color space/clipping state on color space stack
00400         * q - push color space/clipping state on color space stack
00401         * re - rectangle
00402         * RG - set stroke color
00403         * rg _ set fill color
00404         * S - Stroke path
00405         * s - Close and stroke a path (same is "h S")
00406         * scn - something to do with face patterns
00407         * Tf - font size (in points)
00408         * W - marks the current path as the clipping path and intersects it with the current clipping path
00409         * w - line weight
00410 
00411         *****************************
00412         * PDF Drawing commands
00413         ****************************/
00414 
00415         Graphics() {};
00416 
00417         Graphics(Graphics const & g)
00418         {
00419             m_stream << g.m_stream.str();
00420         };
00421 
00422         Graphics const operator = (Graphics const & rhs)
00423         {
00424             m_stream << rhs.m_stream.str();
00425             return *this;
00426         };
00427 
00428         friend class Dict;
00429 
00430         Graphics & Exlicit(string const & cmd)
00431         {
00432             m_stream.write(cmd.c_str(), static_cast<streamsize>(cmd.length()));
00433             m_stream << endl;
00434             return *this;
00435         };
00436 
00437         Graphics & PushGraphicsState() {m_stream << 'q' << endl;return *this;};
00438         Graphics & PopGraphicsState() {m_stream << 'Q' << endl;return *this;};
00439 
00440         Graphics & PenPosition(double const x, double const y)
00441         {
00442             m_stream << x << ' ' << y << " m" << endl;return *this;
00443         };
00444 
00445         Graphics & MovePen(double const x, double const y)
00446         {
00447             m_stream << x << ' ' << y << " l" << endl;return *this;
00448         };
00449 
00450         Graphics & StrokeColor(double const r, double const g, double const b)
00451         {
00452             m_stream << r << ' ' << g << ' ' << b << " RG" << endl;return *this;
00453         };
00454 
00455         Graphics & FillColor(double const r, double const g, double const b)
00456         {
00457             m_stream << r << ' ' << g << ' ' << b << " rg" << endl;return *this;
00458         };
00459 
00460         Graphics & FillAndStrokeWR() {m_stream << "B" << endl;return *this;};
00461         Graphics & FillAndStrokeEO() {m_stream << "B*" << endl;return *this;};
00462         Graphics & CloseFillAndStrokeWR() {m_stream << "b*" << endl;return *this;};
00463         Graphics & CloseFillAndStrokeEO() {m_stream << "b*" << endl;return *this;};
00464         Graphics & FillWR() {m_stream << "f" << endl;return *this;};
00465         Graphics & FillEO() {m_stream << "f*" << endl;return *this;};
00466         Graphics & CompletePath() {m_stream << "h" << endl;return *this;};
00467         Graphics & Stroke() {m_stream << "S" << endl;return *this;};
00468         Graphics & CompleteAndStroke() {m_stream << "s" << endl;return *this;};
00469 
00470         Graphics & BeginText(double const x, double const y, Name const & font_name, double const points)
00471         {
00472             Font(font_name, points);
00473             m_stream << "BT " << x << ' ' << y << " Td ";return *this;
00474         };
00475 
00476         template <typename T>
00477         Graphics & InsertText(T const & text)
00478         {
00479             write_string(m_stream, text);
00480             m_stream << " Tj " << endl;
00481             return *this;
00482         }
00483 
00484         Graphics & InsertText(double const x, double const y, string const & text)
00485         {
00486             m_stream << x << ' ' << y << " Td ";
00487             InsertText(text);
00488             return *this;
00489         };
00490 
00491         Graphics & InsertText(double const x, double const y, wstring const & text)
00492         {
00493             m_stream << x << ' ' << y << " Td ";
00494             InsertText(text);
00495             return *this;
00496         };
00497 
00498         Graphics & EndText()
00499         {
00500             m_stream << "ET" << endl;return *this;
00501         }
00502 
00503         Graphics & InsertImageRGB(double left, double right, double bottom, double top,
00504             int const w, int const h, void const * image)
00505         {
00506             m_stream << "q " << right-left << " 0 0 " << top-bottom << ' ' << left
00507                 << ' ' << bottom << " cm ";
00508             m_stream << "BI /W " << w << " /H " << h << " /CS /RGB /BPC 8 ID ";
00509             m_stream.write(static_cast<char const*>(image), static_cast<streamsize>(w*h*3));
00510             m_stream << "EI Q" << endl;return *this;
00511         };
00512 
00513     };
00514 
00515     class Dict : public BaseObject
00516     {
00517     private:
00518         int m_id;
00519         File * m_file;
00520         stringstream *m_stream;
00521         map < Name, BaseObject * >m_items;
00522 
00523         void *operator   new (size_t size)
00524         {
00525             return malloc (size);
00526         };
00527 
00528         void operator   delete (void *p)
00529         {
00530             free (p);
00531         };
00532 
00533         void write (ostream & out) const
00534         {
00535             out << m_id << " 0 R";
00536         };
00537 
00538         void write_direct (ostream & out) const;
00539         void really_write (ostream & out) const;
00540 
00541         bool managed () const
00542         {
00543             return true;
00544         };
00545 
00546         BaseObject *clone () const
00547         {
00548             // TODO: this isn't really a clone.
00549             return static_cast < BaseObject * >(const_cast < Dict * >(this));
00550         };
00551 
00552         void release ()
00553         {
00554             map < Name, BaseObject * >::iterator iter = m_items.begin ();
00555             while (iter != m_items.end ())
00556             {
00557                 if (!iter->second->managed ())
00558                     iter->second->release ();
00559                 ++iter;
00560             }
00561         };
00562 
00563     public:
00564         friend class File;
00565 
00566         Dict (File * pdf_file, int id):m_id (id), m_file (pdf_file), m_stream (0)
00567         {
00568         };
00569 
00570         ~Dict ()
00571         {
00572             delete m_stream;
00573         };
00574 
00575         Array *newArray () const;
00576         Array *newArray (Name const &);
00577         template <typename T>
00578         Array *newArray (T const *, T const *) const;
00579         template <typename T>
00580         Array *newArray (Name const &, T const *, T const *);
00581         Dict *newDict () const;
00582         Dict *newDict (Name const &);
00583 
00584         template <typename T1> bool get(Name const & key, Array *& value_out)
00585         {
00586             bool retval = false;
00587             map < Name, BaseObject * >::const_iterator iter = m_items.find (key);
00588             if(iter != m_items.end())
00589             {
00590                 //We really need to use a dynamic_cast here, but no RTTI yet in HOOPS.
00591                 //T1 value = dynamic_cast<T1>(iter->second);
00592                 T1 value = static_cast<T1>(iter->second);
00593                 if(value)
00594                 {
00595                     value_out = value;
00596                     retval = true;
00597                 }
00598             }
00599             return retval;
00600         }
00601 
00602         template <typename T1> bool get(Name const & key, Dict *& value_out)
00603         {
00604             bool retval = false;
00605             map < Name, BaseObject * >::const_iterator iter = m_items.find (key);
00606             if(iter != m_items.end())
00607             {
00608                 //We really need to use a dynamic_cast here, but no RTTI yet in HOOPS.
00609                 //T1 value = dynamic_cast<T1>(iter->second);
00610                 T1 value = static_cast<T1>(iter->second);
00611                 if(value)
00612                 {
00613                     value_out = value;
00614                     retval = true;
00615                 }
00616             }
00617             return retval;
00618         }
00619 
00620         template <typename T1, typename T2> bool get(Name const & key, T2 & value_out) const
00621         {
00622             bool retval = false;
00623             map < Name, BaseObject * >::const_iterator iter = m_items.find (key);
00624             if(iter != m_items.end())
00625             {
00626                 //We really need to use a dynamic_cast here, but no RTTI yet in HOOPS.
00627                 //T1 const * value = dynamic_cast<T1*>(iter->second);
00628                 T1 const * value = static_cast<T1*>(iter->second);
00629                 if(value)
00630                 {
00631                     value_out = *value;
00632                     retval = true;
00633                 }
00634             }
00635             return retval;
00636         }
00637 
00638         Dict * appendStream (Graphics g)
00639         {
00640             if (!m_stream)
00641                 m_stream = new stringstream(stringstream::binary |
00642                 stringstream::in |
00643                 stringstream::out);
00644             else
00645                 *m_stream << ' ';
00646 
00647             char buffer[EZPDF_BUFFER_SIZE];
00648             g.m_stream.read (buffer,
00649                 static_cast < streamsize > (EZPDF_BUFFER_SIZE));
00650             while (g.m_stream.gcount () > 0)
00651             {
00652                 m_stream->write (buffer, g.m_stream.gcount ());
00653                 g.m_stream.read (buffer,
00654                     static_cast < streamsize > (EZPDF_BUFFER_SIZE));
00655             }
00656             return this;
00657         }
00658 
00659         Dict * appendStream (void const *begin, size_t size)
00660         {
00661             if (!m_stream)
00662                 m_stream = new stringstream(stringstream::binary |
00663                 stringstream::in |
00664                 stringstream::out);
00665             m_stream->write (static_cast<char const*>(begin), static_cast<streamsize>(size));
00666             return this;
00667         };
00668 
00669         int streamSize () const
00670         {
00671             int retval = 0;
00672             if (m_stream)
00673                 retval = m_stream->tellp ();
00674             return retval;
00675         };
00676 
00677         Dict * remove (Name const &n)
00678         {
00679             map < Name, BaseObject * >::iterator iter = m_items.find (n);
00680             if(iter != m_items.end()){
00681                 if(!iter->second->managed()){
00682                     iter->second->release();
00683                 }
00684                 m_items.erase(n);
00685             }
00686             return this;
00687         };
00688 
00689         Dict * insert (Name const &n, Array * value);
00690 
00691         Dict * insert (Name const &n, int value)
00692         {
00693             remove(n);
00694             BaseObject *b = new Int (value);
00695             m_items.insert (make_pair (n, b));
00696             return this;
00697         };
00698 
00699         Dict * insert (Name const &n, float value)
00700         {
00701             remove(n);
00702             BaseObject *b = new Float (value);
00703             m_items.insert (make_pair (n, b));
00704             return this;
00705         };
00706 
00707         Dict * insert (Name const &n, double value)
00708         {
00709             remove(n);
00710             BaseObject *b = new Float (value);
00711             m_items.insert (make_pair (n, b));
00712             return this;
00713         };
00714 
00715         Dict * insert (Name const &n, long value)
00716         {
00717             remove(n);
00718             BaseObject *b = new Int (value);
00719             m_items.insert (make_pair (n, b));
00720             return this;
00721         };
00722 
00723         Dict * insert (Name const &n, size_t value)
00724         {
00725             remove(n);
00726             BaseObject *b = new Int (static_cast<long>(value));
00727             m_items.insert (make_pair (n, b));
00728             return this;
00729         };
00730 
00731         Dict * insert (Name const &n, bool value)
00732         {
00733             remove(n);
00734             BaseObject *b = new Boolean (value);
00735             m_items.insert (make_pair (n, b));
00736             return this;
00737         };
00738 
00739         Dict * insert (Name const &n, WString const &value)
00740         {
00741             remove(n);
00742             BaseObject *b = new WString (value);
00743             m_items.insert (make_pair (n, b));
00744             return this;
00745         };
00746 
00747         Dict * insert (Name const &n, String const &value)
00748         {
00749             remove(n);
00750             BaseObject *b = new String (value);
00751             m_items.insert (make_pair (n, b));
00752             return this;
00753         };
00754 
00755         Dict * insert (Name const &n, Name const &value)
00756         {
00757             remove(n);
00758             BaseObject *b = new Name (value);
00759             m_items.insert (make_pair (n, b));
00760             return this;
00761         };
00762 
00763         Dict * insert (Name const &n, Dict const * value)
00764         {
00765             remove(n);
00766             Dict * d = const_cast<Dict*>(value);
00767             m_items.insert (make_pair (n, static_cast < BaseObject * >(d)));
00768             return this;
00769         };
00770 
00771     };
00772 
00773     class Array:public BaseObject
00774     {
00775     private:
00776         vector < BaseObject * >m_items;
00777 
00778         void clear ()
00779         {
00780             for (unsigned int i = 0; i < m_items.size (); ++i)
00781             {
00782                 if (!m_items[i]->managed ())
00783                 {
00784                     m_items[i]->release ();
00785                 }
00786             }
00787             m_items.clear ();
00788         };
00789 
00790         void *operator   new (size_t size)
00791         {
00792             return malloc (size);
00793         };
00794 
00795         void operator   delete (void *p)
00796         {
00797             free (p);
00798         };
00799 
00800 
00801         BaseObject *clone () const
00802         {
00803             Array *tmp = new Array;
00804             *tmp = *this;
00805             return tmp;
00806         };
00807 
00808         void write (ostream & out) const
00809         {
00810             out << '[';
00811             if (!m_items.empty ()){
00812                 m_items[0]->write (out);
00813                 for (unsigned int i = 1; i < m_items.size (); ++i)
00814                 {
00815                     out << ' ';
00816                     m_items[i]->write (out);
00817                 }
00818             }
00819             out << ']';
00820         };
00821 
00822         void release ()
00823         {
00824             clear();
00825         };
00826 
00827         bool managed () const
00828         {
00829             return true;
00830         };
00831 
00832         ~Array ()
00833         {
00834             clear ();
00835         };
00836 
00837         Array ()
00838         {
00839         };
00840 
00841         Array (int const *begin, int const *end)
00842         {
00843             insert (begin, end);
00844         };
00845 
00846         Array (float const *begin, float const *end)
00847         {
00848             insert (begin, end);
00849         };
00850 
00851         Array (bool const *begin, bool const *end)
00852         {
00853             insert (begin, end);
00854         };
00855 
00856         Array (WString const *begin, WString const *end)
00857         {
00858             insert (begin, end);
00859         };
00860 
00861         Array (String const *begin, String const *end)
00862         {
00863             insert (begin, end);
00864         };
00865 
00866         Array (Name const *begin, Name const *end)
00867         {
00868             insert (begin, end);
00869         };
00870 
00871         Array (Dict ** begin, Dict ** end)
00872         {
00873             insert (begin, end);
00874         };
00875 
00876         Array (Array * begin, Array * end)
00877         {
00878             insert (begin, end);
00879         };
00880     public:
00881         friend class File;
00882 
00883         template <typename T1> bool get(unsigned int index, Dict *& value_out)
00884         {
00885             bool retval = false;
00886             if(index < m_items.size())
00887             {
00888                 BaseObject * bo = m_items[index];
00889                 //We really need to use a dynamic_cast here, but no RTTI yet in HOOPS.
00890                 //T1 value = dynamic_cast<T1>(bo);
00891                 T1 value = static_cast<T1>(bo);
00892                 if(value)
00893                 {
00894                     value_out = value;
00895                     retval = true;
00896                 }
00897             }
00898             return retval;
00899         }
00900 
00901         template <typename T1, typename T2> bool get(unsigned int index, T2 & value_out) const
00902         {
00903             bool retval = false;
00904             if(index < m_items.size())
00905             {
00906                 BaseObject * bo = m_items[index];
00907                 //We really need to use a dynamic_cast here, but no RTTI yet in HOOPS.
00908                 //T1 * value = dynamic_cast<T1*>(bo);
00909                 T1 * value = static_cast<T1*>(bo);
00910                 if(value)
00911                 {
00912                     value_out = *value;
00913                     retval = true;
00914                 }
00915             }
00916             return retval;
00917         }
00918 
00919         size_t size () const
00920         {
00921             return m_items.size ();
00922         };
00923 
00924         void remove (unsigned int const index)
00925         {
00926             if(index < m_items.size()){
00927 
00928                 if(!m_items[index]->managed())
00929                     m_items[index]->release();
00930 
00931                 m_items.erase(m_items.begin() + index);
00932             }
00933         };
00934 
00935         Array & insert (int value)
00936         {
00937             m_items.push_back (new Int (value));
00938             return *this;
00939         };
00940 
00941         Array & insert (float value)
00942         {
00943             m_items.push_back (new Float (value));
00944             return *this;
00945         };
00946 
00947         Array & insert (double value)
00948         {
00949             m_items.push_back (new Float (value));
00950             return *this;
00951         };
00952 
00953         Array & insert (bool value)
00954         {
00955             m_items.push_back (new Boolean (value));
00956             return *this;
00957         };
00958 
00959         Array & insert (WString const &value)
00960         {
00961             m_items.push_back (new WString (value));
00962             return *this;
00963         };
00964 
00965         Array & insert (String const &value)
00966         {
00967             m_items.push_back (new String (value));
00968             return *this;
00969         };
00970 
00971         Array & insert (Name const &value)
00972         {
00973             m_items.push_back (new Name (value));
00974             return *this;
00975         };
00976 
00977         Array & insert (Dict * value)
00978         {
00979             m_items.push_back (value);
00980             return *this;
00981         };
00982 
00983         Array & insert (Array * value)
00984         {
00985             m_items.push_back (value);
00986             return *this;
00987         };
00988 
00989         Array & insert (int const *begin, int const *end)
00990         {
00991             while (begin != end)
00992             {
00993                 m_items.push_back (new Int (*begin));
00994                 ++begin;
00995             }
00996             return *this;
00997         };
00998 
00999         Array & insert (float const *begin, float const *end)
01000         {
01001             while (begin != end)
01002             {
01003                 m_items.push_back (new Float (*begin));
01004                 ++begin;
01005             }
01006             return *this;
01007         };
01008 
01009         Array & insert (bool const *begin, bool const *end)
01010         {
01011             while (begin != end)
01012             {
01013                 m_items.push_back (new Boolean (*begin));
01014                 ++begin;
01015             }
01016             return *this;
01017         };
01018 
01019         Array & insert (WString const *begin, WString const *end)
01020         {
01021             while (begin != end)
01022             {
01023                 m_items.push_back (new WString (*begin));
01024                 ++begin;
01025             }
01026             return *this;
01027         };
01028 
01029         Array & insert (String const *begin, String const *end)
01030         {
01031             while (begin != end)
01032             {
01033                 m_items.push_back (new String (*begin));
01034                 ++begin;
01035             }
01036             return *this;
01037         };
01038 
01039         Array & insert (Name const *begin, Name const *end)
01040         {
01041             while (begin != end)
01042             {
01043                 m_items.push_back (new Name (*begin));
01044                 ++begin;
01045             }
01046             return *this;
01047         };
01048 
01049         Array & insert (Dict ** begin, Dict ** end)
01050         {
01051             while (begin != end)
01052             {
01053                 m_items.push_back (*begin);
01054                 ++begin;
01055             }
01056             return *this;
01057         };
01058 
01059         Array & insert (Array *begin, Array *end)
01060         {
01061             while (begin != end)
01062             {
01063                 m_items.push_back (begin);
01064                 ++begin;
01065             }
01066             return *this;
01067         };
01068     };
01069 
01070     Dict * Dict::insert (Name const &n, Array * value)
01071     {
01072         remove(n);
01073         m_items.insert (make_pair (n, static_cast<BaseObject*>(value)));
01074         return this;
01075     };
01076 
01077     class File : public BaseObject
01078     {
01079     private:
01080         int m_object_count;
01081         mutable Dict * m_ptrailer;
01082         float m_version;
01083         map < int, long > m_xrefs;
01084         vector < Dict * > m_dictionaries;
01085         vector < Array * > m_arrays;
01086         ofstream m_out;
01087 
01088         BaseObject *clone () const
01089         {
01090             return 0;
01091         };
01092 
01093         void write (ostream & out) const
01094         {
01095             out << "%PDF-" << m_version;
01096 
01097             for (unsigned int i = 0; i < m_dictionaries.size (); ++i)
01098             {
01099                 m_dictionaries[i]->really_write (out);
01100             }
01101 
01102             out << "\n\n\n";
01103             long xref_fpos = out.tellp ();
01104             out << "xref" << endl;
01105             out << "0 " << m_object_count << endl;
01106 
01107             char cur_fill = out.fill ();
01108             out.fill ('0');
01109 
01110             for (int i = 0; i < m_object_count; ++i)
01111             {
01112                 map < int, long >::const_iterator iter = m_xrefs.find (i);
01113                 if (iter == m_xrefs.end ())
01114                     out << "0000000000 65535 f " << endl;
01115                 else
01116                     out << setw (10) << iter->second << " 00000 n " << endl;
01117             }
01118             out.fill (cur_fill);
01119 
01120             m_ptrailer->insert("Size", m_object_count);
01121             out << "\n\n" << "trailer" << endl;
01122             m_ptrailer->write_direct(out);
01123             out << "\n\n\n";
01124 
01125             out << "startxref" << endl << xref_fpos << endl << "%%EOF";
01126 
01127             if(out.fail())
01128                 throw false;
01129         };
01130 
01131         void release ()
01132         {
01133         };
01134 
01135     public:
01136         friend class Dict;
01137 
01138         explicit File (string const & filename):m_object_count (1), m_ptrailer(0),
01139             m_version (1.7f), m_out (filename.c_str(), ios::out | ios::binary)
01140         {
01141         };
01142 
01143         explicit File (wstring const & filename):m_object_count (1), m_ptrailer(0),
01144             m_version (1.7f)
01145         {
01146 #if _MSC_VER
01147             m_out.open(filename.c_str(), ios::out | ios::binary);
01148 #else
01149             int len = wcstombs(0, filename.c_str(), 0) +1;
01150             char * tmp = new char[len];
01151             char const * const old_loc = setlocale(LC_CTYPE, "");
01152             wcstombs(tmp, filename.c_str(), len);
01153             setlocale(LC_CTYPE, old_loc);
01154             m_out.open(tmp, ios::out | ios::binary);
01155             delete [] tmp;
01156 #endif
01157         };
01158 
01159         ~File ()
01160         {
01161             if(m_ptrailer)
01162                 m_ptrailer->release ();
01163             delete m_ptrailer;
01164 
01165             for (unsigned int i = 0; i < m_dictionaries.size (); ++i)
01166             {
01167                 m_dictionaries[i]->release ();
01168             }
01169 
01170             for (unsigned int i = 0; i < m_arrays.size(); ++i)
01171             {
01172                 m_arrays[i]->release();
01173             }
01174 
01175             for (unsigned int i = 0; i < m_dictionaries.size (); ++i)
01176             {
01177                 delete m_dictionaries[i];
01178             }
01179 
01180             for (unsigned int i = 0; i < m_arrays.size(); ++i)
01181             {
01182                 delete m_arrays[i];
01183             }
01184         };
01185 
01186         void close () {
01187             if(m_out.is_open()){
01188                 write(m_out);
01189             }
01190             m_out.close();
01191         };
01192 
01193         template <typename T1> bool get(Name const & key, Dict *& value_out)
01194         {
01195             return m_ptrailer->get<T1> (key, value_out);
01196         }
01197 
01198         template <typename T1, typename T2> bool get(Name const & key, T2 & value_out) const
01199         {
01200             return m_ptrailer->get<T1> (key, value_out);
01201         }
01202 
01203         Array * newArray ()
01204         {
01205             Array *retval = new Array;
01206             m_arrays.push_back (retval);
01207             return retval;
01208         };
01209 
01210         template <typename T>
01211         Array * newArray (T const * begin, T const * end)
01212         {
01213             Array *retval = new Array(begin, end);
01214             m_arrays.push_back (retval);
01215             return retval;
01216         }
01217 
01218         Dict *newDict ()
01219         {
01220             Dict *retval = new Dict (this, m_object_count++);
01221             m_dictionaries.push_back (retval);
01222             return retval;
01223         }
01224 
01225         Dict *newDict (Name const & n)
01226         {
01227             Dict *retval = new Dict (this, m_object_count++);
01228             m_dictionaries.push_back (retval);
01229             if(!m_ptrailer)
01230                 m_ptrailer = new Dict(this, 0);
01231             m_ptrailer->insert(n, retval);
01232             return retval;
01233         }
01234     };
01235 
01236     Array * Dict::newArray() const
01237     {
01238         return m_file->newArray();
01239     };
01240 
01241     Array * Dict::newArray(Name const & n)
01242     {
01243         Array * retval = newArray();
01244         insert(n, retval);
01245         return retval;
01246     };
01247 
01248     template <typename T>
01249     Array * Dict::newArray(T const * begin, T const * end) const
01250     {
01251         return m_file->newArray(begin, end);
01252     }
01253 
01254     template <typename T>
01255     Array * Dict::newArray(Name const & n, T const * begin, T const * end)
01256     {
01257         Array * retval = newArray(begin, end);
01258         insert(n, retval);
01259         return retval;
01260     }
01261 
01262     Dict * Dict::newDict() const
01263     {
01264         Dict *retval = new Dict (m_file, m_file->m_object_count++);
01265         m_file->m_dictionaries.push_back (retval);
01266         return retval;
01267     };
01268 
01269     Dict * Dict::newDict(Name const & n)
01270     {
01271         Dict *retval = newDict();
01272         insert(n, retval);
01273         return retval;
01274     };
01275 
01276     void Dict::write_direct (ostream & out) const
01277     {
01278         out << "<<";
01279 
01280         map < Name, BaseObject * >::const_iterator iter = m_items.begin ();
01281         while (iter != m_items.end ())
01282         {
01283             out << endl;
01284             iter->first.write (out);
01285             out << ' ';
01286             iter->second->write (out);
01287             ++iter;
01288         }
01289 
01290         out << endl << ">>";
01291     };
01292 
01293     void Dict::really_write (ostream & out) const
01294     {
01295         if (m_file->m_xrefs.find (m_id) == m_file->m_xrefs.end ())
01296         {
01297 
01298             out << "\n\n\n";
01299             long dict_fpos = out.tellp ();
01300             m_file->m_xrefs.insert (make_pair (m_id, dict_fpos));
01301             out << m_id << " 0 obj\n";
01302 
01303             write_direct(out);
01304 
01305             out << endl;
01306 
01307             if (m_stream)
01308             {
01309                 out << "stream" << endl;
01310                 char buffer[EZPDF_BUFFER_SIZE];
01311                 m_stream->read (buffer,
01312                     static_cast < streamsize > (EZPDF_BUFFER_SIZE));
01313                 while (m_stream->gcount () > 0)
01314                 {
01315                     out.write (buffer, m_stream->gcount ());
01316                     m_stream->read (buffer,
01317                         static_cast < streamsize >
01318                         (EZPDF_BUFFER_SIZE));
01319                 }
01320                 out << endl << "endstream" << endl;
01321             }
01322 
01323             out << "endobj";
01324         }
01325     };
01326 
01327     namespace filters {
01328         class filter {
01329         public:
01330             virtual ~filter() {};
01331             virtual filter & read(void*, streamsize) = 0;
01332             virtual filter & write(void const *, streamsize) = 0;
01333             virtual streamsize gcount() const = 0;
01334             virtual char const * name() const = 0;
01335         };
01336 
01337         class zlib : public filter {
01338         public:
01339             zlib() : m_reading(false){
01340                 m_zstrm.zalloc = Z_NULL;
01341                 m_zstrm.zfree = Z_NULL;
01342                 m_zstrm.data_type = Z_ASCII;
01343                 m_zstrm.next_out = 0;
01344                 m_zstrm.avail_out = 0;
01345                 m_zstrm.next_in = 0;
01346                 m_zstrm.avail_in = 0;
01347                 if(deflateInit(&m_zstrm, Z_BEST_COMPRESSION) != Z_OK){
01348                     assert(0);
01349                 }
01350             };
01351 
01352             ~zlib() {
01353                 deflateEnd(&m_zstrm);
01354             };
01355 
01356             filter & read(void * out, streamsize howmuch) {
01357                 if(!m_reading){
01358                     char buffer[EZPDF_BUFFER_SIZE];
01359                     int rc;
01360 
01361                     do{
01362                         m_zstrm.next_out = (Bytef*)(&buffer[0]);
01363                         m_zstrm.avail_out = EZPDF_BUFFER_SIZE;
01364                         rc = deflate(&m_zstrm, Z_FINISH);
01365 
01366                         int have = EZPDF_BUFFER_SIZE - m_zstrm.avail_out;
01367                         if(have){
01368                             m_buf.write(buffer, have);
01369                         }
01370                     }while(rc != Z_STREAM_END);
01371                     m_reading = true;
01372                 }
01373 
01374                 m_buf.read((char*)out, howmuch);
01375                 return *this;
01376             };
01377 
01378             filter & write(void const * in, streamsize howmuch) {
01379                 if(!m_reading){
01380                     m_zstrm.next_in = const_cast<Bytef*>(static_cast<Bytef const*>(in));
01381                     m_zstrm.avail_in = howmuch;
01382 
01383                     char buffer[EZPDF_BUFFER_SIZE];
01384 
01385                     m_zstrm.next_out = (Bytef*)(&buffer[0]);
01386                     m_zstrm.avail_out = EZPDF_BUFFER_SIZE;
01387 
01388                     while(m_zstrm.avail_in > 0){
01389                         int rc = deflate(&m_zstrm, Z_NO_FLUSH);
01390                         if(rc != Z_OK)
01391                             assert(0);
01392 
01393                         int have = EZPDF_BUFFER_SIZE - m_zstrm.avail_out;
01394                         if(have){
01395                             m_buf.write(buffer, have);
01396                             m_zstrm.next_out = (Bytef*)(&buffer[0]);
01397                             m_zstrm.avail_out = EZPDF_BUFFER_SIZE;
01398                         }
01399                     }
01400                     int have = EZPDF_BUFFER_SIZE - m_zstrm.avail_out;
01401                     if(have){
01402                         m_buf.write(buffer, have);
01403                     }
01404                 }
01405 
01406                 return *this;
01407             };
01408 
01409             streamsize gcount() const {
01410                 return m_buf.gcount();
01411             };
01412 
01413             char const * name() const {return "FlateDecode";};
01414 
01415         private:
01416             std::stringstream m_buf;
01417             struct z_stream_s m_zstrm;
01418             bool m_reading;
01419         };
01420     }
01421 };
01422 
01423 
01424 #ifdef H_PACK_8
01425 #pragma pack(pop)
01426 #endif
01427 
01428 #endif
01429 
01430 #endif