Mercurial > octave-nkf
view libinterp/dldfcn/__osmesa_print__.cc @ 19895:19755f4fc851
maint: Cleanup C++ code to follow Octave coding conventions.
Try to wrap long lines to < 80 characters.
Use GNU style and don't indent first brace of function definition.
"case" statement is aligned flush left with brace of switch stmt.
Remove trailing '\' line continuation from the end of #define macros.
Use 2 spaces for indent.
* files-dock-widget.cc, history-dock-widget.cc, main-window.cc, octave-cmd.cc,
octave-dock-widget.cc, octave-gui.cc, resource-manager.cc, settings-dialog.cc,
shortcut-manager.cc, welcome-wizard.cc, workspace-view.cc, cellfun.cc, data.cc,
debug.cc, debug.h, dirfns.cc, error.h, file-io.cc, gl-render.cc, gl-render.h,
gl2ps-renderer.h, graphics.cc, graphics.in.h, help.cc, input.cc, load-path.cc,
load-path.h, lookup.cc, lu.cc, oct-stream.cc, octave-default-image.h,
ordschur.cc, pr-output.cc, qz.cc, strfns.cc, symtab.cc, symtab.h, sysdep.cc,
variables.cc, zfstream.h, __fltk_uigetfile__.cc, __init_fltk__.cc,
__magick_read__.cc, __osmesa_print__.cc, audiodevinfo.cc, ov-classdef.cc,
ov-classdef.h, ov-fcn.h, ov-float.cc, ov-flt-complex.cc, ov-java.cc,
ov-range.cc, ov-re-mat.cc, ov-usr-fcn.h, ov.cc, op-int.h, options-usage.h,
pt-eval.cc, Array-C.cc, Array-fC.cc, Array.cc, Array.h, PermMatrix.cc,
Sparse.cc, chMatrix.h, dSparse.cc, dim-vector.h, bsxfun-decl.h, bsxfun-defs.cc,
oct-norm.cc, Sparse-op-defs.h, oct-inttypes.cc, oct-inttypes.h, main.in.cc,
mkoctfile.in.cc: Cleanup C++ code to follow Octave coding conventions.
author | Rik <rik@octave.org> |
---|---|
date | Wed, 25 Feb 2015 11:55:49 -0800 |
parents | ca7599ae464d |
children | ed5ee3f610db |
line wrap: on
line source
/* Copyright (C) 2015 Andreas Weber <andy.weber.aw@gmail.com> This file is part of Octave. Octave is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Octave is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Octave; see the file COPYING. If not, see <http://www.gnu.org/licenses/>. This code is based on Brian Pauls' src/osdemos/osdemo.c from git://anongit.freedesktop.org/mesa/demos */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #include "oct-locbuf.h" #include "unwind-prot.h" #include "defun-dld.h" #include "gl-render.h" #include "gl2ps-renderer.h" #include "graphics.h" #include "gripes.h" #if defined (HAVE_OSMESA_H) #include "osmesa.h" #elif defined (HAVE_GL_OSMESA_H) #include "GL/osmesa.h" #endif #if defined (HAVE_OSMESA) && defined (HAVE_OPENGL) static void close_fcn (FILE *f) { gnulib::fclose (f); } static void reset_visibility (figure::properties *fp) { fp->set_visible ("on"); } #endif DEFUN_DLD(__osmesa_print__, args, , "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {} __osmesa_print__ (@var{h}, @var{file}, @var{term})\n\ @deftypefnx {Loadable Function} {@var{img} =} __osmesa_print__ (@var{h})\n\ Print figure @var{h} using OSMesa and gl2ps for vector formats.\n\ \n\ This is a private internal function.\n\ \n\ The first method calls gl2ps with the appropriate @var{term} and writes\n\ the output of gl2ps to @var{file}. If the first character of @var{file}\n\ is @qcode{|}, then a process is started and the output of gl2ps is piped\n\ to it.\n\ \n\ Valid options for @var{term}, which can be concatenated in one string, are:\n\ \n\ @table @asis\n\ @item @qcode{eps}, @qcode{pdf}, @qcode{ps}, @qcode{svg}, @qcode{pgf}, @qcode{tex}\n\ Select output format.\n\ \n\ @item @qcode{is2D}\n\ Use GL2PS_SIMPLE_SORT instead of GL2PS_BSP_SORT as Z-depth sorting algorithm.\n\ \n\ @item @qcode{notext}\n\ Don't render text.\n\ @end table\n\ \n\ The second method doesn't use gl2ps and returns a RGB image in @var{img}\n\ instead.\n\ \n\ @end deftypefn") { octave_value_list retval; #if ! defined (HAVE_OSMESA) gripe_disabled_feature ("__osmesa_print__", "offscreen rendering"); #else int nargin = args.length (); if (! (nargin == 1 || nargin == 3)) { print_usage (); return retval; } if (nargin == 3) { if (! (args(1).is_string () && args(2).is_string ())) { error ("__osmesa_print__: FILE and TERM has to be strings"); return retval; } #ifndef HAVE_GL2PS_H error ("__osmesa_print__: Octave has been compiled without gl2ps"); return retval; #endif } int h = args(0).double_value (); graphics_object fobj = gh_manager::get_object (h); if (! (fobj && fobj.isa ("figure"))) { error ("__osmesa_print__: H has to be a valid figure handle"); return retval; } figure::properties& fp = dynamic_cast<figure::properties&> (fobj.get_properties ()); bool internal = true; Matrix bb = fp.get_boundingbox (internal); int Width = bb(2); int Height = bb(3); // Create an RGBA-mode context, specify Z=16, stencil=0, accum=0 sizes OSMesaContext ctx = OSMesaCreateContextExt (OSMESA_RGBA, 16, 0, 0, NULL); if (! ctx) { error ("__osmesa_print__: OSMesaCreateContext failed!\n"); return retval; } // Allocate the image buffer OCTAVE_LOCAL_BUFFER (GLubyte, buffer, 4 * Width * Height); // Bind the buffer to the context and make it current if (! OSMesaMakeCurrent (ctx, buffer, GL_UNSIGNED_BYTE, Width, Height)) { error ("__osmesa_print__: OSMesaMakeCurrent failed!\n"); return retval; } // Test for a bug in OSMesa with version < 9.0 // // Unfortunately the macros OSMESA_MAJOR_VERSION and // OSMESA_MINOR_VERSION weren't updated between many releases and // can't be used for detection. (Version 8.0 until 9.1.4 all return // MAJOR 6, MINOR 5) int z, s; glGetIntegerv (GL_DEPTH_BITS, &z); glGetIntegerv (GL_STENCIL_BITS, &s); if (z != 16 || s != 0) error ("__osmesa_print__: Depth and stencil doesn't match," " are you sure you are using OSMesa >= 9.0?"); unwind_protect outer_frame; bool v = fp.is_visible (); if (v) { outer_frame.add_fcn (reset_visibility, &fp); fp.set_visible ("off"); } if (nargin == 3) { // use gl2ps std::string file = args(1).string_value (); std::string term = args(2).string_value (); if (! error_state) { size_t pos = file.find_first_not_of ("|"); if (pos > 0) { // create process and pipe gl2ps output to it std::string cmd = file.substr (pos); gl2ps_print (fobj, cmd, term); } else { // write gl2ps output directly to file FILE *filep = gnulib::fopen (file.c_str (), "w"); if (filep) { unwind_protect frame; frame.add_fcn (close_fcn, filep); glps_renderer rend (filep, term); rend.draw (fobj, ""); // Make sure buffered commands are finished!!! glFinish (); } else error ("__osmesa_print__: Couldn't create file \"%s\"", file.c_str ()); } } } else { // return RGB image opengl_renderer rend; rend.draw (fobj); // Make sure buffered commands are finished!!! glFinish (); dim_vector dv (4, Width, Height); // FIXME: We expect that GLubyte is 1 Byte long. // Adapt code if this isn't always true assert (sizeof (GLubyte) == 1); uint8NDArray img (dv); unsigned char *p = reinterpret_cast<unsigned char*>(img.fortran_vec ()); memcpy (p, buffer, (4 * Width * Height)); Array<octave_idx_type> perm (dim_vector (3, 1)); perm(0) = 2; perm(1) = 1; perm(2) = 0; Array<idx_vector> idx (dim_vector (3, 1)); // Flip Y idx(0) = idx_vector::make_range (Height - 1, -1, Height); idx(1) = idx_vector::colon; // Remove alpha channel idx(2) = idx_vector (0, 3); retval = octave_value (img.permute (perm). index(idx)); } OSMesaDestroyContext (ctx); #endif return retval; } /* %!testif HAVE_OSMESA %! h = figure ("visible", "off"); %! fn = tempname (); %! sombrero (); %! __osmesa_print__ (h, fn, "svg"); %! assert (stat (fn).size, 2692270, -0.1); %! unlink (fn); %! img = __osmesa_print__ (h); %! assert (size (img), [get(h, "position")([4, 3]), 3]) %! ## Use pixel sum per RGB channel as fingerprint %! img_fp = squeeze (sum (sum (img), 2)); %! assert (img_fp, [52942515; 54167797; 56158178], -0.05); %!testif HAVE_OSMESA %! h = figure ("visible", "off"); %! fn = tempname (); %! plot (sin (0:0.1:2*pi)); %! __osmesa_print__ (h, fn, "svgis2d"); %! assert (stat (fn).size, 7438, -0.05); %! unlink (fn); %! img = __osmesa_print__ (h); %! assert (size (img), [get(h, "position")([4, 3]), 3]) %! ## Use pixel sum per RGB channel as fingerprint %! img_fp = squeeze (sum (sum (img), 2)); %! assert (img_fp, [59281711; 59281711; 59482179], -0.05); */