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