w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

drvcairo.cpp
Go to the documentation of this file.
1 /*
2  drvcairo.cpp : This file is part of pstoedit
3  Copyright (C) 2009 - 2020 Dan McMahill dan_AT_mcmahill_DOT_net
4 
5  This driver used drvSAMPL.cpp as a reference.
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 #include "drvcairo.h"
23 #include I_fstream
24 #include I_stdio
25 #include I_stdlib
26 #include <iostream>
27 #include <fstream>
28 #include <memory>
29 
30 // TODO
31 //
32 // - fix text font selection
33 // = When using -pango, the text all appears to be offset in the y-direction from where it
34 // should be. Also bold and italics don't work with -pango.
35 //
36 // = Is it possible to get the postscript bounding box for the text? If so then one idea is I
37 // create the pango or cairo text, get its size and then use cairo_transform to scale it so the pango or
38 // cairo bounding box matches the postscript one. This way even if the fonts are a little different
39 // we end up with something as close as possible.
40 //
41 // = What about symbol font? It looks like the way this has to happen is I need to convert
42 // to the greek alphabet in unicode stored in UTF-8 and that sounds like a pretty big hack
43 // when the chances of really getting fonts to be right are slim. The reality is that
44 // fonts probably won't look right unless you use -dt as a pstoedit option
45 //
46 // - fix bounding box glitches.
47 // = examples/colrtest.ps
48 //
49 // - image and imagemask support
50 // Can I implement this directly?
51 // = examples/imagetest_1.ps
52 // = examples/imagetest_2.ps
53 // = examples/imagetest_3.ps
54 // = examples/oneimg.ps
55 // = examples/woglim.ps
56 // If I can figure out how to get at the pixel data, I can generate cairo code that will render it.
57 // Cairo can also load png from a file however I'd prefer to not to have to do that since it means
58 // the end users program now needs to know how to locate the .png files at runtime and it is not
59 // a given that the users code knows how to reliably do this so I'd rather embed the picture.
60 //
61 // - Is there a better way of getting the name for the header file that is created?
62 //
63 
65  //(const char * driveroptions_p,ostream & theoutStream,ostream & theerrStream): // Constructor
66  constructBase //, imgcount(0)
67 {
68  ofstream outh;
69 
70  // driver specific initializations
71  // and writing of header to output file
72  outf << "/* ***** Generated from pstoedit ***** */" << endl;
73  outf << "#include <cairo.h>" << endl;
74  if (options->pango.value) {
75  outf << "#include <pango/pangocairo.h>" << endl;
76  }
77  outf << "#include <stdio.h>" << endl;
78  outf << endl;
79 
80  maxw = 0;
81  maxh = 0;
82  evenoddmode = false;
83 
84 
85  // Generate the header file
86  outh.open(options->header.value.c_str(), ios::out);
87 
88  outh << "/* " << options->header.value << " */" << endl;
89  outh << "/* ***** Generated from pstoedit ***** */" << endl;
90  outh << "#ifndef __" << options->funcname.value << "_H__" << endl;
91  outh << "#define __" << options->funcname.value << "_H__" << endl;
92  outh << "#include <cairo.h>" << endl;
93  outh << "extern cairo_t * (*" << options->funcname.value << "_render[])(cairo_surface_t *, cairo_t *);" << endl;
94  outh << "extern int " << options->funcname.value << "_total_pages;" << endl;
95  outh << "extern int " << options->funcname.value << "_width[];" << endl;
96  outh << "extern int " << options->funcname.value << "_height[];" << endl;
97  outh << "extern void " << options->funcname.value << "_init(void);" << endl;
98  outh << "#endif /* __" << options->funcname.value << "_H__ */" << endl;
99  outh << endl;
100  outh.close();
101 
102 }
103 
105 {
106  unsigned int i;
107 
108  // driver specific deallocations
109  // and writing of trailer to output file
110  outf << endl;
111  outf << "/* Total number of pages */" << endl;
112  outf << "int " << options->funcname.value << "_" << "total_pages;" << endl;
113  outf << endl;
114  outf << "/* Array of the individual page render functions */" << endl;
115  outf << "cairo_t * (*" << options->funcname.value << "_render[" << totalNumberOfPages() << "])(cairo_surface_t *, cairo_t *);" << endl;
116  outf << endl;
117  outf << "/* array of pointers to the widths and heights */" << endl;
118  outf << "int " << options->funcname.value << "_width[" << totalNumberOfPages() << "];" << endl;
119  outf << "int " << options->funcname.value << "_height[" << totalNumberOfPages() << "];" << endl;
120  outf << endl;
121 
122  outf << "/* This function should be called at the beginning of the user program */" << endl;
123  outf << "void " << options->funcname.value << "_init(void)" << endl;
124  outf << "{" << endl;
125  outf << endl;
126  outf << " " << options->funcname.value << "_" << "total_pages = " << totalNumberOfPages() << ";" << endl;
127  outf << endl;
128 
129  // Now spit out an array of pointers to the render functions, so we can deal with multiple pages
130  for (i = 1 ; i <= drvbase::totalNumberOfPages() ; i++) {
131  outf << " " << options->funcname.value << "_render[" << i-1 << "] = ";
132  outf << options->funcname.value << "_page_" << i << "_render;" << endl;
133  }
134  outf << endl;
135 
136  for (i = 1 ; i <= drvbase::totalNumberOfPages() ; i++) {
137  outf << " " << options->funcname.value << "_width[" << i-1 << "] = ";
138  outf << options->funcname.value << "_page_" << i << "_width;" << endl;
139 
140  }
141 
142  for (i = 1 ; i <= drvbase::totalNumberOfPages() ; i++) {
143  outf << " " << options->funcname.value << "_height[" << i-1 << "] = ";
144  outf << options->funcname.value << "_page_" << i << "_height;" << endl;
145 
146  }
147  outf << "}" << endl;
148  outf << endl;
149 
150  outf << "float " << options->funcname.value << "_width_max = " << maxw << ";" << endl;
151  outf << "float " << options->funcname.value << "_height_max = " << maxh << ";" << endl;
152 
153 }
154 
156 {
157 
158  for (unsigned int n = 0; n < numberOfElementsInPath(); n++) {
159  const basedrawingelement & elem = pathElement(n);
160  switch (elem.getType()) {
161  case moveto:{
162  const Point & p = elem.getPoint(0);
163  outf << " cairo_move_to (cr, ";
164  outf << p.x_ + x_offset << ", " << /* currentDeviceHeight - */ -1*p.y_ + y_offset << ");";
165  }
166  break;
167  case lineto:{
168  const Point & p = elem.getPoint(0);
169  outf << " cairo_line_to (cr, ";
170  outf << p.x_ + x_offset << ", " << /* currentDeviceHeight - */ -1*p.y_ + y_offset << ");";
171  }
172  break;
173  case closepath:
174  outf << " cairo_close_path (cr);";
175  break;
176  case curveto:{
177  outf << " cairo_curve_to (cr";
178  for (unsigned int cp = 0; cp < 3; cp++) {
179  const Point & p = elem.getPoint(cp);
180  outf <<
181  ", " << (p.x_ + x_offset) <<
182  ", " << /* currentDeviceHeight - */ (-1*p.y_ + y_offset);
183  }
184  outf << ");" << endl;
185  }
186  break;
187  default:
188  errf << "\t\tFatal: unexpected case in drvcairo " << endl;
189  abort();
190  break;
191  }
192  outf << endl;
193  }
194 }
195 
196 
197 void drvCAIRO::open_page()
198 {
199  BBox mybox;
200 
201 
202  mybox = getCurrentBBox();
203 
204  x_offset = -mybox.ll.x_;
205  y_offset = mybox.ur.y_;
206  //cout << "Set offset to (" << x_offset << ", " << y_offset << ")" << endl;
207 
208  outf << "/*" << endl;
209  outf << " * Original bounding box = for page # " << currentPageNumber << " is" << endl;
210  outf << " * " << mybox << endl;
211  outf << " * The figure has been offset by (" << x_offset << ", " << y_offset << ")" << endl;
212  outf << " * to move LL to (0,0). The width and height" << endl;
213  outf << " * can be read from the following two variables:" << endl;
214  outf << " */" << endl;
215 
216  outf << "static int " << options->funcname.value <<"_page_" << currentPageNumber << "_width = " <<
217  mybox.ur.x_ - mybox.ll.x_ << ";" << endl;
218  outf << "static int " << options->funcname.value << "_page_" << currentPageNumber << "_height = " <<
219  mybox.ur.y_ - mybox.ll.y_ << ";" << endl;
220  outf << endl;
221 
222  if (mybox.ur.x_ - mybox.ll.x_ > maxw) {
223  maxw = mybox.ur.x_ - mybox.ll.x_;
224  }
225 
226  if (mybox.ur.y_ - mybox.ll.y_ > maxh) {
227  maxh = mybox.ur.y_ - mybox.ll.y_;
228  }
229 
230  outf << "static cairo_t * " << options->funcname.value << "_page_" << currentPageNumber << "_render";
231  outf << "(cairo_surface_t *cs, cairo_t *cr)" << endl;
232  outf << "{" << endl;
233 
234  outf << endl;
235  outf << " if (cr == NULL && cs == NULL) {" << endl;
236  outf << " return NULL;" << endl;
237  outf << " } else if(cr == NULL && cs != NULL) {" << endl;
238  outf << " cr = cairo_create (cs);" << endl;
239  outf << " } else if(cr != NULL && cs == NULL) {" << endl;
240  outf << " } else if(cr != NULL && cs != NULL) {" << endl;
241  outf << " }" << endl;
242  outf << endl;
243 
244  outf << " cairo_save (cr);" << endl;
245  outf << endl;
246  if (!options->pango.value) {
247 
248  outf << " /* set an initial font */" << endl;
249  outf << " cairo_select_font_face (cr, \"monospace\"," <<
250  " CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);" << endl;
251  }
252  outf << endl;
253 
254 }
255 
257 {
258  outf << " cairo_restore (cr);" << endl;
259  outf << endl;
260  outf << " return cr;" << endl;
261  outf << "} /* end of " << options->funcname.value << "_page_" << (currentPageNumber) << "_render() */" ;
262  outf << endl;
263 }
264 
265 void drvCAIRO::show_text(const TextInfo & textinfo)
266 {
267  outf << " /*" << endl;
268  outf << " * " << "X " << textinfo.x() << " Y " << textinfo.y() << endl;
269  outf << " * " << "X_END " << textinfo.x_end() << " Y_END " << textinfo.y_end() << endl;
270  outf << " * " << "currentFontName: " << textinfo.currentFontName.c_str() << endl;
271  outf << " * " << "is_non_standard_font: " << textinfo.is_non_standard_font << endl;
272  outf << " * " << "currentFontFamilyName: " << textinfo.currentFontFamilyName.c_str() << endl;
273  outf << " * " << "currentFontFullName: " << textinfo.currentFontFullName.c_str() << endl;
274  outf << " * " << "currentFontWeight: " << textinfo.currentFontWeight.c_str() << endl;
275  outf << " * " << "currentFontAngle: " << textinfo.currentFontAngle << endl;
276 
277  const float *CTM = getCurrentFontMatrix();
278  const char *family;
279 
280  outf << " * " << "currentFontMatrix: [";
281  for (unsigned int i = 0; i < 6; i++) {
282  outf << " " << CTM[i];
283  }
284  outf << ']' << endl;
285  outf << " */" << endl;
286 
287  outf << " {" << endl;
288  outf << " cairo_matrix_t matrix, save_matrix;" << endl;
289  if (options->pango.value) {
290  outf << " PangoFontDescription *desc;" << endl;
291  outf << " PangoLayout *layout;" << endl;
292  }
293  outf << " const char *text = \"" << textinfo.thetext.c_str() << "\";" << endl;
294  outf << endl;
295 
296  outf << " cairo_set_source_rgb (cr, " << textinfo.currentR << "," <<
297  textinfo.currentG << "," << textinfo.currentB << ");" << endl;
298 
299  outf << " cairo_get_matrix (cr, &save_matrix);" << endl;
300 
301  // cairo_matrix_init (xx, yx, xy, yy, x0, y0)
302  // x_new = xx * x + xy * y + x0;
303  // y_new = yx * x + yy * y + y0;
304  outf << " cairo_save (cr);" << endl;
305  outf << " cairo_matrix_init (&matrix,"
306  << CTM[0]/textinfo.currentFontSize << ", "
307  << -1.0*CTM[1]/textinfo.currentFontSize << ", "
308  << -1.0*CTM[2]/textinfo.currentFontSize << ", "
309  << 1.0*CTM[3]/textinfo.currentFontSize << ", "
310  << CTM[4] + x_offset << ", "
311  << -1.0*CTM[5] + y_offset << ");" << endl;
312 
313  outf << " cairo_transform (cr, &matrix);" << endl;
314  outf << " cairo_move_to (cr, 0, 0);" << endl;
315  outf << endl;
316 
317  family = "monospace";
318  if (strstr(textinfo.currentFontName.c_str(), "Times") ||
319  strstr(textinfo.currentFontName.c_str(), "Roman")) {
320  family = "serif";
321  } else if (strstr(textinfo.currentFontName.c_str(), "Helvetica") ||
322  strstr(textinfo.currentFontName.c_str(), "Sans")) {
323  family = "sans-serif";
324  } else if (strstr(textinfo.currentFontName.c_str(), "Courier") ||
325  strstr(textinfo.currentFontName.c_str(), "Mono")) {
326  family = "monospace";
327  } else if (strstr(textinfo.currentFontName.c_str(), "Symbol") ) {
328  // In this case, what unfortunately needs to happen is I need to convert the
329  // ASCII string to UTF-8 encoded string but with mapping from the
330  family = "symbol";
331  } else {
332  errf << "currentFontName: " << textinfo.currentFontName.c_str() << " is not known." << endl;
333  errf << " Defaulting to " << family << endl;
334  }
335 
336  if (options->pango.value) {
337  outf << " /* Set pango font */" << endl;
338  outf << " layout = pango_cairo_create_layout (cr);" << endl;
339  outf << " desc = pango_font_description_from_string (\"" <<
340  family << "\");" << endl;
341 
342  outf << " /* A size value of 10 * PANGO_SCALE is a 10 point font. */" << endl;
343  outf << " pango_font_description_set_size (desc, " <<
344  textinfo.currentFontSize << " * PANGO_SCALE);" << endl;
345  outf << " pango_layout_set_font_description (layout, desc);" << endl;
346  outf << " pango_font_description_free (desc);" << endl;
347  outf << " pango_layout_set_text (layout, text, -1);" << endl;
348  outf << " pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);" << endl;
349 
350  outf << " pango_cairo_show_layout (cr, layout);" << endl;
351  outf << " g_object_unref (layout);" << endl;
352 
353  } else {
354  const char *weight, *slant;
355  // cairo_select_font_face (cairo_t *cr,
356  // const char *family,
357  // cairo_font_slant_t slant,
358  // cairo_font_weight_t weight);
359  //
360  // family:
361  // standard CSS2 generic family names, ("serif", "sans-serif",
362  // "cursive", "fantasy", "monospace"), are likely to work as expected.
363  //
364 
365  // FIXME -- figure out how to get the family set is a better way
366 
367  // slant:
368  // CAIRO_FONT_SLANT_NORMAL - Upright font style
369  // CAIRO_FONT_SLANT_ITALIC - Italic font style
370  // CAIRO_FONT_SLANT_OBLIQUE - Oblique font style
371  //
372 
373  // FIXME -- set the slant more robustly
374  slant = "CAIRO_FONT_SLANT_NORMAL";
375  if (strstr(textinfo.currentFontFullName.c_str(), "Italic")) {
376  slant = "CAIRO_FONT_SLANT_ITALIC";
377  } else if (strstr(textinfo.currentFontFullName.c_str(), "Oblique")) {
378  slant = "CAIRO_FONT_SLANT_OBLIQUE";
379  }
380 
381  // weight:
382  // CAIRO_FONT_WEIGHT_NORMAL - Normal font weight
383  // CAIRO_FONT_WEIGHT_BOLD - Bold font weight
384  //
385 
386  // FIXME -- set the weight more robustly
387  weight = "CAIRO_FONT_WEIGHT_NORMAL";
388  if (strstr(textinfo.currentFontWeight.c_str(), "bold") ||
389  strstr(textinfo.currentFontWeight.c_str(), "Bold") ) {
390  weight = "CAIRO_FONT_WEIGHT_BOLD";
391  }
392 
393  outf << " cairo_select_font_face (cr, \"" << family << "\"," << endl;
394  outf << " " << slant << "," << endl;
395  outf << " " << weight << ");" << endl;
396 
397  // outf << " status = cairo_status (cr);" << endl;
398  //outf << " printf(\"cairo_select_font_face() returned \\\"%s\\\"\\n\", cairo_status_to_string (status));" << endl;
399 
400  outf << " cairo_set_font_size (cr, " << textinfo.currentFontSize << ");" << endl;
401  outf << " cairo_show_text (cr, text);" << endl;
402  }
403 
404  outf << " cairo_set_matrix (cr, &save_matrix);" << endl;
405  outf << " cairo_restore (cr);" << endl;
406  outf << " cairo_move_to (cr, " << textinfo.x_end() + x_offset
407  << ", " << -1*textinfo.y_end() + y_offset << ");" << endl;
408  outf << " }" << endl;
409  outf << endl;
410 
411 }
412 
414 {
415  // type is 'clip' or 'eoclip'
417 
418  outf << " cairo_save (cr);" << endl;
419  outf << " cairo_reset_clip (cr);" << endl;
420 
421  if (evenoddmode) {
422  outf << " cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);" << endl;
423  } else {
424  outf << " cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);" << endl;
425  }
426 
427  print_coords();
428  outf << " cairo_clip (cr);" << endl;
429  outf << " cairo_restore (cr);" << endl;
430 }
431 
432 void drvCAIRO::show_path()
433 {
435 
436  outf << endl;
437  outf << " /*" << endl;
438  outf << " * Path # " << currentNr() ;
439  if (isPolygon())
440  outf << " (polygon):" << endl;
441  else
442  outf << " (polyline):" << endl;
443  outf << " */" << endl;
444  outf << endl;
445 
446  outf << " cairo_save (cr);" << endl;
447  outf << " cairo_set_line_width (cr, " << currentLineWidth() << ");" << endl;
448 
449  // CAIRO_LINE_CAP_BUTT - start(stop) the line exactly at the start(end) point
450  // CAIRO_LINE_CAP_ROUND - use a round ending, the center of the circle is the end point
451  // CAIRO_LINE_CAP_SQUARE - use squared ending, the center of the square is the end point
452  outf << " cairo_set_line_cap (cr, ";
453  switch( currentLineCap() ) {
454  case 0:
455  outf << "CAIRO_LINE_CAP_BUTT);" << endl;
456  break;
457 
458  case 1:
459  outf << "CAIRO_LINE_CAP_ROUND);" << endl;
460  break;
461 
462  case 2:
463  outf << "CAIRO_LINE_CAP_SQUARE);" << endl;
464  break;
465 
466  default:
467  errf << "Unexpected currentLineCap() in cairo driver: " << currentLineCap() << endl;
468  outf << "CAIRO_LINE_CAP_ROUND);" << endl;
469  break;
470  }
471  // cairo_set_dash (cairo_t *cr, const double *dashes, int num_dashes, double offset);
472  // dashes :
473  // an array specifying alternate lengths of on and off stroke portions
474  //
475  // num_dashes :
476  // the length of the dashes array
477  //
478  // offset :
479  // an offset into the dash pattern at which the stroke should start
480  //
481  // dashPattern: has nrOfEntries, float *numbers, float offset
482 
483  if (dp.nrOfEntries > 0) {
484  outf << " {" << endl;
485  outf << " double pat[" << dp.nrOfEntries << "] = {" << endl;
486  for (int i = 0; i < dp.nrOfEntries; i++) {
487  outf << " " << dp.numbers[i] << ", " << endl;
488  }
489  outf << " };" << endl;
490  outf << endl;
491  outf << " cairo_set_dash (cr, pat, " << dp.nrOfEntries << ", " << dp.offset << ");" << endl;
492  outf << " }" << endl;
493  } else {
494  outf << " cairo_set_dash (cr, NULL, 0, 0.0);" << endl;
495  }
496 
497  // cairo_move_to (cr, 0.25, 0.25);
498  // cairo_line_to (cr, 0.5, 0.375);
499  outf << " /* Path Elements 0 to " << numberOfElementsInPath() - 1 << " */" << endl;
500  print_coords();
501 
502 
503 
504  switch (currentShowType()) {
505  case drvbase::stroke:
506  outf << " cairo_set_source_rgb (cr, " << edgeR() << "," << edgeG() << "," << edgeB() << ");" << endl;
507  outf << " cairo_stroke (cr);" << endl;
508  break;
509 
510  case drvbase::eofill:
511  outf << " cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);" << endl;
512  evenoddmode = true;
513  /* no break */
514  // fall through
515  case drvbase::fill:
516 
517  outf << " cairo_set_source_rgb (cr, " << fillR() << "," << fillG() << "," << fillB() << ");" << endl;
518  outf << " cairo_fill_preserve (cr);" << endl;
519  if (evenoddmode) {
520  outf << " cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);" << endl;
521  evenoddmode = false;
522  }
523  outf << " cairo_set_source_rgb (cr, " << edgeR() << "," << edgeG() << "," << edgeB() << ");" << endl;
524  outf << " cairo_stroke (cr);" << endl;
525  break;
526 
527  default:
528  // cannot happen
529  outf << " // unexpected ShowType " << (int) currentShowType();
530  break;
531  }
532  outf << " cairo_restore (cr);" << endl;
533 
534 }
535 
536 void drvCAIRO::show_rectangle(const float llx, const float lly, const float urx, const float ury)
537 {
538  // FIXME -- I need to get some rectangle calls into my sample so i can test this...
539  // cairo_rectangle (cr, x, y, width, height);
540  outf << " cairo_rectangle (cr, " << llx << "," << lly << ", " << urx-llx << "," << ury-lly << ");" << endl;
541  // just do show_path for a first guess
542  show_path();
543 }
544 
545 void drvCAIRO::show_image(const PSImage & imageinfo)
546 {
547  // first retrieve bounding box
548  Point lowerLeft, upperRight;
549  imageinfo.getBoundingBox(lowerLeft, upperRight);
550 
551  // not only bounding box must account for scale,
552  // but also transformation matrix!
553 
554  // scale bounding box
555  lowerLeft.x_ *= getScale();
556  lowerLeft.y_ *= getScale();
557  upperRight.x_ *= getScale();
558  upperRight.y_ *= getScale();
559 
560  const long width = abs(i_transX(upperRight.x_) - i_transX(lowerLeft.x_));
561  const long height = abs(i_transY(upperRight.y_) - i_transY(lowerLeft.y_));
562 
563  if (Verbose()) {
564  errf << "image.Width:" << imageinfo.width << " image.Height: " << imageinfo.height << endl;
565  errf << "Width:" << width << " Height: " << height << endl;
566  }
567 
568 #if 0
569 
570  // This is an example of how to take image data and get it into a cairo surface.
571  // If I ever figure out the pstoedit end, I can try one of these.
572  int stride;
573  unsigned char *data;
575  g_double w, h;
576  /*
577  CAIRO_FORMAT_ARGB32,
578  CAIRO_FORMAT_RGB24,
579  CAIRO_FORMAT_A8,
580  CAIRO_FORMAT_A1
581  */
582 
584  data = malloc (stride * height);
586  width, height,
587  stride);
589  width, height,
590  stride);
591 #endif
592 
593 
594  // calc long-padded size of scanline
595  const long scanlineLen = ((width * 3) + 3) & ~3L;
596 
597  // now lets get some mem
598  std::unique_ptr<unsigned char[]> output (new unsigned char[scanlineLen * height]);
599 
600  for (long i = 0; i < scanlineLen * height; i++)
601  output[i] = 255; // default is background (white)
602 
603  if (!output) {
604  errf << "ERROR: Cannot allocate memory for image" << endl;
605  return;
606  }
607  // setup inverse transformation matrix (scaled, too!)
608  const float matrixScale(imageinfo.normalizedImageCurrentMatrix[0] *
609  imageinfo.normalizedImageCurrentMatrix[3] -
610  imageinfo.normalizedImageCurrentMatrix[2] *
611  imageinfo.normalizedImageCurrentMatrix[1]);
612  const float inverseMatrix[] = {
613  imageinfo.normalizedImageCurrentMatrix[3] / matrixScale / getScale(),
614  -imageinfo.normalizedImageCurrentMatrix[1] / matrixScale / getScale(),
615  -imageinfo.normalizedImageCurrentMatrix[2] / matrixScale / getScale(),
616  imageinfo.normalizedImageCurrentMatrix[0] / matrixScale / getScale(),
617  (imageinfo.normalizedImageCurrentMatrix[2] *
618  imageinfo.normalizedImageCurrentMatrix[5] -
619  imageinfo.normalizedImageCurrentMatrix[4] *
620  imageinfo.normalizedImageCurrentMatrix[3]) / matrixScale,
621  (imageinfo.normalizedImageCurrentMatrix[4] *
622  imageinfo.normalizedImageCurrentMatrix[1] -
623  imageinfo.normalizedImageCurrentMatrix[0] *
624  imageinfo.normalizedImageCurrentMatrix[5]) / matrixScale
625  };
626 
627  // now transform image
628  for (long ypos = 0; ypos < height; ypos++) {
629  // buffer current output scanline (saves us some multiplications)
630  unsigned char *const currOutput = &output[scanlineLen * ypos];
631 
632  for (long xpos = 0; xpos < width; xpos++) {
633  // now transform from device coordinate space to image space
634 
635  // apply transformation
636  const Point currPoint = Point(xpos + lowerLeft.x_,
637  ypos + lowerLeft.y_).transform(inverseMatrix);
638 
639  // round to integers
640  const long sourceX = (long) (currPoint.x_ + .5);
641  const long sourceY = (long) (currPoint.y_ + .5);
642 
643  // is the pixel out of bounds? If yes, no further processing necessary
644  if (sourceX >= 0L && (unsigned long) sourceX < imageinfo.width &&
645  sourceY >= 0L && (unsigned long) sourceY < imageinfo.height) {
646  // okay, fetch source pixel value into
647  // RGB triplet
648 
649  unsigned char r(255), g(255), b(255), c, m, y, k;
650 
651  // how many components?
652  switch (imageinfo.ncomp) {
653  case 1:
654  r = g = b = imageinfo.getComponent(sourceX, sourceY, 0);
655  break;
656 
657  case 3:
658  r = imageinfo.getComponent(sourceX, sourceY, 0);
659  g = imageinfo.getComponent(sourceX, sourceY, 1);
660  b = imageinfo.getComponent(sourceX, sourceY, 2);
661  break;
662 
663  case 4:
664  c = imageinfo.getComponent(sourceX, sourceY, 0);
665  m = imageinfo.getComponent(sourceX, sourceY, 1);
666  y = imageinfo.getComponent(sourceX, sourceY, 2);
667  k = imageinfo.getComponent(sourceX, sourceY, 3);
668 
669  // account for key
670  c += k;
671  m += k;
672  y += k;
673 
674  // convert color
675  r = 255 - c;
676  g = 255 - m;
677  b = 255 - y;
678  break;
679 
680  default:
681  errf << "\t\tFatal: unexpected case in drvcairo (line "
682  << __LINE__ << ")" << endl;
683  abort();
684  return;
685  }
686 
687  // set color triple
688  currOutput[3 * xpos] = b;
689  currOutput[3 * xpos + 1] = g;
690  currOutput[3 * xpos + 2] = r;
691  }
692  }
693  }
694 }
695 
697  "cairo driver", // short description
698  "generates compilable c code for rendering with cairo", // long description
699  "c", // output file suffix
700  true, // backend supports subpaths
701  // if subpaths are supported, the backend must deal with
702  // sequences of the following form
703  // moveto (start of subpath)
704  // lineto (a line segment)
705  // lineto
706  // moveto (start of a new subpath)
707  // lineto (a line segment)
708  // lineto
709  //
710  // If this argument is set to false each subpath is drawn
711  // individually which might not necessarily represent
712  // the original drawing.
713  true, // backend supports curves
714  true, // backend supports elements which are filled and have edges
715  true, // backend supports text
716  DriverDescription::memoryeps, // format to be used for raster imagese
717  DriverDescription::normalopen, // binary or ascii output file
718  true, // if format supports multiple pages in one file
719  true /*clipping */
720  );
cp
Definition: action.c:1035
double ury
Definition: aftopl.c:56
double urx
Definition: aftopl.c:55
double lly
Definition: aftopl.c:54
double llx
Definition: aftopl.c:53
#define width(a)
Definition: aptex-macros.h:198
#define type(a)
Definition: aptex-macros.h:171
#define height(a)
Definition: aptex-macros.h:200
#define slant(f)
int cairo_format_stride_for_width(cairo_format_t format, int width)
cairo_surface_t * cairo_image_surface_create_for_data(unsigned char *data, cairo_format_t format, int width, int height, int stride)
cairo_surface_t * cairo_image_surface_create_from_png_stream(cairo_read_func_t read_func, void *closure)
Definition: cairo-png.c:824
static struct brw_reg stride(struct brw_reg reg, uint32_t vstride, uint32_t width, uint32_t hstride)
unsigned char getComponent(unsigned int x, unsigned int y, char numComponent) const
Definition: psimage.cpp:234
float normalizedImageCurrentMatrix[6]
Definition: psimage.h:41
void getBoundingBox(Point &ll_p, Point &ur_p) const
Definition: psimage.h:61
unsigned int width
Definition: psimage.h:37
short int ncomp
Definition: psimage.h:39
unsigned int height
Definition: psimage.h:36
const char * c_str() const
Definition: miscutil.h:127
virtual const Point & getPoint(unsigned int i) const =0
virtual Dtype getType() const =0
~drvCAIRO() override
Definition: drvcairo.cpp:104
void print_coords()
Definition: drvcairo.cpp:155
void show_rectangle(const float llx, const float lly, const float urx, const float ury) override
Definition: drvcairo.cpp:536
float maxw
Definition: drvcairo.h:69
void show_text(const TextInfo &textinfo) override
Definition: drvcairo.cpp:265
float maxh
Definition: drvcairo.h:69
void ClipPath(cliptype) override
Definition: drvcairo.cpp:413
void show_image(const PSImage &imageinfo) override
Definition: drvcairo.cpp:545
bool evenoddmode
Definition: drvcairo.h:71
float edgeG() const
Definition: drvbase.h:644
static unsigned int & totalNumberOfPages()
Definition: drvbase.cpp:1676
unsigned int currentPageNumber
Definition: drvbase.h:374
const basedrawingelement & pathElement(unsigned int index) const
Definition: drvbase.cpp:407
showtype currentShowType() const
Definition: drvbase.h:633
unsigned int currentNr() const
Definition: drvbase.h:642
int i_transX(float x) const
Definition: drvbase.h:458
static bool Verbose()
Definition: drvbase.cpp:1707
int i_transY(float y) const
Definition: drvbase.h:462
ostream & errf
Definition: drvbase.h:360
float edgeB() const
Definition: drvbase.h:645
const float * getCurrentFontMatrix() const
Definition: drvbase.h:588
static float getScale()
Definition: drvbase.h:448
const char * dashPattern() const
Definition: drvbase.h:650
float fillG() const
Definition: drvbase.h:647
float edgeR() const
Definition: drvbase.h:643
unsigned int currentLineCap() const
Definition: drvbase.h:635
bool isPolygon() const
Definition: drvbase.h:638
cliptype
Definition: drvbase.h:163
@ eoclip
Definition: drvbase.h:163
ostream & outf
Definition: drvbase.h:359
float fillR() const
Definition: drvbase.h:646
float x_offset
Definition: drvbase.h:371
const BBox & getCurrentBBox() const
Definition: drvbase.cpp:315
virtual void open_page()=0
float currentLineWidth() const
Definition: drvbase.h:641
@ fill
Definition: drvbase.h:162
@ stroke
Definition: drvbase.h:162
@ eofill
Definition: drvbase.h:162
virtual void close_page()=0
virtual void show_path()=0
float y_offset
Definition: drvbase.h:372
float fillB() const
Definition: drvbase.h:648
unsigned int & numberOfElementsInPath()
Definition: drvbase.h:513
#define n
Definition: t4ht.c:1290
#define b
Definition: jpegint.h:372
@ closepath
Definition: cscommands.h:4
@ lineto
Definition: drvbase.h:749
@ moveto
Definition: drvbase.h:749
@ curveto
Definition: drvbase.h:749
#define constructBase
Definition: drvbase.h:884
#define derivedConstructor(Class)
Definition: drvbase.h:871
static DriverDescriptionT< drvCAIRO > D_cairo("cairo", "cairo driver", "generates compilable c code for rendering with cairo", "c", true, true, true, true, DriverDescription::memoryeps, DriverDescription::normalopen, true, true)
int w
Definition: dviconv.c:26
int h
Definition: dviconv.c:9
struct rect data
Definition: dvipdfm.c:64
#define c(n)
Definition: gpos-common.c:150
FILE * out
Definition: hbf2gf.c:286
string family
small capitals from c petite p
Definition: afcover.h:72
small capitals from c petite p scientific i
Definition: afcover.h:80
kerning y
Definition: ttdriver.c:212
char * strstr()
#define output
Definition: cpascal.h:54
#define malloc
Definition: alloca.c:91
void abort()
int k
Definition: otp-parser.c:70
static int format
Definition: pbmclean.c:15
#define abs(a)
Definition: pbmplus.h:225
static cairo_surface_t * surface
Definition: pdftocairo.cc:234
int g
Definition: ppmqvga.c:68
int r
Definition: ppmqvga.c:68
RETTYPE mp_ptr mp_size_t mp_srcptr dp
Definition: sec_div.c:70
Definition: drvbase.h:119
Point ur
Definition: drvbase.h:122
Point ll
Definition: drvbase.h:121
float y_
Definition: drvbase.h:91
Point transform(const float matrix[6]) const
Definition: drvbase.cpp:1572
float x_
Definition: drvbase.h:89
RSString currentFontName
Definition: drvbase.h:176
RSString currentFontFullName
Definition: drvbase.h:179
RSString currentFontFamilyName
Definition: drvbase.h:178
RSString thetext
Definition: drvbase.h:173
float currentFontSize
Definition: drvbase.h:181
float y() const
Definition: drvbase.h:168
float x() const
Definition: drvbase.h:167
float x_end() const
Definition: drvbase.h:171
RSString currentFontWeight
Definition: drvbase.h:180
float currentFontAngle
Definition: drvbase.h:182
bool is_non_standard_font
Definition: drvbase.h:175
float y_end() const
Definition: drvbase.h:172
char * value
Definition: ppmtopjxl.c:57
Definition: output.h:18
m
Definition: tex4ht.c:3990
return() int(((double) *(font_tbl[cur_fnt].wtbl+(int)(*(font_tbl[cur_fnt].char_wi+(int)(ch - font_tbl[cur_fnt].char_f)% 256)))/(double)(1L<< 20)) *(double) font_tbl[cur_fnt].scale)
struct Point Point
@ L
Definition: ubidiimp.h:45