/// // Copyright (C) 2002 - 2004, Fredrik Arnerup & Rasmus Kaj, See COPYING /// #include "psstream.hh" #include // max? #include xml2ps::PsStream::PsStream(const int& out_width, const int& out_height) : page_no_(0), width_max(out_width), height_max(out_height) { // There is no page #0. page_size.push_back(std::make_pair(0, 0)); } xml2ps::PsStream::~PsStream() {} namespace xml2ps { void PsStream::newPage(const int& width, const int& height) { ++page_no_; split(); page_size.push_back(std::make_pair(width, height)); width_max=std::max(width_max, width); height_max=std::max(height_max, height); } void PsStream::require_font(const std::string &fontname) { require_fonts.insert(fontname); } void PsStream::include_font(const std::string &fontname) // can't include yet { include_fonts.insert(fontname); } } namespace { // local typedef std::set FontSet; /** Write the comments block that starts a postscript file. */ void psComments(std::ostream& out, unsigned pages, const std::string& title, float width, float height, const FontSet& require_fonts, const FontSet& include_fonts) { out << "%!PS-Adobe-3.0\n" << "%%Creator: xml2ps by rasmus@kaj.se\n" << "%%LanguageLevel: 2\n" << "%%Pages: " << pages << '\n' << "%%BoundingBox: 0 0 " << width << ' ' << height << '\n'; /// \todo split font comments into several lines, if necessary. if(!require_fonts.empty()) { out << "%%DocumentNeededResources: font"; for(FontSet::const_iterator i=require_fonts.begin(); i!=require_fonts.end(); i++) out << ' ' << *i; out << '\n'; } if(!include_fonts.empty()) { out << "%%DocumentSuppliedResources: font"; for(FontSet::const_iterator i=include_fonts.begin(); i!=include_fonts.end(); i++) out << ' ' << *i; out << '\n'; } out << "%%EndComments\n\n"; } /** Write the postscript setup block for xml2ps. */ void psSetup(std::ostream& out, const FontSet& require_fonts) { out << "%%BeginSetup\n"; /// \todo respect include_fonts for(FontSet::const_iterator i=require_fonts.begin(); i!=require_fonts.end(); i++) out << "%%IncludeResource: font " << *i << '\n'; out << "0 setlinewidth\n" << "%%EndSetup\n\n"; } } void xml2ps::PsStream::psProlog(std::ostream& out) { out << "/S { show } bind def\n" << "/GS { glyphshow } bind def\n" << "/M { moveto } bind def\n" << "/WS { 0 rmoveto } bind def\n" << "/F { findfont exch scalefont setfont } bind def\n" << "/UFROM { currentpoint 3 -1 roll add } bind def\n" << "/UTO { 4 2 roll currentpoint 2 copy 6 4 roll moveto\n" << " 5 -1 roll add lineto 3 -1 roll setlinewidth stroke moveto" << "} bind def\n\n"; } void xml2ps::PsStream::merge(std::ostream& out) const { psComments(out, page_no_, "An xml2ps document", width_max, height_max, require_fonts, include_fonts); out << "%%BeginProlog\n"; psProlog(out); out << "%%EndProlog\n\n"; psSetup(out, require_fonts); for(int p = 1; p <= page_no_; ++p) { out << "%%Page: " << p << ' ' << p << '\n' << "%%PageBoundingBox: 0 0 " << page_size[p].first << ' ' << page_size[p].second << '\n' << "gsave\n"; PagedStream::appendPage(p, out); out << "showpage\n" << "grestore\n"; } out << "%%Trailer\n" << "%%EOF" << std::endl; } void xml2ps::PsStream::pageEps(unsigned page_no, std::ostream& out) { psComments(out, 1, "An xml2ps page", page_size[page_no].first, page_size[page_no].second, require_fonts, include_fonts); psProlog(out); psSetup(out, require_fonts); out << "%%Page: \"" << page_no << "\" 1\n"; PagedStream::appendPage(page_no, out); out << "showpage\n" << "%%Trailer\n" << "%%EOF" << std::endl; }