Mercurial > octave
changeset 26728:f034b29320ad
Use OpenGl textures to render image objects (bug #55632).
* gl-render.[h,cc] (opengl_renderer): Change the following data members to
protected rather than private and allow easy access from gl2ps_renderer:
xmin, xmax, ymin, ymax, zmin, zmax, m_devpixratio, xform.
(opengl_renderer::draw_pixels): Remove virtual methods.
(opengl_renderer::draw_image): Remove unnecessary manual clipping code. Make
use of an opengl_texture to draw pixels rather than glDrawPixels.
(opengl_texture::create): Add support for single and uint16 type pixel data.
* gl2ps-print.cc (gl2ps_renderer::draw_image): New overload. Dump here all the
manual clipping code, which is still necessary since gl2ps does not support
textures only emulates glDrawPixels.
* print.m: Set figure "__printing__" property first and reset last. Set figure
"__modified__" to "off" after resetting all properties.
author | Pantxo Diribarne <pantxo.diribarne@gmail.com> |
---|---|
date | Fri, 08 Feb 2019 18:07:33 +0100 |
parents | 88653f8d536d |
children | 75d79c39ac92 |
files | libinterp/corefcn/gl-render.cc libinterp/corefcn/gl-render.h libinterp/corefcn/gl2ps-print.cc scripts/plot/util/print.m |
diffstat | 4 files changed, 365 insertions(+), 326 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/gl-render.cc Wed Feb 13 15:38:23 2019 +0000 +++ b/libinterp/corefcn/gl-render.cc Fri Feb 08 18:07:33 2019 +0100 @@ -204,7 +204,7 @@ { const NDArray xdata = data.array_value (); - OCTAVE_LOCAL_BUFFER (float, a, (3*tw*th)); + OCTAVE_LOCAL_BUFFER (GLfloat, a, (3*tw*th)); for (int i = 0; i < h; i++) { @@ -216,13 +216,53 @@ } } - glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, GL_RGB, GL_FLOAT, a); + glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, GL_RGB, + GL_FLOAT, a); + } + + else if (data.is_single_type ()) + { + const FloatNDArray xdata = data.float_array_value (); + + OCTAVE_LOCAL_BUFFER (GLfloat, a, (3*tw*th)); + + for (int i = 0; i < h; i++) + { + for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3) + { + a[idx] = xdata(i,j,0); + a[idx+1] = xdata(i,j,1); + a[idx+2] = xdata(i,j,2); + } + } + + glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, GL_RGB, + GL_FLOAT, a); + } + else if (data.is_uint16_type ()) + { + const uint16NDArray xdata = data.uint16_array_value (); + + OCTAVE_LOCAL_BUFFER (GLushort, a, (3*tw*th)); + + for (int i = 0; i < h; i++) + { + for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3) + { + a[idx] = xdata(i,j,0); + a[idx+1] = xdata(i,j,1); + a[idx+2] = xdata(i,j,2); + } + } + + glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, + GL_RGB, GL_UNSIGNED_SHORT, a); } else if (data.is_uint8_type ()) { const uint8NDArray xdata = data.uint8_array_value (); - OCTAVE_LOCAL_BUFFER (octave_uint8, a, (3*tw*th)); + OCTAVE_LOCAL_BUFFER (GLubyte, a, (3*tw*th)); for (int i = 0; i < h; i++) { @@ -240,7 +280,7 @@ else { ok = false; - warning ("opengl_texture::create: invalid texture data type (double or uint8 required)"); + warning ("opengl_texture::create: invalid image data type, expected double, single, uint8, or uint16"); } if (ok) @@ -619,11 +659,11 @@ #endif opengl_renderer::opengl_renderer (opengl_functions& glfcns) - : m_glfcns (glfcns), toolkit (), xform (), xmin (), xmax (), ymin (), - ymax (), zmin (), zmax (), xZ1 (), xZ2 (), marker_id (), + : m_glfcns (glfcns), xmin (), xmax (), ymin (), ymax (), zmin (), zmax (), + m_devpixratio (1.), xform (), toolkit (), xZ1 (), xZ2 (), marker_id (), filled_marker_id (), camera_pos (), camera_dir (), view_vector (), interpreter ("none"), txt_renderer (), m_current_light (0), - m_max_lights (0), selecting (false), m_devpixratio (1.) + m_max_lights (0), selecting (false) { // This constructor will fail if we don't have OpenGL or if the data // types we assumed in our public interface aren't compatible with the @@ -3833,250 +3873,49 @@ dim_vector dv (cdata.dims ()); int h = dv(0); int w = dv(1); + double x0, x1, y0, y1; Matrix x = props.get_xdata ().matrix_value (); + double dx = 1.0; + if (w > 1) + dx = (x(1) - x(0)) / (w - 1); + + x0 = x(0)-dx/2; + x1 = x(1)+dx/2; + Matrix y = props.get_ydata ().matrix_value (); - - // Someone wants us to draw an empty image? No way. - if (x.isempty () || y.isempty ()) - return; - - // Sort x/ydata and mark flipped dimensions - bool xflip = false; - if (x(0) > x(1)) - { - std::swap (x(0), x(1)); - xflip = true; - } - else if (w > 1 && x(1) == x(0)) - x(1) = x(1) + (w-1); - - bool yflip = false; - if (y(0) > y(1)) - { - std::swap (y(0), y(1)); - yflip = true; - } - else if (h > 1 && y(1) == y(0)) - y(1) = y(1) + (h-1); - - const ColumnVector p0 = xform.transform (x(0), y(0), 0); - const ColumnVector p1 = xform.transform (x(1), y(1), 0); - - if (math::isnan (p0(0)) || math::isnan (p0(1)) - || math::isnan (p1(0)) || math::isnan (p1(1))) - { - warning ("opengl_renderer: image X,Y data too large to draw"); - return; - } - - // image pixel size in screen pixel units - float pix_dx, pix_dy; - // image pixel size in normalized units - float nor_dx, nor_dy; - - if (w > 1) - { - pix_dx = (p1(0) - p0(0)) / (w-1); - nor_dx = (x(1) - x(0)) / (w-1); - } - else - { - const ColumnVector p1w = xform.transform (x(1) + 1, y(1), 0); - pix_dx = p1w(0) - p0(0); - nor_dx = 1; - } - + double dy = 1.0; if (h > 1) - { - pix_dy = (p1(1) - p0(1)) / (h-1); - nor_dy = (y(1) - y(0)) / (h-1); - } - else - { - const ColumnVector p1h = xform.transform (x(1), y(1) + 1, 0); - pix_dy = p1h(1) - p0(1); - nor_dy = 1; - } - - // OpenGL won't draw any of the image if its origin is outside the - // viewport/clipping plane so we must do the clipping ourselves. - - int j0, j1, jj, i0, i1, ii; - j0 = 0, j1 = w; - i0 = 0, i1 = h; - - float im_xmin = x(0) - nor_dx/2; - float im_xmax = x(1) + nor_dx/2; - float im_ymin = y(0) - nor_dy/2; - float im_ymax = y(1) + nor_dy/2; - - // Clip to axes or viewport - bool do_clip = props.is_clipping (); - Matrix vp = get_viewport_scaled (); - - ColumnVector vp_lim_min = - xform.untransform (std::numeric_limits <float>::epsilon (), - std::numeric_limits <float>::epsilon ()); - ColumnVector vp_lim_max = xform.untransform (vp(2), vp(3)); - - if (vp_lim_min(0) > vp_lim_max(0)) - std::swap (vp_lim_min(0), vp_lim_max(0)); - - if (vp_lim_min(1) > vp_lim_max(1)) - std::swap (vp_lim_min(1), vp_lim_max(1)); - - float clip_xmin = - (do_clip ? (vp_lim_min(0) > xmin ? vp_lim_min(0) : xmin) : vp_lim_min(0)); - float clip_ymin = - (do_clip ? (vp_lim_min(1) > ymin ? vp_lim_min(1) : ymin) : vp_lim_min(1)); - - float clip_xmax = - (do_clip ? (vp_lim_max(0) < xmax ? vp_lim_max(0) : xmax) : vp_lim_max(0)); - float clip_ymax = - (do_clip ? (vp_lim_max(1) < ymax ? vp_lim_max(1) : ymax) : vp_lim_max(1)); - - if (im_xmin < clip_xmin) - j0 += (clip_xmin - im_xmin)/nor_dx + 1; - if (im_xmax > clip_xmax) - j1 -= (im_xmax - clip_xmax)/nor_dx; - - if (im_ymin < clip_ymin) - i0 += (clip_ymin - im_ymin)/nor_dy + 1; - if (im_ymax > clip_ymax) - i1 -= (im_ymax - clip_ymax)/nor_dy; - - if (i0 >= i1 || j0 >= j1) - return; - - m_glfcns.glPixelZoom (m_devpixratio * pix_dx, - - m_devpixratio * pix_dy); - m_glfcns.glRasterPos3d (im_xmin + nor_dx*j0, im_ymin + nor_dy*i0, 0); - - // by default this is 4 - m_glfcns.glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + dy = (y(1) - y(0)) / (h - 1); + + y0 = y(0)-dy/2; + y1 = y(1)+dy/2; // Expect RGB data if (dv.ndims () == 3 && dv(2) == 3) { - if (cdata.is_double_type ()) - { - const NDArray xcdata = cdata.array_value (); - - OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0)); - - for (int i = i0; i < i1; i++) - { - for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) - { - if (! yflip) - ii = i; - else - ii = h - i - 1; - - if (! xflip) - jj = j; - else - jj = w - j - 1; - - a[idx] = xcdata(ii,jj,0); - a[idx+1] = xcdata(ii,jj,1); - a[idx+2] = xcdata(ii,jj,2); - } - } - - draw_pixels (j1-j0, i1-i0, a); - - } - else if (cdata.is_single_type ()) - { - const FloatNDArray xcdata = cdata.float_array_value (); - - OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0)); - - for (int i = i0; i < i1; i++) - { - for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) - { - if (! yflip) - ii = i; - else - ii = h - i - 1; - - if (! xflip) - jj = j; - else - jj = w - j - 1; - - a[idx] = xcdata(ii,jj,0); - a[idx+1] = xcdata(ii,jj,1); - a[idx+2] = xcdata(ii,jj,2); - } - } - - draw_pixels (j1-j0, i1-i0, a); - - } - else if (cdata.is_uint8_type ()) - { - const uint8NDArray xcdata = cdata.uint8_array_value (); - - OCTAVE_LOCAL_BUFFER (GLubyte, a, 3*(j1-j0)*(i1-i0)); - - for (int i = i0; i < i1; i++) - { - for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) - { - if (! yflip) - ii = i; - else - ii = h - i - 1; - - if (! xflip) - jj = j; - else - jj = w - j - 1; - - a[idx] = xcdata(ii,jj,0); - a[idx+1] = xcdata(ii,jj,1); - a[idx+2] = xcdata(ii,jj,2); - } - } - - draw_pixels (j1-j0, i1-i0, a); - - } - else if (cdata.is_uint16_type ()) - { - const uint16NDArray xcdata = cdata.uint16_array_value (); - - OCTAVE_LOCAL_BUFFER (GLushort, a, 3*(j1-j0)*(i1-i0)); - - for (int i = i0; i < i1; i++) - { - for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) - { - if (! yflip) - ii = i; - else - ii = h - i - 1; - - if (! xflip) - jj = j; - else - jj = w - j - 1; - - a[idx] = xcdata(ii,jj,0); - a[idx+1] = xcdata(ii,jj,1); - a[idx+2] = xcdata(ii,jj,2); - } - } - - draw_pixels (j1-j0, i1-i0, a); - - } - else - warning ("opengl_renderer: invalid image data type (expected double, single, uint8, or uint16)"); + opengl_texture tex (m_glfcns); + tex = opengl_texture::create (m_glfcns, cdata); + m_glfcns.glColor4d (1.0, 1.0, 1.0, 1.0); + + m_glfcns.glEnable (GL_TEXTURE_2D); + + m_glfcns.glBegin (GL_QUADS); + + tex.tex_coord (0.0, 0.0); + m_glfcns.glVertex3d (x0, y0, 0.0); + + tex.tex_coord (1.0, 0.0); + m_glfcns.glVertex3d (x1, y0, 0.0); + + tex.tex_coord (1.0, 1.0); + m_glfcns.glVertex3d (x1, y1, 0.0); + + tex.tex_coord (0.0, 1.0); + m_glfcns.glVertex3d (x0, y1, 0.0); + + m_glfcns.glEnd (); + m_glfcns.glDisable (GL_TEXTURE_2D); } else warning ("opengl_renderer: invalid image size (expected MxNx3 or MxN)"); @@ -4145,69 +3984,6 @@ } void - opengl_renderer::draw_pixels (int width, int height, const float *data) - { -#if defined (HAVE_OPENGL) - - m_glfcns.glDrawPixels (width, height, GL_RGB, GL_FLOAT, data); - -#else - - octave_unused_parameter (width); - octave_unused_parameter (height); - octave_unused_parameter (data); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); - -#endif - } - - void - opengl_renderer::draw_pixels (int width, int height, const uint8_t *data) - { -#if defined (HAVE_OPENGL) - - m_glfcns.glDrawPixels (width, height, GL_RGB, GL_UNSIGNED_BYTE, data); - -#else - - octave_unused_parameter (width); - octave_unused_parameter (height); - octave_unused_parameter (data); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); - -#endif - } - - void - opengl_renderer::draw_pixels (int width, int height, const uint16_t *data) - { -#if defined (HAVE_OPENGL) - - m_glfcns.glDrawPixels (width, height, GL_RGB, GL_UNSIGNED_SHORT, data); - -#else - - octave_unused_parameter (width); - octave_unused_parameter (height); - octave_unused_parameter (data); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); - -#endif - } - - void opengl_renderer::set_color (const Matrix& c) { #if defined (HAVE_OPENGL)
--- a/libinterp/corefcn/gl-render.h Wed Feb 13 15:38:23 2019 +0000 +++ b/libinterp/corefcn/gl-render.h Fri Feb 08 18:07:33 2019 +0100 @@ -140,10 +140,6 @@ double x, double y, double z, int halign, int valign, double rotation = 0.0); - virtual void draw_pixels (int w, int h, const float *data); - virtual void draw_pixels (int w, int h, const uint8_t *data); - virtual void draw_pixels (int w, int h, const uint16_t *data); - virtual void render_grid (const double linewidth, const std::string& gridstyle, const Matrix& gridcolor, const double gridalpha, @@ -212,19 +208,22 @@ opengl_functions& m_glfcns; + // axis limits in model scaled coordinate + double xmin, xmax; + double ymin, ymax; + double zmin, zmax; + + // Factor used for translating Octave pixels to actual device pixels + double m_devpixratio; + + // axes transformation data + graphics_xform xform; + private: // The graphics toolkit associated with the figure being rendered. graphics_toolkit toolkit; - // axes transformation data - graphics_xform xform; - - // axis limits in model scaled coordinate - double xmin, xmax; - double ymin, ymax; - double zmin, zmax; - // Z projection limits in windows coordinate double xZ1, xZ2; @@ -246,9 +245,6 @@ // Indicate we are drawing for selection purpose bool selecting; - // Factor used for translating Octave pixels to actual device pixels - double m_devpixratio; - private: class patch_tesselator; };
--- a/libinterp/corefcn/gl2ps-print.cc Wed Feb 13 15:38:23 2019 +0000 +++ b/libinterp/corefcn/gl2ps-print.cc Fri Feb 08 18:07:33 2019 +0100 @@ -175,6 +175,7 @@ void draw_text (const text::properties& props); + void draw_image (const image::properties& props); void draw_pixels (int w, int h, const float *data); void draw_pixels (int w, int h, const uint8_t *data); void draw_pixels (int w, int h, const uint16_t *data); @@ -1027,6 +1028,266 @@ } void + gl2ps_renderer::draw_image (const image::properties& props) + { + octave_value cdata = props.get_color_data (); + dim_vector dv (cdata.dims ()); + int h = dv(0); + int w = dv(1); + + Matrix x = props.get_xdata ().matrix_value (); + Matrix y = props.get_ydata ().matrix_value (); + + // Someone wants us to draw an empty image? No way. + if (x.isempty () || y.isempty ()) + return; + + // Sort x/ydata and mark flipped dimensions + bool xflip = false; + if (x(0) > x(1)) + { + std::swap (x(0), x(1)); + xflip = true; + } + else if (w > 1 && x(1) == x(0)) + x(1) = x(1) + (w-1); + + bool yflip = false; + if (y(0) > y(1)) + { + std::swap (y(0), y(1)); + yflip = true; + } + else if (h > 1 && y(1) == y(0)) + y(1) = y(1) + (h-1); + + + const ColumnVector p0 = xform.transform (x(0), y(0), 0); + const ColumnVector p1 = xform.transform (x(1), y(1), 0); + + if (math::isnan (p0(0)) || math::isnan (p0(1)) + || math::isnan (p1(0)) || math::isnan (p1(1))) + { + warning ("opengl_renderer: image X,Y data too large to draw"); + return; + } + + // image pixel size in screen pixel units + float pix_dx, pix_dy; + // image pixel size in normalized units + float nor_dx, nor_dy; + + if (w > 1) + { + pix_dx = (p1(0) - p0(0)) / (w-1); + nor_dx = (x(1) - x(0)) / (w-1); + } + else + { + const ColumnVector p1w = xform.transform (x(1) + 1, y(1), 0); + pix_dx = p1w(0) - p0(0); + nor_dx = 1; + } + + if (h > 1) + { + pix_dy = (p1(1) - p0(1)) / (h-1); + nor_dy = (y(1) - y(0)) / (h-1); + } + else + { + const ColumnVector p1h = xform.transform (x(1), y(1) + 1, 0); + pix_dy = p1h(1) - p0(1); + nor_dy = 1; + } + + // OpenGL won't draw any of the image if its origin is outside the + // viewport/clipping plane so we must do the clipping ourselves. + + int j0, j1, jj, i0, i1, ii; + j0 = 0, j1 = w; + i0 = 0, i1 = h; + + float im_xmin = x(0) - nor_dx/2; + float im_xmax = x(1) + nor_dx/2; + float im_ymin = y(0) - nor_dy/2; + float im_ymax = y(1) + nor_dy/2; + + // Clip to axes or viewport + bool do_clip = props.is_clipping (); + Matrix vp = get_viewport_scaled (); + + ColumnVector vp_lim_min = + xform.untransform (std::numeric_limits <float>::epsilon (), + std::numeric_limits <float>::epsilon ()); + ColumnVector vp_lim_max = xform.untransform (vp(2), vp(3)); + + if (vp_lim_min(0) > vp_lim_max(0)) + std::swap (vp_lim_min(0), vp_lim_max(0)); + + if (vp_lim_min(1) > vp_lim_max(1)) + std::swap (vp_lim_min(1), vp_lim_max(1)); + + float clip_xmin = + (do_clip ? (vp_lim_min(0) > xmin ? vp_lim_min(0) : xmin) : vp_lim_min(0)); + float clip_ymin = + (do_clip ? (vp_lim_min(1) > ymin ? vp_lim_min(1) : ymin) : vp_lim_min(1)); + + float clip_xmax = + (do_clip ? (vp_lim_max(0) < xmax ? vp_lim_max(0) : xmax) : vp_lim_max(0)); + float clip_ymax = + (do_clip ? (vp_lim_max(1) < ymax ? vp_lim_max(1) : ymax) : vp_lim_max(1)); + + if (im_xmin < clip_xmin) + j0 += (clip_xmin - im_xmin)/nor_dx + 1; + if (im_xmax > clip_xmax) + j1 -= (im_xmax - clip_xmax)/nor_dx; + + if (im_ymin < clip_ymin) + i0 += (clip_ymin - im_ymin)/nor_dy + 1; + if (im_ymax > clip_ymax) + i1 -= (im_ymax - clip_ymax)/nor_dy; + + if (i0 >= i1 || j0 >= j1) + return; + + float zoom_x; + m_glfcns.glGetFloatv (GL_ZOOM_X, &zoom_x); + float zoom_y; + m_glfcns.glGetFloatv (GL_ZOOM_Y, &zoom_y); + + m_glfcns.glPixelZoom (m_devpixratio * pix_dx, + - m_devpixratio * pix_dy); + m_glfcns.glRasterPos3d (im_xmin + nor_dx*j0, im_ymin + nor_dy*i0, 0); + + // Expect RGB data + if (dv.ndims () == 3 && dv(2) == 3) + { + if (cdata.is_double_type ()) + { + const NDArray xcdata = cdata.array_value (); + + OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0)); + + for (int i = i0; i < i1; i++) + { + for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) + { + if (! yflip) + ii = i; + else + ii = h - i - 1; + + if (! xflip) + jj = j; + else + jj = w - j - 1; + + a[idx] = xcdata(ii,jj,0); + a[idx+1] = xcdata(ii,jj,1); + a[idx+2] = xcdata(ii,jj,2); + } + } + + draw_pixels (j1-j0, i1-i0, a); + + } + else if (cdata.is_single_type ()) + { + const FloatNDArray xcdata = cdata.float_array_value (); + + OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0)); + + for (int i = i0; i < i1; i++) + { + for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) + { + if (! yflip) + ii = i; + else + ii = h - i - 1; + + if (! xflip) + jj = j; + else + jj = w - j - 1; + + a[idx] = xcdata(ii,jj,0); + a[idx+1] = xcdata(ii,jj,1); + a[idx+2] = xcdata(ii,jj,2); + } + } + + draw_pixels (j1-j0, i1-i0, a); + + } + else if (cdata.is_uint8_type ()) + { + const uint8NDArray xcdata = cdata.uint8_array_value (); + + OCTAVE_LOCAL_BUFFER (GLubyte, a, 3*(j1-j0)*(i1-i0)); + + for (int i = i0; i < i1; i++) + { + for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) + { + if (! yflip) + ii = i; + else + ii = h - i - 1; + + if (! xflip) + jj = j; + else + jj = w - j - 1; + + a[idx] = xcdata(ii,jj,0); + a[idx+1] = xcdata(ii,jj,1); + a[idx+2] = xcdata(ii,jj,2); + } + } + + draw_pixels (j1-j0, i1-i0, a); + + } + else if (cdata.is_uint16_type ()) + { + const uint16NDArray xcdata = cdata.uint16_array_value (); + + OCTAVE_LOCAL_BUFFER (GLushort, a, 3*(j1-j0)*(i1-i0)); + + for (int i = i0; i < i1; i++) + { + for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) + { + if (! yflip) + ii = i; + else + ii = h - i - 1; + + if (! xflip) + jj = j; + else + jj = w - j - 1; + + a[idx] = xcdata(ii,jj,0); + a[idx+1] = xcdata(ii,jj,1); + a[idx+2] = xcdata(ii,jj,2); + } + } + + draw_pixels (j1-j0, i1-i0, a); + + } + else + warning ("opengl_renderer: invalid image data type (expected double, single, uint8, or uint16)"); + + m_glfcns.glPixelZoom (zoom_x, zoom_y); + + } + } + + void gl2ps_renderer::draw_pixels (int w, int h, const float *data) { // Clip data between 0 and 1 for float values
--- a/scripts/plot/util/print.m Wed Feb 13 15:38:23 2019 +0000 +++ b/scripts/plot/util/print.m Fri Feb 08 18:07:33 2019 +0100 @@ -466,6 +466,13 @@ drawnow (); + ## Set the __printing__ property first + props(1).h = opts.figure; + props(1).name = "__printing__"; + props(1).value = {"off"}; + set (opts.figure, "__printing__", "on"); + nfig += 1; + ## print() requires children of axes to have units = "normalized", or "data" hobj = findall (opts.figure, "-not", "type", "figure", ... "-not", "type", "axes", "-property", "units", ... @@ -552,13 +559,10 @@ ## graphics toolkit translates figure position to eps bbox (points) fpos = get (opts.figure, "position"); props(end+1).h = opts.figure; - props(end).name = "__printing__"; - props(end).value = {"off"}; - props(end+1).h = opts.figure; props(end).name = "position"; props(end).value = {fpos}; fpos(3:4) = opts.canvas_size; - set (opts.figure, "__printing__", "on", "position", fpos); + set (opts.figure, "position", fpos); nfig += 1; ## Implement InvertHardCopy option @@ -727,6 +731,9 @@ endfor endif + ## Avoid a redraw since the figure should not have changed + set (gcf, "__modified__", "off"); + ## Unlink temporary files for n = 1:numel (opts.unlink) [status, output] = unlink (opts.unlink{n}); @@ -740,7 +747,6 @@ if (isfigure (orig_figure)) set (0, "currentfigure", orig_figure); endif - endfunction function cmd = epstool (opts, filein, fileout)