Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
latex-pstricks.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * LaTeX Printing
4 *
5 * Author:
6 * Michael Forbes <miforbes@mbhs.edu>
7 * Abhishek Sharma
8 *
9 * Copyright (C) 2004 Authors
10 *
11 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
12 */
13
14#include <2geom/pathvector.h>
16#include <2geom/curves.h>
17#include <cerrno>
18#include <csignal>
19#include "util/units.h"
20#include "helper/geom-curves.h"
21
22#include "colors/color.h"
23#include "extension/print.h"
24#include "extension/system.h"
25#include "inkscape-version.h"
26#include "io/sys.h"
27#include "latex-pstricks.h"
28#include "style.h"
29#include "document.h"
30#include <cstring>
31
32namespace Inkscape {
33namespace Extension {
34namespace Internal {
35
37 _width(0),
38 _height(0),
39 _stream(nullptr)
40{
41}
42
44{
45 if (_stream) fclose(_stream);
46}
47
49{
50 return TRUE;
51}
52
54{
56 int res;
57 FILE *osf = nullptr;
58 const gchar * fn = nullptr;
59 gsize bytesRead = 0;
60 gsize bytesWritten = 0;
61 GError* error = nullptr;
62
63 os.setf(std::ios::fixed);
64 fn = mod->get_param_string("destination");
65 gchar* local_fn = g_filename_from_utf8( fn,
66 -1, &bytesRead, &bytesWritten, &error);
67 fn = local_fn;
68
69 /* TODO: Replace the below fprintf's with something that does the right thing whether in
70 * gui or batch mode (e.g. --print=blah). Consider throwing an exception: currently one of
71 * the callers (sp_print_document_to_file, "ret = mod->begin(doc)") wrongly ignores the
72 * return code.
73 */
74 if (fn != nullptr) {
75 while (isspace(*fn)) fn += 1;
77 osf = Inkscape::IO::fopen_utf8name(fn, "w+");
78 if (!osf) {
79 fprintf(stderr, "inkscape: fopen(%s): %s\n", fn, strerror(errno));
80 g_free(local_fn);
81 return 0;
82 }
83 _stream = osf;
84 }
85
86 g_free(local_fn);
87
88 res = fprintf(_stream, "%%LaTeX with PSTricks extensions\n");
89 /* flush this to test output stream as early as possible */
90 if (fflush(_stream)) {
91 /*g_warning("caught error in sp_module_print_plain_begin");*/
92 if (ferror(_stream)) {
93 g_warning("Error %d on output stream: %s", errno,
94 g_strerror(errno));
95 }
96 g_warning("Printing failed");
97 /* fixme: should use pclose() for pipes */
98 fclose(_stream);
99 _stream = nullptr;
100 fflush(stdout);
101 return 0;
102 }
103
104 // width and height in pt
105 _width = doc->getWidth().value("pt");
106 _height = doc->getHeight().value("pt");
107
108 if (res >= 0) {
109
110 os << "%%Creator: Inkscape " << Inkscape::version_string << "\n";
111 os << "%%Please note this file requires PSTricks extensions\n";
112
113 os << "\\psset{xunit=.5pt,yunit=.5pt,runit=.5pt}\n";
114 // from now on we can output px, but they will be treated as pt
115
116 os << "\\begin{pspicture}(" << doc->getWidth().value("px") << "," << doc->getHeight().value("px") << ")\n";
117 }
118
119 m_tr_stack.push( Geom::Scale(1, -1) * Geom::Translate(0, doc->getHeight().value("px")));
120
121 return fprintf(_stream, "%s", os.str().c_str());
122}
123
125{
126 if (_stream) {
127 fprintf(_stream, "\\end{pspicture}\n");
128
129 // Flush stream to be sure.
130 fflush(_stream);
131
132 fclose(_stream);
133 _stream = nullptr;
134 }
135 return 0;
136}
137
138unsigned int PrintLatex::bind(Inkscape::Extension::Print * /*mod*/, Geom::Affine const &transform, float /*opacity*/)
139{
140 if (!m_tr_stack.empty()) {
141 Geom::Affine tr_top = m_tr_stack.top();
142 m_tr_stack.push(transform * tr_top);
143 } else {
144 m_tr_stack.push(transform);
145 }
146
147 return 1;
148}
149
151{
152 m_tr_stack.pop();
153 return 1;
154}
155
157 Geom::PathVector const &pathv, Geom::Affine const &transform, SPStyle const *style,
158 Geom::OptRect const & /*pbox*/, Geom::OptRect const & /*dbox*/, Geom::OptRect const & /*bbox*/)
159{
160 if (!_stream) {
161 return 0; // XXX: fixme, returning -1 as unsigned.
162 }
163
164 if (style->fill.isColor()) {
166 float fill_opacity;
167
168 os.setf(std::ios::fixed);
169
170 fill_opacity=SP_SCALE24_TO_FLOAT(style->fill_opacity.value);
171 auto rgb = *style->fill.getColor().converted(Colors::Space::Type::RGB);
172 os << "{\n\\newrgbcolor{curcolor}{" << rgb[0] << " " << rgb[1] << " " << rgb[2] << "}\n";
173 os << "\\pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor";
174 if (fill_opacity!=1.0) {
175 os << ",opacity="<<fill_opacity;
176 }
177
178 os << "]\n{\n";
179
180 print_pathvector(os, pathv, transform);
181
182 os << "}\n}\n";
183
184 fprintf(_stream, "%s", os.str().c_str());
185 }
186
187 return 0;
188}
189
191 Geom::PathVector const &pathv, Geom::Affine const &transform, SPStyle const *style,
192 Geom::OptRect const & /*pbox*/, Geom::OptRect const & /*dbox*/, Geom::OptRect const & /*bbox*/)
193{
194 if (!_stream) {
195 return 0; // XXX: fixme, returning -1 as unsigned.
196 }
197
198 if (style->stroke.isColor()) {
200 Geom::Affine tr_stack = m_tr_stack.top();
201 double const scale = tr_stack.descrim();
202 os.setf(std::ios::fixed);
203
204 double stroke_opacity = style->stroke_opacity;
205 auto rgb = *style->stroke.getColor().converted(Colors::Space::Type::RGB);
206 os << "{\n\\newrgbcolor{curcolor}{" << rgb[0] << " " << rgb[1] << " " << rgb[2] << "}\n";
207
208 os << "\\pscustom[linewidth=" << style->stroke_width.computed*scale<< ",linecolor=curcolor";
209
210 if (stroke_opacity!=1.0) {
211 os<<",strokeopacity="<<stroke_opacity;
212 }
213
214 if (style->stroke_dasharray.set && !style->stroke_dasharray.values.empty()) {
215 os << ",linestyle=dashed,dash=";
216 for (unsigned i = 0; i < style->stroke_dasharray.values.size(); i++) {
217 if ((i)) {
218 os << " ";
219 }
220 os << style->stroke_dasharray.values[i].value;
221 }
222 }
223
224 os <<"]\n{\n";
225
226 print_pathvector(os, pathv, transform);
227
228 os << "}\n}\n";
229
230 fprintf(_stream, "%s", os.str().c_str());
231 }
232
233 return 0;
234}
235
236// FIXME: why is 'transform' argument not used?
237void
239{
240 if (pathv_in.empty())
241 return;
242
243// Geom::Affine tf=transform; // why was this here?
244 Geom::Affine tf_stack=m_tr_stack.top(); // and why is transform argument not used?
245 Geom::PathVector pathv = pathv_in * tf_stack; // generates new path, which is a bit slow, but this doesn't have to be performance optimized
246
247 os << "\\newpath\n";
248
249 for(const auto & it : pathv) {
250
251 os << "\\moveto(" << it.initialPoint()[Geom::X] << "," << it.initialPoint()[Geom::Y] << ")\n";
252
253 for(Geom::Path::const_iterator cit = it.begin(); cit != it.end_open(); ++cit) {
254 print_2geomcurve(os, *cit);
255 }
256
257 if (it.closed()) {
258 os << "\\closepath\n";
259 }
260
261 }
262}
263
264void
266{
267 using Geom::X;
268 using Geom::Y;
269
270 if( is_straight_curve(c) )
271 {
272 os << "\\lineto(" << c.finalPoint()[X] << "," << c.finalPoint()[Y] << ")\n";
273 }
274 else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast<Geom::CubicBezier const*>(&c)) {
275 std::vector<Geom::Point> points = cubic_bezier->controlPoints();
276 os << "\\curveto(" << points[1][X] << "," << points[1][Y] << ")("
277 << points[2][X] << "," << points[2][Y] << ")("
278 << points[3][X] << "," << points[3][Y] << ")\n";
279 }
280 else {
281 //this case handles sbasis as well as all other curve types
282 Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(c.toSBasis(), 0.1);
283
284 for(const auto & iter : sbasis_path) {
285 print_2geomcurve(os, iter);
286 }
287 }
288}
289
290bool
292{
293 return ext->get_param_bool("textToPath");
294}
295
296#include "clear-n_.h"
297
299{
300 /* SVG in */
301 // clang-format off
303 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
304 "<name>" N_("LaTeX Print") "</name>\n"
305 "<id>" SP_MODULE_KEY_PRINT_LATEX "</id>\n"
306 "<param gui-hidden=\"true\" name=\"destination\" type=\"string\"></param>\n"
307 "<param gui-hidden=\"true\" name=\"textToPath\" type=\"bool\">true</param>\n"
308 "<print/>\n"
309 "</inkscape-extension>", std::make_unique<PrintLatex>());
310 // clang-format on
311}
312
313} /* namespace Internal */
314} /* namespace Extension */
315} /* namespace Inkscape */
316
317/*
318 Local Variables:
319 mode:c++
320 c-file-style:"stroustrup"
321 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
322 indent-tabs-mode:nil
323 fill-column:99
324 End:
325*/
326// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
327
double scale
Definition aa.cpp:228
3x3 matrix representing an affine transformation.
Definition affine.h:70
Coord descrim() const
Calculate the descriminant.
Definition affine.cpp:434
Bezier curve with compile-time specified order.
Abstract continuous curve on a plane defined on [0,1].
Definition curve.h:78
Axis-aligned rectangle that can be empty.
Definition rect.h:203
Sequence of subpaths.
Definition pathvector.h:122
bool empty() const
Check whether the vector contains any paths.
Definition pathvector.h:145
Sequence of contiguous curves, aka spline.
Definition path.h:353
Scaling from the origin.
Definition transforms.h:150
Translation by a vector.
Definition transforms.h:115
bool get_param_bool(char const *name) const
Gets a parameter identified by name with the bool placed in value.
unsigned int setup(Inkscape::Extension::Print *module) override
bool textToPath(Inkscape::Extension::Print *ext) override
Tell the printing engine whether text should be text or path.
void print_pathvector(SVGOStringStream &os, Geom::PathVector const &pathv_in, const Geom::Affine &)
void print_2geomcurve(SVGOStringStream &os, Geom::Curve const &c)
std::stack< Geom::Affine > m_tr_stack
unsigned int finish(Inkscape::Extension::Print *module) override
unsigned int begin(Inkscape::Extension::Print *module, SPDocument *doc) override
unsigned int release(Inkscape::Extension::Print *module) override
unsigned int bind(Inkscape::Extension::Print *module, Geom::Affine const &transform, float opacity) override
unsigned int stroke(Inkscape::Extension::Print *module, Geom::PathVector const &pathv, Geom::Affine const &ctm, SPStyle const *style, Geom::OptRect const &pbox, Geom::OptRect const &dbox, Geom::OptRect const &bbox) override
unsigned int fill(Inkscape::Extension::Print *module, Geom::PathVector const &pathv, Geom::Affine const &ctm, SPStyle const *style, Geom::OptRect const &pbox, Geom::OptRect const &dbox, Geom::OptRect const &bbox) override
std::string str() const
std::ios::fmtflags setf(std::ios::fmtflags fmtfl)
double value(Unit const *u) const
Return the quantity's value in the specified unit.
Definition units.cpp:502
Typed SVG document implementation.
Definition document.h:103
Inkscape::Util::Quantity getWidth() const
Definition document.cpp:857
Inkscape::Util::Quantity getHeight() const
Definition document.cpp:896
An SVG style object.
Definition style.h:45
T< SPAttr::FILL, SPIPaint > fill
fill
Definition style.h:240
T< SPAttr::STROKE_DASHARRAY, SPIDashArray > stroke_dasharray
stroke-dasharray
Definition style.h:257
T< SPAttr::STROKE, SPIPaint > stroke
stroke
Definition style.h:247
T< SPAttr::STROKE_WIDTH, SPILength > stroke_width
stroke-width
Definition style.h:249
T< SPAttr::FILL_OPACITY, SPIScale24 > fill_opacity
fill-opacity
Definition style.h:242
T< SPAttr::STROKE_OPACITY, SPIScale24 > stroke_opacity
stroke-opacity
Definition style.h:261
A way to clear the N_ macro, which is defined as an inline function.
Include all curve types.
double c[8][4]
Specific curve type functions for Inkscape, not provided by lib2geom.
bool is_straight_curve(Geom::BezierCurve const &c)
Definition geom-curves.h:22
@ Y
Definition coord.h:48
@ X
Definition coord.h:48
Mini static library that contains the version of Inkscape.
Path cubicbezierpath_from_sbasis(D2< SBasis > const &B, double tol)
void build_from_mem(gchar const *buffer, std::unique_ptr< Implementation::Implementation > in_imp)
Create a module from a buffer holding an XML description.
Definition system.cpp:459
void dump_fopen_call(char const *utf8name, char const *id)
Definition sys.cpp:37
FILE * fopen_utf8name(char const *utf8name, char const *mode)
Open a file with g_fopen().
Definition sys.cpp:72
Helper class to stream background task notifications as a series of messages.
char const * version_string
full version string
PathVector - a sequence of subpaths.
RGB rgb
Definition quantize.cpp:36
Conversion between SBasis and Bezier basis polynomials.
SPStyle - a style object for SPItem objects.