26 #include "utf_utils.h"
34 #pragma warning(disable : 4244) // conversion warn
41 int const EZPDF_BUFFER_SIZE = 1024*64;
49 unsigned short lebom = 0xfffe;
50 unsigned char const *
const first_byte = (
unsigned char const *
const)&lebom;
51 return *first_byte == 0xfe;
54 void escape_char(ostream & out,
char const c)
56 if(c ==
'\\' || c ==
'(' || c ==
')')
61 using namespace common;
63 void write_string(ostream & out, wstring
const & s)
65 H_UTF16 utf16(s.c_str());
67 out <<
'(' << (char)-2 << (
char)-1;
68 utf16_char
const * next = utf16.encodedText();
70 char const upper = (char)((*next >> 8) & 0xff);
71 escape_char(out, upper);
74 char const lower = (char)(*next & 0xff);
75 escape_char(out, lower);
83 void write_string(ostream & out,
string const & s)
86 char const * next = s.c_str();
88 escape_char(out, *next);
113 virtual void release ()
117 virtual bool managed ()
const
122 virtual void write (ostream & out)
const = 0;
131 void write (ostream & out)
const
133 out << (m_bool ?
"true" :
"false");
153 operator bool ()
const
164 void write (ostream & out)
const
182 Int (
long i):m_int (i)
186 operator int ()
const
188 return static_cast<int>(m_int);
191 operator long ()
const
196 operator size_t ()
const
198 return static_cast<size_t>(m_int);
207 void write (ostream & out)
const
209 out << fixed << setprecision(6) << m_float;
225 Float (
double f):m_float (f)
229 operator float ()
const
231 return static_cast<float>(m_float);
234 operator double ()
const
246 void write (ostream & out)
const
248 out <<
'/' << m_name;
265 Name (
string const &s):m_name (s)
269 Name (
char const * s):m_name (s)
273 bool operator < (
Name const &rhs)
const
275 return m_name < rhs.m_name;
278 bool operator == (
Name const &rhs)
const
280 return m_name == rhs.m_name;
283 bool operator != (
Name const &rhs)
const
285 return m_name != rhs.m_name;
288 operator string ()
const
300 void write (ostream & out)
const
302 write_string(out, m_string);
317 explicit WString (
string const &s):m_string (H_WCS(s.c_str()).encodedText())
321 explicit WString (wstring
const &s):m_string(s)
325 operator wstring ()
const
337 void write (ostream & out)
const
339 write_string(out, m_string);
354 explicit String (
string const &s):m_string (s)
358 operator string ()
const
370 stringstream m_stream;
372 void Font(
Name const & font_name,
double const points) {
373 font_name.write(m_stream);
374 m_stream <<
' ' << points <<
" Tf" << endl;
418 m_stream << g.m_stream.str();
423 m_stream << rhs.m_stream.str();
429 Graphics & Exlicit(
string const & cmd)
431 m_stream.write(cmd.c_str(),
static_cast<streamsize
>(cmd.length()));
436 Graphics & PushGraphicsState() {m_stream <<
'q' << endl;
return *
this;};
437 Graphics & PopGraphicsState() {m_stream <<
'Q' << endl;
return *
this;};
439 Graphics & PenPosition(
double const x,
double const y)
441 m_stream << x <<
' ' << y <<
" m" << endl;
return *
this;
444 Graphics & MovePen(
double const x,
double const y)
446 m_stream << x <<
' ' << y <<
" l" << endl;
return *
this;
449 Graphics & StrokeColor(
double const r,
double const g,
double const b)
451 m_stream << r <<
' ' << g <<
' ' << b <<
" RG" << endl;
return *
this;
454 Graphics & FillColor(
double const r,
double const g,
double const b)
456 m_stream << r <<
' ' << g <<
' ' << b <<
" rg" << endl;
return *
this;
459 Graphics & FillAndStrokeWR() {m_stream <<
"B" << endl;
return *
this;};
460 Graphics & FillAndStrokeEO() {m_stream <<
"B*" << endl;
return *
this;};
461 Graphics & CloseFillAndStrokeWR() {m_stream <<
"b*" << endl;
return *
this;};
462 Graphics & CloseFillAndStrokeEO() {m_stream <<
"b*" << endl;
return *
this;};
463 Graphics & FillWR() {m_stream <<
"f" << endl;
return *
this;};
464 Graphics & FillEO() {m_stream <<
"f*" << endl;
return *
this;};
465 Graphics & CompletePath() {m_stream <<
"h" << endl;
return *
this;};
466 Graphics & Stroke() {m_stream <<
"S" << endl;
return *
this;};
467 Graphics & CompleteAndStroke() {m_stream <<
"s" << endl;
return *
this;};
469 Graphics & BeginText(
double const x,
double const y,
Name const & font_name,
double const points)
471 Font(font_name, points);
472 m_stream <<
"BT " << x <<
' ' << y <<
" Td ";
return *
this;
475 template <
typename T>
476 Graphics & InsertText(T
const & text)
478 write_string(m_stream, text);
479 m_stream <<
" Tj " << endl;
483 Graphics & InsertText(
double const x,
double const y,
string const & text)
485 m_stream << x <<
' ' << y <<
" Td ";
490 Graphics & InsertText(
double const x,
double const y, wstring
const & text)
492 m_stream << x <<
' ' << y <<
" Td ";
499 m_stream <<
"ET" << endl;
return *
this;
502 Graphics & InsertImageRGB(
double left,
double right,
double bottom,
double top,
503 int const w,
int const h,
void const * image)
505 m_stream <<
"q " << right-left <<
" 0 0 " << top-bottom <<
' ' << left
506 <<
' ' << bottom <<
" cm ";
507 m_stream <<
"BI /W " << w <<
" /H " << h <<
" /CS /RGB /BPC 8 ID ";
508 m_stream.write(static_cast<char const*>(image), static_cast<streamsize>(w*h*3));
509 m_stream <<
"EI Q" << endl;
return *
this;
519 stringstream *m_stream;
520 map < Name, BaseObject * >m_items;
522 void *
operator new (
size_t size)
524 return malloc (size);
527 void operator delete (
void *p)
532 void write (ostream & out)
const
534 out << m_id <<
" 0 R";
537 void write_direct (ostream & out)
const;
538 void really_write (ostream & out)
const;
540 bool managed ()
const
553 map < Name, BaseObject * >::iterator iter = m_items.begin ();
554 while (iter != m_items.end ())
556 if (!iter->second->managed ())
557 iter->second->release ();
565 Dict (
File * pdf_file,
int id):m_id (
id), m_file (pdf_file), m_stream (0)
574 Array *newArray ()
const;
576 template <
typename T>
577 Array *newArray (T
const *, T
const *)
const;
578 template <
typename T>
579 Array *newArray (
Name const &, T
const *, T
const *);
580 Dict *newDict ()
const;
583 template <
typename T1>
bool get(
Name const & key,
Array *& value_out)
586 map < Name, BaseObject * >::const_iterator iter = m_items.find (key);
587 if(iter != m_items.end())
591 T1 value =
static_cast<T1
>(iter->second);
601 template <
typename T1>
bool get(
Name const & key,
Dict *& value_out)
604 map < Name, BaseObject * >::const_iterator iter = m_items.find (key);
605 if(iter != m_items.end())
609 T1 value =
static_cast<T1
>(iter->second);
619 template <
typename T1,
typename T2>
bool get(
Name const & key, T2 & value_out)
const
622 map < Name, BaseObject * >::const_iterator iter = m_items.find (key);
623 if(iter != m_items.end())
627 T1
const * value =
static_cast<T1*
>(iter->second);
640 m_stream =
new stringstream(stringstream::binary |
646 char buffer[EZPDF_BUFFER_SIZE];
647 g.m_stream.read (buffer,
648 static_cast < streamsize > (EZPDF_BUFFER_SIZE));
649 while (g.m_stream.gcount () > 0)
651 m_stream->write (buffer, g.m_stream.gcount ());
652 g.m_stream.read (buffer,
653 static_cast < streamsize > (EZPDF_BUFFER_SIZE));
658 Dict * appendStream (
void const *begin,
size_t size)
661 m_stream =
new stringstream(stringstream::binary |
664 m_stream->write (static_cast<char const*>(begin), static_cast<streamsize>(size));
668 int streamSize ()
const
672 retval = m_stream->tellp ();
678 map < Name, BaseObject * >::iterator iter = m_items.find (n);
679 if(iter != m_items.end()){
680 if(!iter->second->managed()){
681 iter->second->release();
690 Dict * insert (
Name const &n,
int value)
694 m_items.insert (make_pair (n, b));
698 Dict * insert (
Name const &n,
float value)
702 m_items.insert (make_pair (n, b));
706 Dict * insert (
Name const &n,
double value)
710 m_items.insert (make_pair (n, b));
714 Dict * insert (
Name const &n,
long value)
718 m_items.insert (make_pair (n, b));
722 Dict * insert (
Name const &n,
size_t value)
726 m_items.insert (make_pair (n, b));
730 Dict * insert (
Name const &n,
bool value)
734 m_items.insert (make_pair (n, b));
742 m_items.insert (make_pair (n, b));
750 m_items.insert (make_pair (n, b));
758 m_items.insert (make_pair (n, b));
765 Dict * d =
const_cast<Dict*
>(value);
766 m_items.insert (make_pair (n, static_cast < BaseObject * >(d)));
775 vector < BaseObject * >m_items;
779 for (
unsigned int i = 0; i < m_items.size (); ++i)
781 if (!m_items[i]->managed ())
783 m_items[i]->release ();
789 void *
operator new (
size_t size)
791 return malloc (size);
794 void operator delete (
void *p)
807 void write (ostream & out)
const
810 if (!m_items.empty ()){
811 m_items[0]->write (out);
812 for (
unsigned int i = 1; i < m_items.size (); ++i)
815 m_items[i]->write (out);
826 bool managed ()
const
840 Array (
int const *begin,
int const *end)
845 Array (
float const *begin,
float const *end)
850 Array (
bool const *begin,
bool const *end)
882 template <
typename T1>
bool get(
unsigned int index,
Dict *& value_out)
885 if(index < m_items.size())
890 T1 value =
static_cast<T1
>(bo);
900 template <
typename T1,
typename T2>
bool get(
unsigned int index, T2 & value_out)
const
903 if(index < m_items.size())
908 T1 * value =
static_cast<T1*
>(bo);
920 return m_items.size ();
923 void remove (
unsigned int const index)
925 if(index < m_items.size()){
927 if(!m_items[index]->managed())
928 m_items[index]->release();
930 m_items.erase(m_items.begin() + index);
934 Array & insert (
int value)
936 m_items.push_back (
new Int (value));
940 Array & insert (
float value)
942 m_items.push_back (
new Float (value));
946 Array & insert (
double value)
948 m_items.push_back (
new Float (value));
952 Array & insert (
bool value)
954 m_items.push_back (
new Boolean (value));
960 m_items.push_back (
new WString (value));
966 m_items.push_back (
new String (value));
972 m_items.push_back (
new Name (value));
978 m_items.push_back (value);
984 m_items.push_back (value);
988 Array & insert (
int const *begin,
int const *end)
992 m_items.push_back (
new Int (*begin));
998 Array & insert (
float const *begin,
float const *end)
1000 while (begin != end)
1002 m_items.push_back (
new Float (*begin));
1008 Array & insert (
bool const *begin,
bool const *end)
1010 while (begin != end)
1012 m_items.push_back (
new Boolean (*begin));
1020 while (begin != end)
1022 m_items.push_back (
new WString (*begin));
1030 while (begin != end)
1032 m_items.push_back (
new String (*begin));
1040 while (begin != end)
1042 m_items.push_back (
new Name (*begin));
1050 while (begin != end)
1052 m_items.push_back (*begin);
1060 while (begin != end)
1062 m_items.push_back (begin);
1072 m_items.insert (make_pair (n, static_cast<BaseObject*>(value)));
1080 mutable Dict * m_ptrailer;
1082 map < int, long > m_xrefs;
1083 vector < Dict * > m_dictionaries;
1084 vector < Array * > m_arrays;
1092 void write (ostream & out)
const
1094 out <<
"%PDF-" << m_version;
1096 for (
unsigned int i = 0; i < m_dictionaries.size (); ++i)
1098 m_dictionaries[i]->really_write (out);
1102 long xref_fpos = out.tellp ();
1103 out <<
"xref" << endl;
1104 out <<
"0 " << m_object_count << endl;
1106 char cur_fill = out.fill ();
1109 for (
int i = 0; i < m_object_count; ++i)
1111 map < int, long >::const_iterator iter = m_xrefs.find (i);
1112 if (iter == m_xrefs.end ())
1113 out <<
"0000000000 65535 f " << endl;
1115 out << setw (10) << iter->second <<
" 00000 n " << endl;
1117 out.fill (cur_fill);
1119 m_ptrailer->insert(
"Size", m_object_count);
1120 out <<
"\n\n" <<
"trailer" << endl;
1121 m_ptrailer->write_direct(out);
1124 out <<
"startxref" << endl << xref_fpos << endl <<
"%%EOF";
1137 explicit File (
string const & filename):m_object_count (1), m_ptrailer(0),
1138 m_version (1.7f), m_out (filename.c_str(), ios::out | ios::binary)
1142 explicit File (wstring
const & filename):m_object_count (1), m_ptrailer(0),
1146 m_out.open(filename.c_str(), ios::out | ios::binary);
1148 int len = wcstombs(0, filename.c_str(), 0) +1;
1149 char * tmp =
new char[len];
1150 char const *
const old_loc = setlocale(LC_CTYPE,
"");
1151 wcstombs(tmp, filename.c_str(), len);
1152 setlocale(LC_CTYPE, old_loc);
1153 m_out.open(tmp, ios::out | ios::binary);
1161 m_ptrailer->release ();
1164 for (
unsigned int i = 0; i < m_dictionaries.size (); ++i)
1166 m_dictionaries[i]->release ();
1169 for (
unsigned int i = 0; i < m_arrays.size(); ++i)
1171 m_arrays[i]->release();
1174 for (
unsigned int i = 0; i < m_dictionaries.size (); ++i)
1176 delete m_dictionaries[i];
1179 for (
unsigned int i = 0; i < m_arrays.size(); ++i)
1186 if(m_out.is_open()){
1192 template <
typename T1>
bool get(
Name const & key,
Dict *& value_out)
1194 return m_ptrailer->get<T1> (key, value_out);
1197 template <
typename T1,
typename T2>
bool get(
Name const & key, T2 & value_out)
const
1199 return m_ptrailer->get<T1> (key, value_out);
1205 m_arrays.push_back (retval);
1209 template <
typename T>
1210 Array * newArray (T
const * begin, T
const * end)
1213 m_arrays.push_back (retval);
1219 Dict *retval =
new Dict (
this, m_object_count++);
1220 m_dictionaries.push_back (retval);
1226 Dict *retval =
new Dict (
this, m_object_count++);
1227 m_dictionaries.push_back (retval);
1229 m_ptrailer =
new Dict(
this, 0);
1230 m_ptrailer->insert(n, retval);
1235 Array * Dict::newArray()
const
1237 return m_file->newArray();
1240 Array * Dict::newArray(Name
const & n)
1242 Array * retval = newArray();
1247 template <
typename T>
1248 Array * Dict::newArray(T
const * begin, T
const * end)
const
1250 return m_file->newArray(begin, end);
1253 template <
typename T>
1254 Array * Dict::newArray(Name
const & n, T
const * begin, T
const * end)
1256 Array * retval = newArray(begin, end);
1261 Dict * Dict::newDict()
const
1263 Dict *retval =
new Dict (m_file, m_file->m_object_count++);
1264 m_file->m_dictionaries.push_back (retval);
1268 Dict * Dict::newDict(Name
const & n)
1270 Dict *retval = newDict();
1275 void Dict::write_direct (ostream & out)
const
1279 map < Name, BaseObject * >::const_iterator iter = m_items.begin ();
1280 while (iter != m_items.end ())
1283 iter->first.write (out);
1285 iter->second->write (out);
1289 out << endl <<
">>";
1292 void Dict::really_write (ostream & out)
const
1294 if (m_file->m_xrefs.find (m_id) == m_file->m_xrefs.end ())
1298 long dict_fpos = out.tellp ();
1299 m_file->m_xrefs.insert (make_pair (m_id, dict_fpos));
1300 out << m_id <<
" 0 obj\n";
1308 out <<
"stream" << endl;
1309 char buffer[EZPDF_BUFFER_SIZE];
1310 m_stream->read (buffer,
1311 static_cast < streamsize > (EZPDF_BUFFER_SIZE));
1312 while (m_stream->gcount () > 0)
1314 out.write (buffer, m_stream->gcount ());
1315 m_stream->read (buffer,
1316 static_cast < streamsize >
1317 (EZPDF_BUFFER_SIZE));
1319 out << endl <<
"endstream" << endl;
1330 virtual filter & read(
void*, streamsize) = 0;
1331 virtual filter & write(
void const *, streamsize) = 0;
1332 virtual streamsize gcount()
const = 0;
1333 virtual char const * name()
const = 0;
1338 zlib() : m_reading(
false){
1339 m_zstrm.zalloc = Z_NULL;
1340 m_zstrm.zfree = Z_NULL;
1341 m_zstrm.data_type = Z_ASCII;
1342 m_zstrm.next_out = 0;
1343 m_zstrm.avail_out = 0;
1344 m_zstrm.next_in = 0;
1345 m_zstrm.avail_in = 0;
1346 if(deflateInit(&m_zstrm, Z_BEST_COMPRESSION) != Z_OK){
1352 deflateEnd(&m_zstrm);
1355 filter & read(
void * out, streamsize howmuch) {
1357 char buffer[EZPDF_BUFFER_SIZE];
1361 m_zstrm.next_out = (Bytef*)(&buffer[0]);
1362 m_zstrm.avail_out = EZPDF_BUFFER_SIZE;
1363 rc = deflate(&m_zstrm, Z_FINISH);
1365 int have = EZPDF_BUFFER_SIZE - m_zstrm.avail_out;
1367 m_buf.write(buffer, have);
1369 }
while(rc != Z_STREAM_END);
1373 m_buf.read((
char*)out, howmuch);
1377 filter & write(
void const * in, streamsize howmuch) {
1379 m_zstrm.next_in =
const_cast<Bytef*
>(
static_cast<Bytef const*
>(in));
1380 m_zstrm.avail_in = howmuch;
1382 char buffer[EZPDF_BUFFER_SIZE];
1384 m_zstrm.next_out = (Bytef*)(&buffer[0]);
1385 m_zstrm.avail_out = EZPDF_BUFFER_SIZE;
1387 while(m_zstrm.avail_in > 0){
1388 int rc = deflate(&m_zstrm, Z_NO_FLUSH);
1392 int have = EZPDF_BUFFER_SIZE - m_zstrm.avail_out;
1394 m_buf.write(buffer, have);
1395 m_zstrm.next_out = (Bytef*)(&buffer[0]);
1396 m_zstrm.avail_out = EZPDF_BUFFER_SIZE;
1399 int have = EZPDF_BUFFER_SIZE - m_zstrm.avail_out;
1401 m_buf.write(buffer, have);
1408 streamsize gcount()
const {
1409 return m_buf.gcount();
1412 char const * name()
const {
return "FlateDecode";};
1415 std::stringstream m_buf;
1416 struct z_stream_s m_zstrm;