Mercurial > hg > octave-nkf
diff src/gl-render.cc @ 9403:4af6e29449c1
[mq]: graphics_text_engine
author | Michael Goffioul <michael.goffioul@gmail.com> |
---|---|
date | Fri, 26 Jun 2009 21:12:09 +0100 |
parents | eb63fbe60fab |
children | 7cc35bc348cc |
line wrap: on
line diff
--- a/src/gl-render.cc +++ b/src/gl-render.cc @@ -26,9 +26,13 @@ #if defined (HAVE_OPENGL) +#include <iostream> + #include <lo-mappers.h> #include "oct-locbuf.h" #include "gl-render.h" +#include "txt-eng.h" +#include "txt-eng-ft.h" #define LIGHT_MODE GL_FRONT_AND_BACK @@ -540,6 +544,8 @@ draw (dynamic_cast<const patch::properties&> (props)); else if (go.isa ("hggroup")) draw (dynamic_cast<const hggroup::properties&> (props)); + else if (go.isa ("text")) + draw (dynamic_cast<const text::properties&> (props)); else warning ("opengl_renderer: cannot render object of type `%s'", props.graphics_object_name ().c_str ()); @@ -555,6 +561,7 @@ glEnable (GL_DEPTH_TEST); glDepthFunc (GL_LEQUAL); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glAlphaFunc (GL_GREATER, 0.0f); glEnable (GL_NORMALIZE); if (props.is___enhanced__ ()) @@ -874,6 +881,8 @@ std::string gridstyle = props.get_gridlinestyle (); std::string minorgridstyle = props.get_minorgridlinestyle (); + set_font (props); + // X grid if (visible && xstate != AXE_DEPTH_DIR) @@ -884,8 +893,7 @@ Matrix xticks = xform.xscale (props.get_xtick ().matrix_value ()); // FIXME: use pre-computed minor ticks Matrix xmticks; - // FIXME: use xticklabels property - string_vector xticklabels; + string_vector xticklabels = props.get_xticklabel ().all_strings (); int wmax = 0, hmax = 0; bool tick_along_z = xisinf (fy); Matrix tickpos (xticks.numel (), 3); @@ -957,7 +965,27 @@ glEnd (); } - // FIXME: tick texts + // tick texts + if (xticklabels.numel () > 0) + { + int n = std::min (xticklabels.numel (), xticks.numel ()); + int halign = (xstate == AXE_HORZ_DIR ? 1 : (xySym ? 0 : 2)); + int valign = (xstate == AXE_VERT_DIR + ? 1 + : (zd*zv(2) <= 0 && !x2Dtop ? 2 : 0)); + + for (int i = 0; i < n; i++) + { + // FIXME: as tick text is transparent, shouldn't be + // drawn after axes object, for correct rendering? + Matrix b = draw_text (xticklabels(i), + tickpos(i,0), tickpos(i,1), tickpos(i,2), + halign, valign); + + wmax = std::max (wmax, static_cast<int> (b(2))); + hmax = std::max (hmax, static_cast<int> (b(3))); + } + } // minor grid lines if (do_xminorgrid) @@ -1026,6 +1054,8 @@ text::properties& xlabel_props = reinterpret_cast<text::properties&> (gh_manager::get_object (props.get_xlabel ()).get_properties ()); + xlabel_props.set_visible ("on"); + // FIXME: auto-positioning should be disabled if the // label has been positioned manually if (! xlabel_props.get_string ().empty ()) @@ -1060,6 +1090,10 @@ xlabel_props.set_rotation (angle); } } + else + { + gh_manager::get_object (props.get_xlabel ()).set ("visible", "off"); + } // Y grid @@ -1071,8 +1105,7 @@ Matrix yticks = xform.yscale (props.get_ytick ().matrix_value ()); // FIXME: use pre-computed minor ticks Matrix ymticks; - // FIXME: use yticklabels property - string_vector yticklabels; + string_vector yticklabels = props.get_yticklabel ().all_strings (); int wmax = 0, hmax = 0; bool tick_along_z = xisinf (fx); Matrix tickpos (yticks.numel (), 3); @@ -1144,7 +1177,25 @@ glEnd (); } - // FIXME: tick texts + // tick texts + if (yticklabels.numel () > 0) + { + int n = std::min (yticklabels.numel (), yticks.numel ()); + int halign = (ystate == AXE_HORZ_DIR ? 1 : (!xySym || y2Dright ? 0 : 2)); + int valign = (ystate == AXE_VERT_DIR ? 1 : (zd*zv(2) <= 0 ? 2 : 0)); + + for (int i = 0; i < n; i++) + { + // FIXME: as tick text is transparent, shouldn't be + // drawn after axes object, for correct rendering? + Matrix b = draw_text (yticklabels(i), + tickpos(i,0), tickpos(i,1), tickpos(i,2), + halign, valign); + + wmax = std::max (wmax, static_cast<int> (b(2))); + hmax = std::max (hmax, static_cast<int> (b(3))); + } + } // minor grid lines if (do_yminorgrid) @@ -1213,6 +1264,8 @@ text::properties& ylabel_props = reinterpret_cast<text::properties&> (gh_manager::get_object (props.get_ylabel ()).get_properties ()); + ylabel_props.set_visible ("on"); + // FIXME: auto-positioning should be disabled if the // label has been positioned manually if (! ylabel_props.get_string ().empty ()) @@ -1247,6 +1300,10 @@ ylabel_props.set_rotation (angle); } } + else + { + gh_manager::get_object (props.get_ylabel ()).set ("visible", "off"); + } // Z Grid @@ -1258,8 +1315,7 @@ Matrix zticks = xform.zscale (props.get_ztick ().matrix_value ()); // FIXME: use pre-computed minor ticks Matrix zmticks; - // FIXME: use zticklabels property - string_vector zticklabels; + string_vector zticklabels = props.get_zticklabel ().all_strings (); int wmax = 0, hmax = 0; Matrix tickpos (zticks.numel (), 3); @@ -1364,6 +1420,24 @@ } // FIXME: tick texts + if (zticklabels.numel () > 0) + { + int n = std::min (zticklabels.numel (), zticks.numel ()); + int halign = 2; + int valign = (zstate == AXE_VERT_DIR ? 1 : (zd*zv(2) < 0 ? 3 : 2)); + + for (int i = 0; i < n; i++) + { + // FIXME: as tick text is transparent, shouldn't be + // drawn after axes object, for correct rendering? + Matrix b = draw_text (zticklabels(i), + tickpos(i,0), tickpos(i,1), tickpos(i,2), + halign, valign); + + wmax = std::max (wmax, static_cast<int> (b(2))); + hmax = std::max (hmax, static_cast<int> (b(3))); + } + } // minor grid lines if (do_zminorgrid) @@ -1457,6 +1531,8 @@ text::properties& zlabel_props = reinterpret_cast<text::properties&> (gh_manager::get_object (props.get_zlabel ()).get_properties ()); + zlabel_props.set_visible ("on"); + // FIXME: auto-positioning should be disabled if the // label has been positioned manually if (! zlabel_props.get_string ().empty ()) @@ -1512,6 +1588,10 @@ zlabel_props.set_rotation (angle); } } + else + { + gh_manager::get_object (props.get_zlabel ()).set ("visible", "off"); + } set_linestyle ("-"); @@ -1537,7 +1617,7 @@ if (antialias == GL_TRUE) glEnable (GL_LINE_SMOOTH); - Matrix children = props.get_children (); + Matrix children = props.get_all_children (); std::list<graphics_object> obj_list; std::list<graphics_object>::iterator it; @@ -1564,7 +1644,7 @@ graphics_object go = (*it); // FIXME: check whether object has "units" property and it is set to "data" - if (! go.isa ("text") || go.get ("units").string_value () == "data") + if (! go.isa ("text") || go.get (caseless_str ("units")).string_value () == "data") { set_clipping (go.get_properties ().is_clipping ()); draw (go); @@ -2572,6 +2652,38 @@ } void +opengl_renderer::draw (const text::properties& props) +{ + if (props.get_string ().empty ()) + return; + + set_font (props); + set_color (props.get_color_rgb ()); + + // FIXME: take "units" into account + Matrix pos = props.get_position ().matrix_value (); + int halign = 0, valign = 0; + + if (props.horizontalalignment_is ("center")) + halign = 1; + else if (props.horizontalalignment_is ("right")) + halign = 2; + + if (props.verticalalignment_is ("top")) + valign = 2; + else if (props.verticalalignment_is ("baseline")) + valign = 3; + else if (props.verticalalignment_is ("middle")) + valign = 1; + + // FIXME: handle margin and surrounding box + + draw_text (props.get_string (), + pos(0), pos(1), pos(2), + halign, valign, props.get_rotation ()); +} + +void opengl_renderer::set_viewport (int w, int h) { glViewport (0, 0, w, h); @@ -2581,6 +2693,17 @@ opengl_renderer::set_color (const Matrix& c) { glColor3dv (c.data ()); +#if HAVE_FREETYPE + text_renderer.set_color (c); +#endif +} + +void +opengl_renderer::set_font (const base_properties& props) +{ +#if HAVE_FREETYPE + text_renderer.set_font (props); +#endif } void @@ -2869,6 +2992,85 @@ return ID; } +Matrix +opengl_renderer::draw_text (const std::string& txt, + double x, double y, double z, + int halign, int valign, double rotation) +{ +#if HAVE_FREETYPE + if (txt.empty ()) + return Matrix (1, 4, 0.0); + + // FIXME: clip "rotation" between 0 and 360 + + int rot_mode = ft_render::ROTATION_0; + + if (rotation == 90.0) + rot_mode = ft_render::ROTATION_90; + else if (rotation == 180.0) + rot_mode = ft_render::ROTATION_180; + else if (rotation == 270.0) + rot_mode = ft_render::ROTATION_270; + + text_element *elt = text_parser_none ().parse (txt); + Matrix bbox; + uint8NDArray pixels = text_renderer.render (elt, bbox, rot_mode); + int x0 = 0, y0 = 0; + int w = bbox(2), h = bbox(3); + + switch (halign) + { + default: break; + case 1: x0 = -bbox(2)/2; break; + case 2: x0 = -bbox(2); break; + } + switch (valign) + { + default: break; + case 1: y0 = -bbox(3)/2; break; + case 2: y0 = -bbox(3); break; + case 3: y0 = bbox(1); break; + } + + switch (rot_mode) + { + case ft_render::ROTATION_90: + std::swap (x0, y0); + std::swap (w, h); + x0 -= bbox(3); + break; + case ft_render::ROTATION_180: + x0 -= bbox(2); + y0 -= bbox(3); + break; + case ft_render::ROTATION_270: + std::swap (x0, y0); + std::swap (w, h); + y0 -= bbox(2); + break; + } + + bool blend = glIsEnabled (GL_BLEND); + + glEnable (GL_BLEND); + glEnable (GL_ALPHA_TEST); + glRasterPos3d (x, y, z); + glBitmap(0, 0, 0, 0, x0, y0, 0); + glDrawPixels (w, h, + GL_RGBA, GL_UNSIGNED_BYTE, pixels.data ()); + glDisable (GL_ALPHA_TEST); + if (! blend) + glDisable (GL_BLEND); + + delete elt; + + return bbox; +#else + ::error ("draw_text: cannot render text, Freetype library not available"); + return Matrix (1, 4, 0.0); +#endif +} + #endif /*