GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
gl2ps-renderer.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2009-2013 Shai Ayal
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #ifdef HAVE_GL2PS_H
28 
29 #include <cstdio>
30 
31 #include "lo-mappers.h"
32 #include "oct-locbuf.h"
33 
34 #include "gl2ps-renderer.h"
35 #include "gl2ps.h"
36 
37 void
38 glps_renderer::draw (const graphics_object& go, const std::string print_cmd)
39 {
40  static bool in_draw = false;
41  static std::string old_print_cmd;
42 
43  if (!in_draw)
44  {
45  in_draw = true;
46 
47  GLint buffsize = 0, state = GL2PS_OVERFLOW;
48  GLint viewport[4];
49 
50  glGetIntegerv (GL_VIEWPORT, viewport);
51 
52  GLint gl2ps_term;
53  if (term.find ("eps") != std::string::npos) gl2ps_term = GL2PS_EPS;
54  else if (term.find ("pdf") != std::string::npos) gl2ps_term = GL2PS_PDF;
55  else if (term.find ("svg") != std::string::npos) gl2ps_term = GL2PS_SVG;
56  else if (term.find ("ps") != std::string::npos) gl2ps_term = GL2PS_PS;
57  else if (term.find ("pgf") != std::string::npos) gl2ps_term = GL2PS_PGF;
58  else if (term.find ("tex") != std::string::npos) gl2ps_term = GL2PS_TEX;
59  else
60  {
61  error ("gl2ps-renderer:: Unknown terminal");
62  return;
63  }
64 
65  GLint gl2ps_text = 0;
66  if (term.find ("notxt") != std::string::npos) gl2ps_text = GL2PS_NO_TEXT;
67 
68  // Default sort order optimizes for 3D plots
69  GLint gl2ps_sort = GL2PS_BSP_SORT;
70  if (term.find ("is2D") != std::string::npos) gl2ps_sort = GL2PS_NO_SORT;
71 
72  while (state == GL2PS_OVERFLOW)
73  {
74  // For LaTeX output the fltk print process uses 2 drawnow() commands.
75  // The first one is for the pdf/ps/eps graph to be included. The
76  // print_cmd is saved as old_print_cmd. Then the second drawnow()
77  // outputs the tex-file and the graphic filename to be included is
78  // extracted from old_print_cmd.
79  std::string include_graph;
80  std::size_t found_redirect = old_print_cmd.find (">");
81  if (found_redirect != std::string::npos)
82  include_graph = old_print_cmd.substr (found_redirect + 1);
83  else
84  include_graph = old_print_cmd;
85  std::size_t n_begin = include_graph.find_first_not_of (" ");
86  if (n_begin != std::string::npos)
87  {
88  std::size_t n_end = include_graph.find_last_not_of (" ");
89  include_graph = include_graph.substr (n_begin,
90  n_end - n_begin + 1);
91  }
92  else
93  include_graph = "foobar-inc";
94  buffsize += 1024*1024;
95  gl2psBeginPage ("glps_renderer figure", "Octave", viewport,
96  gl2ps_term, gl2ps_sort,
97  (GL2PS_SILENT | GL2PS_SIMPLE_LINE_OFFSET
98  | GL2PS_NO_BLENDING | GL2PS_OCCLUSION_CULL
99  | GL2PS_BEST_ROOT | gl2ps_text
100  | GL2PS_NO_PS3_SHADING),
101  GL_RGBA, 0, NULL, 0, 0, 0,
102  buffsize, fp, include_graph.c_str ());
103  old_print_cmd = print_cmd;
105  state = gl2psEndPage ();
106  }
107 
108  in_draw = 0;
109  }
110  else
112 }
113 
114 int
115 glps_renderer::alignment_to_mode (int ha, int va) const
116 {
117  int gl2psa=GL2PS_TEXT_BL;
118  if (ha == 0)
119  {
120  if (va == 0 || va == 3)
121  gl2psa=GL2PS_TEXT_BL;
122  else if (va == 2)
123  gl2psa=GL2PS_TEXT_TL;
124  else if (va == 1)
125  gl2psa=GL2PS_TEXT_CL;
126  }
127  else if (ha == 2)
128  {
129  if (va == 0 || va == 3)
130  gl2psa=GL2PS_TEXT_BR;
131  else if (va == 2)
132  gl2psa=GL2PS_TEXT_TR;
133  else if (va == 1)
134  gl2psa=GL2PS_TEXT_CR;
135  }
136  else if (ha == 1)
137  {
138  if (va == 0 || va == 3)
139  gl2psa=GL2PS_TEXT_B;
140  else if (va == 2)
141  gl2psa=GL2PS_TEXT_T;
142  else if (va == 1)
143  gl2psa=GL2PS_TEXT_C;
144  }
145  return gl2psa;
146 }
147 
148 Matrix
149 glps_renderer::render_text (const std::string& txt,
150  double x, double y, double z,
151  int ha, int va, double rotation)
152 {
153  if (txt.empty ())
154  return Matrix (1, 4, 0.0);
155 
156  glRasterPos3d (x, y, z);
157  gl2psTextOpt (txt.c_str (), fontname.c_str (), fontsize,
158  alignment_to_mode (ha, va), rotation);
159 
160  // FIXME?
161  // We have no way of getting a bounding box from gl2ps, so we use freetype.
162  Matrix bbox;
163  uint8NDArray pixels;
164  text_to_pixels (txt, pixels, bbox, 0, 0, rotation);
165  return bbox;
166 }
167 
168 void
169 glps_renderer::set_font (const base_properties& props)
170 {
172 
173  fontsize = props.get ("fontsize").double_value ();
174 
175  caseless_str fn = props.get ("fontname").string_value ();
176  fontname = "";
177  if (fn == "times" || fn == "times-roman")
178  fontname = "Times-Roman";
179  else if (fn == "courier")
180  fontname = "Courier";
181  else if (fn == "symbol")
182  fontname = "Symbol";
183  else if (fn == "zapfdingbats")
184  fontname = "ZapfDingbats";
185  else
186  fontname = "Helvetica";
187 
188  // FIXME: add support for bold and italic
189 }
190 
191 template <typename T>
192 static void
193 draw_pixels (GLsizei w, GLsizei h, GLenum format, const T *data)
194 {
195  OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*w*h);
196 
197  for (int i = 0; i < 3*w*h; i++)
198  a[i] = data[i];
199 
200  gl2psDrawPixels (w, h, 0, 0, format, GL_FLOAT, a);
201 }
202 
203 void
204 glps_renderer::draw_pixels (GLsizei w, GLsizei h, GLenum format,
205  GLenum type, const GLvoid *data)
206 {
207  if (type == GL_UNSIGNED_SHORT)
208  ::draw_pixels (w, h, format, static_cast<const GLushort *> (data));
209  else if (type == GL_UNSIGNED_BYTE)
210  ::draw_pixels (w, h, format, static_cast<const GLubyte *> (data));
211  else
212  gl2psDrawPixels (w, h, 0, 0, format, type, data);
213 }
214 
215 void
216 glps_renderer::draw_text (const text::properties& props)
217 {
218  if (props.get_string ().is_empty ())
219  return;
220 
221  set_font (props);
222  set_color (props.get_color_rgb ());
223 
224  const Matrix pos = get_transform ().scale (props.get_data_position ());
225  int halign = 0, valign = 0;
226 
227  if (props.horizontalalignment_is ("center"))
228  halign = 1;
229  else if (props.horizontalalignment_is ("right"))
230  halign = 2;
231 
232  if (props.verticalalignment_is ("top"))
233  valign = 2;
234  else if (props.verticalalignment_is ("baseline"))
235  valign = 3;
236  else if (props.verticalalignment_is ("middle"))
237  valign = 1;
238 
239  // FIXME: handle margin and surrounding box
240 
241  glRasterPos3d (pos(0), pos(1), pos.numel () > 2 ? pos(2) : 0.0);
242 
243  octave_value string_prop = props.get_string ();
244 
245  string_vector sv = string_prop.all_strings ();
246 
247  std::string s = sv.join ("\n");
248 
249  gl2psTextOpt (s.c_str (), fontname.c_str (), fontsize,
250  alignment_to_mode (halign, valign), props.get_rotation ());
251 }
252 
253 #endif