32 #include "utf_utils.h"
43 int const EZPDF_BUFFER_SIZE = 1024*64;
51 unsigned short lebom = 0xfffe;
52 unsigned char const *
const first_byte = (
unsigned char const *
const)&lebom;
53 return *first_byte == 0xfe;
56 void escape_char(ostream & out,
char const c)
58 if(c ==
'\\' || c ==
'(' || c ==
')')
63 using namespace common;
65 void write_string(ostream & out, wstring
const & s)
67 H_UTF16 utf16(s.c_str());
69 out <<
'(' << (char)-2 << (
char)-1;
70 utf16_char
const * next = utf16.encodedText();
72 char const upper = (char)((*next >> 8) & 0xff);
73 escape_char(out, upper);
76 char const lower = (char)(*next & 0xff);
77 escape_char(out, lower);
85 void write_string(ostream & out,
string const & s)
88 char const * next = s.c_str();
90 escape_char(out, *next);
115 virtual void release ()
119 virtual bool managed ()
const
124 virtual void write (ostream & out)
const = 0;
133 void write (ostream & out)
const
135 out << (m_bool ?
"true" :
"false");
155 operator bool ()
const
166 void write (ostream & out)
const
184 Int (
long i):m_int (i)
188 operator int ()
const
190 return static_cast<int>(m_int);
193 operator long ()
const
198 operator size_t ()
const
200 return static_cast<size_t>(m_int);
209 void write (ostream & out)
const
211 out << fixed << m_float;
227 Float (
double f):m_float (f)
231 operator float ()
const
233 return static_cast<float>(m_float);
236 operator double ()
const
248 void write (ostream & out)
const
250 out <<
'/' << m_name;
267 Name (
string const &s):m_name (s)
271 Name (
char const * s):m_name (s)
275 bool operator < (
Name const &rhs)
const
277 return m_name < rhs.m_name;
280 bool operator == (
Name const &rhs)
const
282 return m_name == rhs.m_name;
285 bool operator != (
Name const &rhs)
const
287 return m_name != rhs.m_name;
290 operator string ()
const
302 void write (ostream & out)
const
304 write_string(out, m_string);
319 explicit WString (
string const &s):m_string (H_WCS(s.c_str()).encodedText())
323 explicit WString (wstring
const &s):m_string(s)
327 operator wstring ()
const
339 void write (ostream & out)
const
341 write_string(out, m_string);
356 explicit String (
string const &s):m_string (s)
360 operator string ()
const
372 stringstream m_stream;
374 void Font(
Name const & font_name,
double const points) {
375 font_name.write(m_stream);
376 m_stream <<
' ' << points <<
" Tf" << endl;
420 m_stream << g.m_stream.str();
425 m_stream << rhs.m_stream.str();
431 Graphics & Exlicit(
string const & cmd)
433 m_stream.write(cmd.c_str(),
static_cast<streamsize
>(cmd.length()));
438 Graphics & PushGraphicsState() {m_stream <<
'q' << endl;
return *
this;};
439 Graphics & PopGraphicsState() {m_stream <<
'Q' << endl;
return *
this;};
441 Graphics & PenPosition(
double const x,
double const y)
443 m_stream << x <<
' ' << y <<
" m" << endl;
return *
this;
446 Graphics & MovePen(
double const x,
double const y)
448 m_stream << x <<
' ' << y <<
" l" << endl;
return *
this;
451 Graphics & StrokeColor(
double const r,
double const g,
double const b)
453 m_stream << r <<
' ' << g <<
' ' << b <<
" RG" << endl;
return *
this;
456 Graphics & FillColor(
double const r,
double const g,
double const b)
458 m_stream << r <<
' ' << g <<
' ' << b <<
" rg" << endl;
return *
this;
461 Graphics & FillAndStrokeWR() {m_stream <<
"B" << endl;
return *
this;};
462 Graphics & FillAndStrokeEO() {m_stream <<
"B*" << endl;
return *
this;};
463 Graphics & CloseFillAndStrokeWR() {m_stream <<
"b*" << endl;
return *
this;};
464 Graphics & CloseFillAndStrokeEO() {m_stream <<
"b*" << endl;
return *
this;};
465 Graphics & FillWR() {m_stream <<
"f" << endl;
return *
this;};
466 Graphics & FillEO() {m_stream <<
"f*" << endl;
return *
this;};
467 Graphics & CompletePath() {m_stream <<
"h" << endl;
return *
this;};
468 Graphics & Stroke() {m_stream <<
"S" << endl;
return *
this;};
469 Graphics & CompleteAndStroke() {m_stream <<
"s" << endl;
return *
this;};
471 Graphics & BeginText(
double const x,
double const y,
Name const & font_name,
double const points)
473 Font(font_name, points);
474 m_stream <<
"BT " << x <<
' ' << y <<
" Td ";
return *
this;
477 template <
typename T>
478 Graphics & InsertText(T
const & text)
480 write_string(m_stream, text);
481 m_stream <<
" Tj " << endl;
485 Graphics & InsertText(
double const x,
double const y,
string const & text)
487 m_stream << x <<
' ' << y <<
" Td ";
492 Graphics & InsertText(
double const x,
double const y, wstring
const & text)
494 m_stream << x <<
' ' << y <<
" Td ";
501 m_stream <<
"ET" << endl;
return *
this;
504 Graphics & InsertImageRGB(
double left,
double right,
double bottom,
double top,
505 int const w,
int const h,
void const * image)
507 m_stream <<
"q " << right-left <<
" 0 0 " << top-bottom <<
' ' << left
508 <<
' ' << bottom <<
" cm ";
509 m_stream <<
"BI /W " << w <<
" /H " << h <<
" /CS /RGB /BPC 8 ID ";
510 m_stream.write(static_cast<char const*>(image), static_cast<streamsize>(w*h*3));
511 m_stream <<
"EI Q" << endl;
return *
this;
521 stringstream *m_stream;
522 map < Name, BaseObject * >m_items;
524 void *
operator new (
size_t size)
526 return malloc (size);
529 void operator delete (
void *p)
534 void write (ostream & out)
const
536 out << m_id <<
" 0 R";
539 void write_direct (ostream & out)
const;
540 void really_write (ostream & out)
const;
542 bool managed ()
const
555 map < Name, BaseObject * >::iterator iter = m_items.begin ();
556 while (iter != m_items.end ())
558 if (!iter->second->managed ())
559 iter->second->release ();
567 Dict (
File * pdf_file,
int id):m_id (
id), m_file (pdf_file), m_stream (0)
576 Array *newArray ()
const;
578 template <
typename T>
579 Array *newArray (T
const *, T
const *)
const;
580 template <
typename T>
581 Array *newArray (
Name const &, T
const *, T
const *);
582 Dict *newDict ()
const;
585 template <
typename T1>
bool get(
Name const & key,
Array *& value_out)
588 map < Name, BaseObject * >::const_iterator iter = m_items.find (key);
589 if(iter != m_items.end())
593 T1 value =
static_cast<T1
>(iter->second);
603 template <
typename T1>
bool get(
Name const & key,
Dict *& value_out)
606 map < Name, BaseObject * >::const_iterator iter = m_items.find (key);
607 if(iter != m_items.end())
611 T1 value =
static_cast<T1
>(iter->second);
621 template <
typename T1,
typename T2>
bool get(
Name const & key, T2 & value_out)
const
624 map < Name, BaseObject * >::const_iterator iter = m_items.find (key);
625 if(iter != m_items.end())
629 T1
const * value =
static_cast<T1*
>(iter->second);
642 m_stream =
new stringstream(stringstream::binary |
648 char buffer[EZPDF_BUFFER_SIZE];
649 g.m_stream.read (buffer,
650 static_cast < streamsize > (EZPDF_BUFFER_SIZE));
651 while (g.m_stream.gcount () > 0)
653 m_stream->write (buffer, g.m_stream.gcount ());
654 g.m_stream.read (buffer,
655 static_cast < streamsize > (EZPDF_BUFFER_SIZE));
660 Dict * appendStream (
void const *begin,
size_t size)
663 m_stream =
new stringstream(stringstream::binary |
666 m_stream->write (static_cast<char const*>(begin), static_cast<streamsize>(size));
670 int streamSize ()
const
674 retval = m_stream->tellp ();
680 map < Name, BaseObject * >::iterator iter = m_items.find (n);
681 if(iter != m_items.end()){
682 if(!iter->second->managed()){
683 iter->second->release();
692 Dict * insert (
Name const &n,
int value)
696 m_items.insert (make_pair (n, b));
700 Dict * insert (
Name const &n,
float value)
704 m_items.insert (make_pair (n, b));
708 Dict * insert (
Name const &n,
double value)
712 m_items.insert (make_pair (n, b));
716 Dict * insert (
Name const &n,
long value)
720 m_items.insert (make_pair (n, b));
724 Dict * insert (
Name const &n,
size_t value)
728 m_items.insert (make_pair (n, b));
732 Dict * insert (
Name const &n,
bool value)
736 m_items.insert (make_pair (n, b));
744 m_items.insert (make_pair (n, b));
752 m_items.insert (make_pair (n, b));
760 m_items.insert (make_pair (n, b));
767 Dict * d =
const_cast<Dict*
>(value);
768 m_items.insert (make_pair (n, static_cast < BaseObject * >(d)));
777 vector < BaseObject * >m_items;
781 for (
unsigned int i = 0; i < m_items.size (); ++i)
783 if (!m_items[i]->managed ())
785 m_items[i]->release ();
791 void *
operator new (
size_t size)
793 return malloc (size);
796 void operator delete (
void *p)
809 void write (ostream & out)
const
812 if (!m_items.empty ()){
813 m_items[0]->write (out);
814 for (
unsigned int i = 1; i < m_items.size (); ++i)
817 m_items[i]->write (out);
828 bool managed ()
const
842 Array (
int const *begin,
int const *end)
847 Array (
float const *begin,
float const *end)
852 Array (
bool const *begin,
bool const *end)
884 template <
typename T1>
bool get(
unsigned int index,
Dict *& value_out)
887 if(index < m_items.size())
892 T1 value =
static_cast<T1
>(bo);
902 template <
typename T1,
typename T2>
bool get(
unsigned int index, T2 & value_out)
const
905 if(index < m_items.size())
910 T1 * value =
static_cast<T1*
>(bo);
922 return m_items.size ();
925 void remove (
unsigned int const index)
927 if(index < m_items.size()){
929 if(!m_items[index]->managed())
930 m_items[index]->release();
932 m_items.erase(m_items.begin() + index);
936 Array & insert (
int value)
938 m_items.push_back (
new Int (value));
942 Array & insert (
float value)
944 m_items.push_back (
new Float (value));
948 Array & insert (
double value)
950 m_items.push_back (
new Float (value));
954 Array & insert (
bool value)
956 m_items.push_back (
new Boolean (value));
962 m_items.push_back (
new WString (value));
968 m_items.push_back (
new String (value));
974 m_items.push_back (
new Name (value));
980 m_items.push_back (value);
986 m_items.push_back (value);
990 Array & insert (
int const *begin,
int const *end)
994 m_items.push_back (
new Int (*begin));
1000 Array & insert (
float const *begin,
float const *end)
1002 while (begin != end)
1004 m_items.push_back (
new Float (*begin));
1010 Array & insert (
bool const *begin,
bool const *end)
1012 while (begin != end)
1014 m_items.push_back (
new Boolean (*begin));
1022 while (begin != end)
1024 m_items.push_back (
new WString (*begin));
1032 while (begin != end)
1034 m_items.push_back (
new String (*begin));
1042 while (begin != end)
1044 m_items.push_back (
new Name (*begin));
1052 while (begin != end)
1054 m_items.push_back (*begin);
1062 while (begin != end)
1064 m_items.push_back (begin);
1074 m_items.insert (make_pair (n, static_cast<BaseObject*>(value)));
1082 mutable Dict * m_ptrailer;
1084 map < int, long > m_xrefs;
1085 vector < Dict * > m_dictionaries;
1086 vector < Array * > m_arrays;
1094 void write (ostream & out)
const
1096 out <<
"%PDF-" << m_version;
1098 for (
unsigned int i = 0; i < m_dictionaries.size (); ++i)
1100 m_dictionaries[i]->really_write (out);
1104 long xref_fpos = out.tellp ();
1105 out <<
"xref" << endl;
1106 out <<
"0 " << m_object_count << endl;
1108 char cur_fill = out.fill ();
1111 for (
int i = 0; i < m_object_count; ++i)
1113 map < int, long >::const_iterator iter = m_xrefs.find (i);
1114 if (iter == m_xrefs.end ())
1115 out <<
"0000000000 65535 f " << endl;
1117 out << setw (10) << iter->second <<
" 00000 n " << endl;
1119 out.fill (cur_fill);
1121 m_ptrailer->insert(
"Size", m_object_count);
1122 out <<
"\n\n" <<
"trailer" << endl;
1123 m_ptrailer->write_direct(out);
1126 out <<
"startxref" << endl << xref_fpos << endl <<
"%%EOF";
1139 explicit File (
string const & filename):m_object_count (1), m_ptrailer(0),
1140 m_version (1.7f), m_out (filename.c_str(), ios::out | ios::binary)
1144 explicit File (wstring
const & filename):m_object_count (1), m_ptrailer(0),
1148 m_out.open(filename.c_str(), ios::out | ios::binary);
1150 int len = wcstombs(0, filename.c_str(), 0) +1;
1151 char * tmp =
new char[len];
1152 char const *
const old_loc = setlocale(LC_CTYPE,
"");
1153 wcstombs(tmp, filename.c_str(), len);
1154 setlocale(LC_CTYPE, old_loc);
1155 m_out.open(tmp, ios::out | ios::binary);
1163 m_ptrailer->release ();
1166 for (
unsigned int i = 0; i < m_dictionaries.size (); ++i)
1168 m_dictionaries[i]->release ();
1171 for (
unsigned int i = 0; i < m_arrays.size(); ++i)
1173 m_arrays[i]->release();
1176 for (
unsigned int i = 0; i < m_dictionaries.size (); ++i)
1178 delete m_dictionaries[i];
1181 for (
unsigned int i = 0; i < m_arrays.size(); ++i)
1188 if(m_out.is_open()){
1194 template <
typename T1>
bool get(
Name const & key,
Dict *& value_out)
1196 return m_ptrailer->get<T1> (key, value_out);
1199 template <
typename T1,
typename T2>
bool get(
Name const & key, T2 & value_out)
const
1201 return m_ptrailer->get<T1> (key, value_out);
1207 m_arrays.push_back (retval);
1211 template <
typename T>
1212 Array * newArray (T
const * begin, T
const * end)
1215 m_arrays.push_back (retval);
1221 Dict *retval =
new Dict (
this, m_object_count++);
1222 m_dictionaries.push_back (retval);
1228 Dict *retval =
new Dict (
this, m_object_count++);
1229 m_dictionaries.push_back (retval);
1231 m_ptrailer =
new Dict(
this, 0);
1232 m_ptrailer->insert(n, retval);
1237 Array * Dict::newArray()
const
1239 return m_file->newArray();
1242 Array * Dict::newArray(Name
const & n)
1244 Array * retval = newArray();
1249 template <
typename T>
1250 Array * Dict::newArray(T
const * begin, T
const * end)
const
1252 return m_file->newArray(begin, end);
1255 template <
typename T>
1256 Array * Dict::newArray(Name
const & n, T
const * begin, T
const * end)
1258 Array * retval = newArray(begin, end);
1263 Dict * Dict::newDict()
const
1265 Dict *retval =
new Dict (m_file, m_file->m_object_count++);
1266 m_file->m_dictionaries.push_back (retval);
1270 Dict * Dict::newDict(Name
const & n)
1272 Dict *retval = newDict();
1277 void Dict::write_direct (ostream & out)
const
1281 map < Name, BaseObject * >::const_iterator iter = m_items.begin ();
1282 while (iter != m_items.end ())
1285 iter->first.write (out);
1287 iter->second->write (out);
1291 out << endl <<
">>";
1294 void Dict::really_write (ostream & out)
const
1296 if (m_file->m_xrefs.find (m_id) == m_file->m_xrefs.end ())
1300 long dict_fpos = out.tellp ();
1301 m_file->m_xrefs.insert (make_pair (m_id, dict_fpos));
1302 out << m_id <<
" 0 obj\n";
1310 out <<
"stream" << endl;
1311 char buffer[EZPDF_BUFFER_SIZE];
1312 m_stream->read (buffer,
1313 static_cast < streamsize > (EZPDF_BUFFER_SIZE));
1314 while (m_stream->gcount () > 0)
1316 out.write (buffer, m_stream->gcount ());
1317 m_stream->read (buffer,
1318 static_cast < streamsize >
1319 (EZPDF_BUFFER_SIZE));
1321 out << endl <<
"endstream" << endl;
1332 virtual filter & read(
void*, streamsize) = 0;
1333 virtual filter & write(
void const *, streamsize) = 0;
1334 virtual streamsize gcount()
const = 0;
1335 virtual char const * name()
const = 0;
1340 zlib() : m_reading(
false){
1341 m_zstrm.zalloc = Z_NULL;
1342 m_zstrm.zfree = Z_NULL;
1343 m_zstrm.data_type = Z_ASCII;
1344 m_zstrm.next_out = 0;
1345 m_zstrm.avail_out = 0;
1346 m_zstrm.next_in = 0;
1347 m_zstrm.avail_in = 0;
1348 if(deflateInit(&m_zstrm, Z_BEST_COMPRESSION) != Z_OK){
1354 deflateEnd(&m_zstrm);
1357 filter & read(
void * out, streamsize howmuch) {
1359 char buffer[EZPDF_BUFFER_SIZE];
1363 m_zstrm.next_out = (Bytef*)(&buffer[0]);
1364 m_zstrm.avail_out = EZPDF_BUFFER_SIZE;
1365 rc = deflate(&m_zstrm, Z_FINISH);
1367 int have = EZPDF_BUFFER_SIZE - m_zstrm.avail_out;
1369 m_buf.write(buffer, have);
1371 }
while(rc != Z_STREAM_END);
1375 m_buf.read((
char*)out, howmuch);
1379 filter & write(
void const * in, streamsize howmuch) {
1381 m_zstrm.next_in =
const_cast<Bytef*
>(
static_cast<Bytef const*
>(in));
1382 m_zstrm.avail_in = howmuch;
1384 char buffer[EZPDF_BUFFER_SIZE];
1386 m_zstrm.next_out = (Bytef*)(&buffer[0]);
1387 m_zstrm.avail_out = EZPDF_BUFFER_SIZE;
1389 while(m_zstrm.avail_in > 0){
1390 int rc = deflate(&m_zstrm, Z_NO_FLUSH);
1394 int have = EZPDF_BUFFER_SIZE - m_zstrm.avail_out;
1396 m_buf.write(buffer, have);
1397 m_zstrm.next_out = (Bytef*)(&buffer[0]);
1398 m_zstrm.avail_out = EZPDF_BUFFER_SIZE;
1401 int have = EZPDF_BUFFER_SIZE - m_zstrm.avail_out;
1403 m_buf.write(buffer, have);
1410 streamsize gcount()
const {
1411 return m_buf.gcount();
1414 char const * name()
const {
return "FlateDecode";};
1417 std::stringstream m_buf;
1418 struct z_stream_s m_zstrm;