1 // Copyright (C) 2000-2007, Luca Padovani <padovani@sti.uniurb.it>.
2 //
3 // This file is part of GtkMathView, a flexible, high-quality rendering
4 // engine for MathML documents.
5 //
6 // GtkMathView is free software; you can redistribute it and/or modify it
7 // under the terms of the GNU Lesser General Public License as published
8 // by the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // GtkMathView is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19 #include <config.h>
20 #include <iostream>
21 #include <sstream>
22 #include <ctime>
23
24 #include "PS_StreamRenderingContext.hh"
25 #include "String.hh"
26 #include "FontDataBase.hh"
27
PS_StreamRenderingContext(const SmartPtr<AbstractLogger> & logger,std::ostream & os,SmartPtr<FontDataBase> fDb)28 PS_StreamRenderingContext::PS_StreamRenderingContext(const SmartPtr<AbstractLogger>& logger,
29 std::ostream& os,
30 SmartPtr<FontDataBase> fDb)
31 : PS_RenderingContext(logger), output(os), fontDb(fDb)
32 { }
33
~PS_StreamRenderingContext()34 PS_StreamRenderingContext::~PS_StreamRenderingContext()
35 { }
36
37 /*
38 String
39 PS_StreamRenderingContext::getId(const SmartPtr<Element>& elem) const
40 { return ""; }
41 */
42
43 void
documentStart(const scaled & x,const scaled & y,const BoundingBox & bbox,const char * name)44 PS_StreamRenderingContext::documentStart(const scaled& x, const scaled& y,
45 const BoundingBox& bbox, const char* name)
46 {
47 time_t curTime = time(NULL);
48 std::ostringstream appName;
49 appName << "MathML to PostScript - written by Luca Padovani & Nicola Rossi";
50
51 header << "%!PS-Adobe-3.0 EPSF-3.0" << std::endl;
52 header << "%%BoundingBox: " << PS_RenderingContext::toPS(x) << " "
53 << PS_RenderingContext::toPS(y) << " "
54 << toPS(bbox.width) << " "
55 << toPS(bbox.verticalExtent()) << std::endl
56 << "%%Creator: " << appName.str() << std::endl
57 << "%%CreationDate: " << asctime(localtime(&curTime))
58 << "%%EndComments" << std::endl
59 << "%%Version: v" << VERSION << std::endl
60 << "%%Pages: 1" << std::endl
61 << "%%Title: " << "\"" << name << "\"" << std::endl << std::endl;
62 }
63
64 void
documentEnd(void)65 PS_StreamRenderingContext::documentEnd(void)
66 {
67 output << header.str();
68 fontDb->dumpFontTable(output);
69 output << std::endl;
70 output << body.str();
71 output << "showpage" << std::endl;
72 output << "%%Trailer" << std::endl;
73 output << "%%EOF" << std::endl;
74 }
75
76 void
setGraphicsContext(const RGBColor & strokeColor,const scaled & strokeWidth)77 PS_StreamRenderingContext::setGraphicsContext(const RGBColor& strokeColor,
78 const scaled& strokeWidth)
79 {
80 body << strokeColor.red / 255.0 << " "
81 << strokeColor.green / 255.0 << " "
82 << strokeColor.blue / 255.0
83 << " setrgbcolor" << std::endl;
84 body << PS_RenderingContext::toPS(strokeWidth)
85 << " setlinewidth" << std::endl;
86 }
87
88 void
rect(const scaled & x,const scaled & y,const scaled & width,const scaled & height,const RGBColor & fillColor,const RGBColor & strokeColor,const scaled & strokeWidth)89 PS_StreamRenderingContext::rect(const scaled& x, const scaled& y,
90 const scaled& width, const scaled& height,
91 const RGBColor& fillColor, const RGBColor& strokeColor,
92 const scaled& strokeWidth)
93 {
94 setGraphicsContext(strokeColor, strokeWidth);
95
96 body << "newpath" << std::endl;
97 body << PS_RenderingContext::toPS(x) << " "
98 << PS_RenderingContext::toPS(y)
99 << " moveto" << std::endl;
100 body << PS_RenderingContext::toPS(width) << " "
101 << 0.0
102 << " rlineto" << std::endl;
103 body << 0.0 << " "
104 << -(PS_RenderingContext::toPS(height))
105 << " rlineto" << std::endl;
106 body << -(PS_RenderingContext::toPS(width)) << " "
107 << 0.0
108 << " rlineto" << std::endl;
109 body << "closepath" << std::endl;
110 body << fillColor.red / 255.0 << " "
111 << fillColor.green / 255.0 << " "
112 << fillColor.blue / 255.0 << " "
113 << "setrgbcolor" << " fill" << std::endl;
114 body << "stroke" << std::endl;
115 }
116
117 void
text(const scaled & x,const scaled & y,const String & family,const scaled & size,const RGBColor & fillColor,const RGBColor & strokeColor,const scaled & strokeWidth,const String & content)118 PS_StreamRenderingContext::text(const scaled& x, const scaled& y,
119 const String& family, const scaled& size,
120 const RGBColor& fillColor, const RGBColor& strokeColor,
121 const scaled& strokeWidth, const String& content)
122 {
123 int familyId = fontDb->getFontId(family, toPS(size));
124 fontDb->recallFont(familyId, body);
125 setGraphicsContext(strokeColor, strokeWidth);
126
127 body << "newpath" << std::endl;
128 body << PS_RenderingContext::toPS(x) << " "
129 << PS_RenderingContext::toPS(y) << " "
130 << "moveto" << std::endl;
131
132 body << "(";
133 for (String::const_iterator i = content.begin(); i != content.end(); i++)
134 drawChar((unsigned char) (*i));
135 body << ") show" << std::endl;
136
137 fontDb->usedChar(content, family);
138
139 body << fillColor.red / 255.0 << " "
140 << fillColor.green / 255.0 << " "
141 << fillColor.blue / 255.0 << " "
142 << "setrgbcolor" << " fill" << std::endl;
143 }
144
145 void
drawChar(unsigned char ch)146 PS_StreamRenderingContext::drawChar(unsigned char ch)
147 {
148 switch(ch) {
149 case '(': body << "\\("; break;
150 case ')': body << "\\)"; break;
151 case '\\': body << "\\\\"; break;
152 default:
153 if (isprint(ch) && !isspace(ch))
154 body << ch;
155 else
156 body << "\\" << (ch / 64) % 8 << (ch / 8) % 8 << ch % 8;
157 break;
158 }
159 }
160
161 void
line(const scaled & x1,const scaled & y1,const scaled & x2,const scaled & y2,const RGBColor & strokeColor,const scaled & strokeWidth)162 PS_StreamRenderingContext::line(const scaled& x1, const scaled& y1,
163 const scaled& x2, const scaled& y2,
164 const RGBColor& strokeColor, const scaled& strokeWidth)
165 {
166 setGraphicsContext(strokeColor, strokeWidth);
167
168 body << "newpath" << std::endl;
169 body << PS_RenderingContext::toPS(x1) << " "
170 << PS_RenderingContext::toPS(y1) << " "
171 << "moveto" << std::endl;
172 body << PS_RenderingContext::toPS(x2) << " "
173 << PS_RenderingContext::toPS(y2) << " "
174 << "lineto" << std::endl;
175 }
176