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