26 #include "utf_utils.h"
37 int const EZPDF_BUFFER_SIZE = 1024*64;
45 unsigned short lebom = 0xfffe;
46 unsigned char const *
const first_byte = (
unsigned char const *
const)&lebom;
47 return *first_byte == 0xfe;
50 void escape_char(ostream & out,
char const c)
52 if(c ==
'\\' || c ==
'(' || c ==
')')
57 using namespace common;
59 void write_string(ostream & out, wstring
const & s)
61 H_UTF16 utf16(s.c_str());
63 out <<
'(' << (char)-2 << (
char)-1;
64 utf16_char
const * next = utf16.encodedText();
66 char const upper = (char)((*next >> 8) & 0xff);
67 escape_char(out, upper);
70 char const lower = (char)(*next & 0xff);
71 escape_char(out, lower);
79 void write_string(ostream & out,
string const & s)
82 char const * next = s.c_str();
84 escape_char(out, *next);
109 virtual void release ()
113 virtual bool managed ()
const
118 virtual void write (ostream & out)
const = 0;
127 void write (ostream & out)
const
129 out << (m_bool ?
"true" :
"false");
149 operator bool ()
const
160 void write (ostream & out)
const
178 Int (
long i):m_int (i)
182 operator int ()
const
184 return static_cast<int>(m_int);
187 operator long ()
const
192 operator size_t ()
const
194 return static_cast<size_t>(m_int);
203 void write (ostream & out)
const
205 out << fixed << setprecision(6) << m_float;
221 Float (
double f):m_float (f)
225 operator float ()
const
227 return static_cast<float>(m_float);
230 operator double ()
const
242 void write (ostream & out)
const
244 out <<
'/' << m_name;
261 Name (
string const &s):m_name (s)
265 Name (
char const * s):m_name (s)
269 bool operator < (
Name const &rhs)
const
271 return m_name < rhs.m_name;
274 bool operator == (
Name const &rhs)
const
276 return m_name == rhs.m_name;
279 bool operator != (
Name const &rhs)
const
281 return m_name != rhs.m_name;
284 operator string ()
const
296 void write (ostream & out)
const
298 write_string(out, m_string);
313 explicit WString (
string const &s):m_string (H_WCS(s.c_str()).encodedText())
317 explicit WString (wstring
const &s):m_string(s)
321 operator wstring ()
const
333 void write (ostream & out)
const
335 write_string(out, m_string);
350 explicit String (
string const &s):m_string (s)
354 operator string ()
const
366 stringstream m_stream;
368 void Font(
Name const & font_name,
double const points) {
369 font_name.write(m_stream);
370 m_stream <<
' ' << points <<
" Tf" << endl;
414 m_stream << g.m_stream.str();
419 m_stream << rhs.m_stream.str();
425 Graphics & Exlicit(
string const & cmd)
427 m_stream.write(cmd.c_str(),
static_cast<streamsize
>(cmd.length()));
432 Graphics & PushGraphicsState() {m_stream <<
'q' << endl;
return *
this;};
433 Graphics & PopGraphicsState() {m_stream <<
'Q' << endl;
return *
this;};
435 Graphics & PenPosition(
double const x,
double const y)
437 m_stream << x <<
' ' << y <<
" m" << endl;
return *
this;
440 Graphics & MovePen(
double const x,
double const y)
442 m_stream << x <<
' ' << y <<
" l" << endl;
return *
this;
445 Graphics & StrokeColor(
double const r,
double const g,
double const b)
447 m_stream << r <<
' ' << g <<
' ' << b <<
" RG" << endl;
return *
this;
450 Graphics & FillColor(
double const r,
double const g,
double const b)
452 m_stream << r <<
' ' << g <<
' ' << b <<
" rg" << endl;
return *
this;
455 Graphics & FillAndStrokeWR() {m_stream <<
"B" << endl;
return *
this;};
456 Graphics & FillAndStrokeEO() {m_stream <<
"B*" << endl;
return *
this;};
457 Graphics & CloseFillAndStrokeWR() {m_stream <<
"b*" << endl;
return *
this;};
458 Graphics & CloseFillAndStrokeEO() {m_stream <<
"b*" << endl;
return *
this;};
459 Graphics & FillWR() {m_stream <<
"f" << endl;
return *
this;};
460 Graphics & FillEO() {m_stream <<
"f*" << endl;
return *
this;};
461 Graphics & CompletePath() {m_stream <<
"h" << endl;
return *
this;};
462 Graphics & Stroke() {m_stream <<
"S" << endl;
return *
this;};
463 Graphics & CompleteAndStroke() {m_stream <<
"s" << endl;
return *
this;};
465 Graphics & BeginText(
double const x,
double const y,
Name const & font_name,
double const points)
467 Font(font_name, points);
468 m_stream <<
"BT " << x <<
' ' << y <<
" Td ";
return *
this;
471 template <
typename T>
472 Graphics & InsertText(T
const & text)
474 write_string(m_stream, text);
475 m_stream <<
" Tj " << endl;
479 Graphics & InsertText(
double const x,
double const y,
string const & text)
481 m_stream << x <<
' ' << y <<
" Td ";
486 Graphics & InsertText(
double const x,
double const y, wstring
const & text)
488 m_stream << x <<
' ' << y <<
" Td ";
495 m_stream <<
"ET" << endl;
return *
this;
498 Graphics & InsertImageRGB(
double left,
double right,
double bottom,
double top,
499 int const w,
int const h,
void const * image)
501 m_stream <<
"q " << right-left <<
" 0 0 " << top-bottom <<
' ' << left
502 <<
' ' << bottom <<
" cm ";
503 m_stream <<
"BI /W " << w <<
" /H " << h <<
" /CS /RGB /BPC 8 ID ";
504 m_stream.write(static_cast<char const*>(image), static_cast<streamsize>(w*h*3));
505 m_stream <<
"EI Q" << endl;
return *
this;
515 stringstream *m_stream;
516 map < Name, BaseObject * >m_items;
518 void *
operator new (
size_t size)
520 return malloc (size);
523 void operator delete (
void *p)
528 void write (ostream & out)
const
530 out << m_id <<
" 0 R";
533 void write_direct (ostream & out)
const;
534 void really_write (ostream & out)
const;
536 bool managed ()
const
549 map < Name, BaseObject * >::iterator iter = m_items.begin ();
550 while (iter != m_items.end ())
552 if (!iter->second->managed ())
553 iter->second->release ();
561 Dict (
File * pdf_file,
int id):m_id (
id), m_file (pdf_file), m_stream (0)
570 Array *newArray ()
const;
572 template <
typename T>
573 Array *newArray (T
const *, T
const *)
const;
574 template <
typename T>
575 Array *newArray (
Name const &, T
const *, T
const *);
576 Dict *newDict ()
const;
579 template <
typename T1>
bool get(
Name const & key,
Array *& value_out)
582 map < Name, BaseObject * >::const_iterator iter = m_items.find (key);
583 if(iter != m_items.end())
587 T1 value =
static_cast<T1
>(iter->second);
597 template <
typename T1>
bool get(
Name const & key,
Dict *& value_out)
600 map < Name, BaseObject * >::const_iterator iter = m_items.find (key);
601 if(iter != m_items.end())
605 T1 value =
static_cast<T1
>(iter->second);
615 template <
typename T1,
typename T2>
bool get(
Name const & key, T2 & value_out)
const
618 map < Name, BaseObject * >::const_iterator iter = m_items.find (key);
619 if(iter != m_items.end())
623 T1
const * value =
static_cast<T1*
>(iter->second);
636 m_stream =
new stringstream(stringstream::binary |
642 char buffer[EZPDF_BUFFER_SIZE];
643 g.m_stream.read (buffer,
644 static_cast < streamsize > (EZPDF_BUFFER_SIZE));
645 while (g.m_stream.gcount () > 0)
647 m_stream->write (buffer, g.m_stream.gcount ());
648 g.m_stream.read (buffer,
649 static_cast < streamsize > (EZPDF_BUFFER_SIZE));
654 Dict * appendStream (
void const *begin,
size_t size)
657 m_stream =
new stringstream(stringstream::binary |
660 m_stream->write (static_cast<char const*>(begin), static_cast<streamsize>(size));
664 int streamSize ()
const
668 retval = m_stream->tellp ();
674 map < Name, BaseObject * >::iterator iter = m_items.find (n);
675 if(iter != m_items.end()){
676 if(!iter->second->managed()){
677 iter->second->release();
686 Dict * insert (
Name const &n,
int value)
690 m_items.insert (make_pair (n, b));
694 Dict * insert (
Name const &n,
float value)
698 m_items.insert (make_pair (n, b));
702 Dict * insert (
Name const &n,
double value)
706 m_items.insert (make_pair (n, b));
710 Dict * insert (
Name const &n,
long value)
714 m_items.insert (make_pair (n, b));
718 Dict * insert (
Name const &n,
size_t value)
722 m_items.insert (make_pair (n, b));
726 Dict * insert (
Name const &n,
bool value)
730 m_items.insert (make_pair (n, b));
738 m_items.insert (make_pair (n, b));
746 m_items.insert (make_pair (n, b));
754 m_items.insert (make_pair (n, b));
761 Dict * d =
const_cast<Dict*
>(value);
762 m_items.insert (make_pair (n, static_cast < BaseObject * >(d)));
771 vector < BaseObject * >m_items;
775 for (
unsigned int i = 0; i < m_items.size (); ++i)
777 if (!m_items[i]->managed ())
779 m_items[i]->release ();
785 void *
operator new (
size_t size)
787 return malloc (size);
790 void operator delete (
void *p)
803 void write (ostream & out)
const
806 if (!m_items.empty ()){
807 m_items[0]->write (out);
808 for (
unsigned int i = 1; i < m_items.size (); ++i)
811 m_items[i]->write (out);
822 bool managed ()
const
836 Array (
int const *begin,
int const *end)
841 Array (
float const *begin,
float const *end)
846 Array (
bool const *begin,
bool const *end)
878 template <
typename T1>
bool get(
unsigned int index,
Dict *& value_out)
881 if(index < m_items.size())
886 T1 value =
static_cast<T1
>(bo);
896 template <
typename T1,
typename T2>
bool get(
unsigned int index, T2 & value_out)
const
899 if(index < m_items.size())
904 T1 * value =
static_cast<T1*
>(bo);
916 return m_items.size ();
919 void remove (
unsigned int const index)
921 if(index < m_items.size()){
923 if(!m_items[index]->managed())
924 m_items[index]->release();
926 m_items.erase(m_items.begin() + index);
930 Array & insert (
int value)
932 m_items.push_back (
new Int (value));
936 Array & insert (
float value)
938 m_items.push_back (
new Float (value));
942 Array & insert (
double value)
944 m_items.push_back (
new Float (value));
948 Array & insert (
bool value)
950 m_items.push_back (
new Boolean (value));
956 m_items.push_back (
new WString (value));
962 m_items.push_back (
new String (value));
968 m_items.push_back (
new Name (value));
974 m_items.push_back (value);
980 m_items.push_back (value);
984 Array & insert (
int const *begin,
int const *end)
988 m_items.push_back (
new Int (*begin));
994 Array & insert (
float const *begin,
float const *end)
998 m_items.push_back (
new Float (*begin));
1004 Array & insert (
bool const *begin,
bool const *end)
1006 while (begin != end)
1008 m_items.push_back (
new Boolean (*begin));
1016 while (begin != end)
1018 m_items.push_back (
new WString (*begin));
1026 while (begin != end)
1028 m_items.push_back (
new String (*begin));
1036 while (begin != end)
1038 m_items.push_back (
new Name (*begin));
1046 while (begin != end)
1048 m_items.push_back (*begin);
1056 while (begin != end)
1058 m_items.push_back (begin);
1068 m_items.insert (make_pair (n, static_cast<BaseObject*>(value)));
1076 mutable Dict * m_ptrailer;
1078 map < int, long > m_xrefs;
1079 vector < Dict * > m_dictionaries;
1080 vector < Array * > m_arrays;
1088 void write (ostream & out)
const
1090 out <<
"%PDF-" << m_version;
1092 for (
unsigned int i = 0; i < m_dictionaries.size (); ++i)
1094 m_dictionaries[i]->really_write (out);
1098 long xref_fpos = out.tellp ();
1099 out <<
"xref" << endl;
1100 out <<
"0 " << m_object_count << endl;
1102 char cur_fill = out.fill ();
1105 for (
int i = 0; i < m_object_count; ++i)
1107 map < int, long >::const_iterator iter = m_xrefs.find (i);
1108 if (iter == m_xrefs.end ())
1109 out <<
"0000000000 65535 f " << endl;
1111 out << setw (10) << iter->second <<
" 00000 n " << endl;
1113 out.fill (cur_fill);
1115 m_ptrailer->insert(
"Size", m_object_count);
1116 out <<
"\n\n" <<
"trailer" << endl;
1117 m_ptrailer->write_direct(out);
1120 out <<
"startxref" << endl << xref_fpos << endl <<
"%%EOF";
1133 explicit File (
string const & filename):m_object_count (1), m_ptrailer(0),
1134 m_version (1.7f), m_out (filename.c_str(), ios::out | ios::binary)
1138 explicit File (wstring
const & filename):m_object_count (1), m_ptrailer(0),
1142 m_out.open(filename.c_str(), ios::out | ios::binary);
1144 int len = wcstombs(0, filename.c_str(), 0) +1;
1145 char * tmp =
new char[len];
1146 char const *
const old_loc = setlocale(LC_CTYPE,
"");
1147 wcstombs(tmp, filename.c_str(), len);
1148 setlocale(LC_CTYPE, old_loc);
1149 m_out.open(tmp, ios::out | ios::binary);
1157 m_ptrailer->release ();
1160 for (
unsigned int i = 0; i < m_dictionaries.size (); ++i)
1162 m_dictionaries[i]->release ();
1165 for (
unsigned int i = 0; i < m_arrays.size(); ++i)
1167 m_arrays[i]->release();
1170 for (
unsigned int i = 0; i < m_dictionaries.size (); ++i)
1172 delete m_dictionaries[i];
1175 for (
unsigned int i = 0; i < m_arrays.size(); ++i)
1182 if(m_out.is_open()){
1188 template <
typename T1>
bool get(
Name const & key,
Dict *& value_out)
1190 return m_ptrailer->get<T1> (key, value_out);
1193 template <
typename T1,
typename T2>
bool get(
Name const & key, T2 & value_out)
const
1195 return m_ptrailer->get<T1> (key, value_out);
1201 m_arrays.push_back (retval);
1205 template <
typename T>
1206 Array * newArray (T
const * begin, T
const * end)
1209 m_arrays.push_back (retval);
1215 Dict *retval =
new Dict (
this, m_object_count++);
1216 m_dictionaries.push_back (retval);
1222 Dict *retval =
new Dict (
this, m_object_count++);
1223 m_dictionaries.push_back (retval);
1225 m_ptrailer =
new Dict(
this, 0);
1226 m_ptrailer->insert(n, retval);
1231 Array * Dict::newArray()
const
1233 return m_file->newArray();
1236 Array * Dict::newArray(Name
const & n)
1238 Array * retval = newArray();
1243 template <
typename T>
1244 Array * Dict::newArray(T
const * begin, T
const * end)
const
1246 return m_file->newArray(begin, end);
1249 template <
typename T>
1250 Array * Dict::newArray(Name
const & n, T
const * begin, T
const * end)
1252 Array * retval = newArray(begin, end);
1257 Dict * Dict::newDict()
const
1259 Dict *retval =
new Dict (m_file, m_file->m_object_count++);
1260 m_file->m_dictionaries.push_back (retval);
1264 Dict * Dict::newDict(Name
const & n)
1266 Dict *retval = newDict();
1271 void Dict::write_direct (ostream & out)
const
1275 map < Name, BaseObject * >::const_iterator iter = m_items.begin ();
1276 while (iter != m_items.end ())
1279 iter->first.write (out);
1281 iter->second->write (out);
1285 out << endl <<
">>";
1288 void Dict::really_write (ostream & out)
const
1290 if (m_file->m_xrefs.find (m_id) == m_file->m_xrefs.end ())
1294 long dict_fpos = out.tellp ();
1295 m_file->m_xrefs.insert (make_pair (m_id, dict_fpos));
1296 out << m_id <<
" 0 obj\n";
1304 out <<
"stream" << endl;
1305 char buffer[EZPDF_BUFFER_SIZE];
1306 m_stream->read (buffer,
1307 static_cast < streamsize > (EZPDF_BUFFER_SIZE));
1308 while (m_stream->gcount () > 0)
1310 out.write (buffer, m_stream->gcount ());
1311 m_stream->read (buffer,
1312 static_cast < streamsize >
1313 (EZPDF_BUFFER_SIZE));
1315 out << endl <<
"endstream" << endl;
1326 virtual filter & read(
void*, streamsize) = 0;
1327 virtual filter & write(
void const *, streamsize) = 0;
1328 virtual streamsize gcount()
const = 0;
1329 virtual char const * name()
const = 0;
1334 zlib() : m_reading(
false){
1335 m_zstrm.zalloc = Z_NULL;
1336 m_zstrm.zfree = Z_NULL;
1337 m_zstrm.data_type = Z_ASCII;
1338 m_zstrm.next_out = 0;
1339 m_zstrm.avail_out = 0;
1340 m_zstrm.next_in = 0;
1341 m_zstrm.avail_in = 0;
1342 if(deflateInit(&m_zstrm, Z_BEST_COMPRESSION) != Z_OK){
1348 deflateEnd(&m_zstrm);
1351 filter & read(
void * out, streamsize howmuch) {
1353 char buffer[EZPDF_BUFFER_SIZE];
1357 m_zstrm.next_out = (Bytef*)(&buffer[0]);
1358 m_zstrm.avail_out = EZPDF_BUFFER_SIZE;
1359 rc = deflate(&m_zstrm, Z_FINISH);
1361 int have = EZPDF_BUFFER_SIZE - m_zstrm.avail_out;
1363 m_buf.write(buffer, have);
1365 }
while(rc != Z_STREAM_END);
1369 m_buf.read((
char*)out, howmuch);
1373 filter & write(
void const * in, streamsize howmuch) {
1375 m_zstrm.next_in =
const_cast<Bytef*
>(
static_cast<Bytef const*
>(in));
1376 m_zstrm.avail_in = howmuch;
1378 char buffer[EZPDF_BUFFER_SIZE];
1380 m_zstrm.next_out = (Bytef*)(&buffer[0]);
1381 m_zstrm.avail_out = EZPDF_BUFFER_SIZE;
1383 while(m_zstrm.avail_in > 0){
1384 int rc = deflate(&m_zstrm, Z_NO_FLUSH);
1388 int have = EZPDF_BUFFER_SIZE - m_zstrm.avail_out;
1390 m_buf.write(buffer, have);
1391 m_zstrm.next_out = (Bytef*)(&buffer[0]);
1392 m_zstrm.avail_out = EZPDF_BUFFER_SIZE;
1395 int have = EZPDF_BUFFER_SIZE - m_zstrm.avail_out;
1397 m_buf.write(buffer, have);
1404 streamsize gcount()
const {
1405 return m_buf.gcount();
1408 char const * name()
const {
return "FlateDecode";};
1411 std::stringstream m_buf;
1412 struct z_stream_s m_zstrm;