# HG changeset patch # User Konstantinos Poulios # Date 1296757813 -3600 # Node ID e23f4609d558d2989d8957a128c4ce8aa8653eb0 # Parent 3458c5bba6e58dd2f303de0c0299531e59c24765 Move axes labels and title positioning to axes::properties diff -r 3458c5bba6e5 -r e23f4609d558 src/ChangeLog --- a/src/ChangeLog Thu Feb 03 12:47:05 2011 +0100 +++ b/src/ChangeLog Thu Feb 03 19:30:13 2011 +0100 @@ -1,3 +1,21 @@ +2011-02-03 Konstantinos Poulios + + * gl-render.h: (opengl_renderer::draw_axes_titles): Remove prototype. + * gl-render.cc: (opengl_renderer::draw_axes_titles): Remove function. + (opengl_renderer::draw_axes_x_grid, + opengl_renderer::draw_axes_y_grid, + opengl_renderer::draw_axes_z_grid): Remove calculation of axis label + positions. + * graphics.cc: (axes::properties::update_xlabel_position, + axes::properties::update_ylabel_position + axes::properties::update_zlabel_position + axes::properties::update_title_position): New functions calculating + label and title positions. + (axes::properties::get_ticklabel_extents): New function. + * graphics.h.in: Provide functions prototypes. + * txt-eng-ft.cc (ft_render::get_extent): New function version. + * txt-eng-ft.h (ft_render::get_extent): Provide function prototype. + 2011-02-03 Kai Habel * src/gl-render.cc(text_to_pixels): Use text_renderer object only diff -r 3458c5bba6e5 -r e23f4609d558 src/gl-render.cc --- a/src/gl-render.cc Thu Feb 03 12:47:05 2011 +0100 +++ b/src/gl-render.cc Thu Feb 03 19:30:13 2011 +0100 @@ -1027,76 +1027,7 @@ 0., 0, (box && xstate != AXE_ANY_DIR)); } - text::properties& xlabel_props = - reinterpret_cast (gh_manager::get_object (props.get_xlabel ()).get_properties ()); - - xlabel_props.set_visible ("on"); - - if (! xlabel_props.get_string ().empty ()) - { - if (xlabel_props.horizontalalignmentmode_is ("auto")) - { - xlabel_props.set_horizontalalignment - (xstate > AXE_DEPTH_DIR - ? "center" : (xyzSym ? "left" : "right")); - - xlabel_props.set_horizontalalignmentmode ("auto"); - } - - if (xlabel_props.verticalalignmentmode_is ("auto")) - { - xlabel_props.set_verticalalignment - (xstate == AXE_VERT_DIR || x2Dtop ? "bottom" : "top"); - - xlabel_props.set_verticalalignmentmode ("auto"); - } - - if (xlabel_props.positionmode_is ("auto") - || xlabel_props.rotationmode_is ("auto")) - { - double angle = 0; - ColumnVector p - = graphics_xform::xform_vector ((x_min+x_max)/2, - ypTick, zpTick); - - if (tick_along_z) - p(2) += (signum(zpTick-zpTickN)*fz*xtickoffset); - else - p(1) += (signum(ypTick-ypTickN)*fy*xtickoffset); - - p = xform.transform (p(0), p(1), p(2), false); - - switch (xstate) - { - case AXE_ANY_DIR: - p(0) += (xyzSym ? wmax : -wmax); - p(1) += hmax; - break; - - case AXE_VERT_DIR: - p(0) -= wmax; - angle = 90; - break; - - case AXE_HORZ_DIR: - p(1) += (x2Dtop ? -hmax : hmax); - break; - } - - if (xlabel_props.positionmode_is ("auto")) - { - p = xform.untransform (p(0), p(1), p(2), true); - xlabel_props.set_position (p.extract_n (0, 3).transpose ()); - xlabel_props.set_positionmode ("auto"); - } - - if (xlabel_props.rotationmode_is ("auto")) - { - xlabel_props.set_rotation (angle); - xlabel_props.set_rotationmode ("auto"); - } - } - } + gh_manager::get_object (props.get_xlabel ()).set ("visible", "on"); } else gh_manager::get_object (props.get_xlabel ()).set ("visible", "off"); @@ -1200,74 +1131,7 @@ 0., 0., 1, (box && ystate != AXE_ANY_DIR)); } - text::properties& ylabel_props = - reinterpret_cast (gh_manager::get_object (props.get_ylabel ()).get_properties ()); - - ylabel_props.set_visible ("on"); - - if (! ylabel_props.get_string ().empty ()) - { - if (ylabel_props.horizontalalignmentmode_is ("auto")) - { - ylabel_props.set_horizontalalignment - (ystate > AXE_DEPTH_DIR - ? "center" : (!xyzSym ? "left" : "right")); - - ylabel_props.set_horizontalalignmentmode ("auto"); - } - - if (ylabel_props.verticalalignmentmode_is ("auto")) - { - ylabel_props.set_verticalalignment - (ystate == AXE_VERT_DIR && !y2Dright ? "bottom" : "top"); - - ylabel_props.set_verticalalignmentmode ("auto"); - } - - if (ylabel_props.positionmode_is ("auto") - || ylabel_props.rotationmode_is ("auto")) - { - double angle = 0; - ColumnVector p = graphics_xform::xform_vector (xpTick, (y_min+y_max)/2, zpTick); - - if (tick_along_z) - p(2) += (signum(zpTick-zpTickN)*fz*ytickoffset); - else - p(0) += (signum(xpTick-xpTickN)*fx*ytickoffset); - - p = xform.transform (p(0), p(1), p(2), false); - - switch (ystate) - { - case AXE_ANY_DIR: - p(0) += (!xyzSym ? wmax : -wmax); - p(1) += hmax; - break; - - case AXE_VERT_DIR: - p(0) += (y2Dright ? wmax : -wmax); - angle = 90; - break; - - case AXE_HORZ_DIR: - p(1) += hmax; - break; - } - - if (ylabel_props.positionmode_is ("auto")) - { - p = xform.untransform (p(0), p(1), p(2), true); - ylabel_props.set_position (p.extract_n (0, 3).transpose ()); - ylabel_props.set_positionmode ("auto"); - } - - if (ylabel_props.rotationmode_is ("auto")) - { - ylabel_props.set_rotation (angle); - ylabel_props.set_rotationmode ("auto"); - } - } - } + gh_manager::get_object (props.get_ylabel ()).set ("visible", "on"); } else gh_manager::get_object (props.get_ylabel ()).set ("visible", "off"); @@ -1406,157 +1270,13 @@ } } - text::properties& zlabel_props = - reinterpret_cast (gh_manager::get_object (props.get_zlabel ()).get_properties ()); - - zlabel_props.set_visible ("on"); - - if (! zlabel_props.get_string ().empty ()) - { - bool camAuto = props.cameraupvectormode_is ("auto"); - - if (zlabel_props.horizontalalignmentmode_is ("auto")) - { - zlabel_props.set_horizontalalignment - ((zstate > AXE_DEPTH_DIR || camAuto) ? "center" : "right"); - - zlabel_props.set_horizontalalignmentmode ("auto"); - } - - if (zlabel_props.verticalalignmentmode_is ("auto")) - { - zlabel_props.set_verticalalignment - (zstate == AXE_VERT_DIR - ? "bottom" : ((zSign || camAuto) ? "bottom" : "top")); - - zlabel_props.set_verticalalignmentmode ("auto"); - } - - if (zlabel_props.positionmode_is ("auto") - || zlabel_props.rotationmode_is ("auto")) - { - double angle = 0; - ColumnVector p; - - if (xySym) - { - p = graphics_xform::xform_vector (xPlaneN, yPlane, - (z_min+z_max)/2); - if (xisinf (fy)) - p(0) += (signum(xPlaneN-xPlane)*fx*ztickoffset); - else - p(1) += (signum(yPlane-yPlaneN)*fy*ztickoffset); - } - else - { - p = graphics_xform::xform_vector (xPlane, yPlaneN, - (z_min+z_max)/2); - if (xisinf (fx)) - p(1) += (signum(yPlaneN-yPlane)*fy*ztickoffset); - else - p(0) += (signum(xPlane-xPlaneN)*fx*ztickoffset); - } - - p = xform.transform (p(0), p(1), p(2), false); - - switch (zstate) - { - case AXE_ANY_DIR: - if (camAuto) - { - p(0) -= wmax; - angle = 90; - } - - // FIXME -- what's the correct offset? - // - // p[0] += (!xySym ? wmax : -wmax); - // p[1] += (zSign ? hmax : -hmax); - - break; - - case AXE_VERT_DIR: - p(0) -= wmax; - angle = 90; - break; - - case AXE_HORZ_DIR: - p(1) += hmax; - break; - } - - if (zlabel_props.positionmode_is ("auto")) - { - p = xform.untransform (p(0), p(1), p(2), true); - zlabel_props.set_position (p.extract_n (0, 3).transpose ()); - zlabel_props.set_positionmode ("auto"); - } - - if (zlabel_props.rotationmode_is ("auto")) - { - zlabel_props.set_rotation (angle); - zlabel_props.set_rotationmode ("auto"); - } - } - } + gh_manager::get_object (props.get_zlabel ()).set ("visible", "on"); } else gh_manager::get_object (props.get_zlabel ()).set ("visible", "off"); } void -opengl_renderer::draw_axes_title (const axes::properties& props) -{ - double x_min = props.get_x_min (); - double x_max = props.get_x_max (); - double y_min = props.get_y_min (); - double y_max = props.get_y_max (); - double z_min = props.get_z_min (); - double z_max = props.get_z_max (); - - // Title - - // FIXME: bbox has to be moved to axes::properties - ColumnVector bbox(4); - bbox(0) = octave_Inf; - bbox(1) = octave_Inf; - bbox(2) = -octave_Inf; - bbox(3) = -octave_Inf; - for (int i = 0; i <= 1; i++) - for (int j = 0; j <= 1; j++) - for (int k = 0; k <= 1; k++) - { - ColumnVector p = xform.transform (i ? x_max : x_min, - j ? y_max : y_min, - k ? z_max : z_min, false); - bbox(0) = std::min (bbox(0), p(0)); - bbox(1) = std::min (bbox(1), p(1)); - bbox(2) = std::max (bbox(2), p(0)); - bbox(3) = std::max (bbox(3), p(1)); - } - - bbox(2) = bbox(2)-bbox(0); - bbox(3) = bbox(3)-bbox(1); - - Matrix x_zlim = props.get_transform_zlim (); - - text::properties& title_props = - reinterpret_cast (gh_manager::get_object (props.get_title ()).get_properties ()); - - if (! title_props.get_string ().empty () - && title_props.positionmode_is ("auto")) - { - ColumnVector p = xform.untransform (bbox(0)+bbox(2)/2, (bbox(1)-10), - (x_zlim(0)+x_zlim(1))/2, true); - - title_props.set_position (p.extract_n(0, 3).transpose ()); - title_props.set_positionmode ("auto"); - } - - set_clipbox (x_min, x_max, y_min, y_max, z_min, z_max); -} - -void opengl_renderer::draw_axes_children (const axes::properties& props) { // Children @@ -1632,6 +1352,13 @@ void opengl_renderer::draw_axes (const axes::properties& props) { + double x_min = props.get_x_min (); + double x_max = props.get_x_max (); + double y_min = props.get_y_min (); + double y_max = props.get_y_max (); + double z_min = props.get_z_min (); + double z_max = props.get_z_max (); + setup_opengl_transformation (props); // draw axes object @@ -1647,7 +1374,7 @@ set_linestyle ("-"); - draw_axes_title (props); + set_clipbox (x_min, x_max, y_min, y_max, z_min, z_max); draw_axes_children (props); } diff -r 3458c5bba6e5 -r e23f4609d558 src/gl-render.h --- a/src/gl-render.h Thu Feb 03 12:47:05 2011 +0100 +++ b/src/gl-render.h Thu Feb 03 19:30:13 2011 +0100 @@ -173,7 +173,6 @@ void draw_axes_y_grid (const axes::properties& props); void draw_axes_z_grid (const axes::properties& props); - void draw_axes_title (const axes::properties& props); void draw_axes_children (const axes::properties& props); private: diff -r 3458c5bba6e5 -r e23f4609d558 src/graphics.cc --- a/src/graphics.cc Thu Feb 03 12:47:05 2011 +0100 +++ b/src/graphics.cc Thu Feb 03 19:30:13 2011 +0100 @@ -3301,6 +3301,7 @@ xset (xlabel.handle_value (), "verticalalignmentmode", "auto"); xset (xlabel.handle_value (), "clipping", "off"); xset (xlabel.handle_value (), "color", get_xcolor ()); + update_xlabel_position (); } void @@ -3313,6 +3314,7 @@ xset (ylabel.handle_value (), "verticalalignmentmode", "auto"); xset (ylabel.handle_value (), "clipping", "off"); xset (ylabel.handle_value (), "color", get_ycolor ()); + update_ylabel_position (); } void @@ -3325,6 +3327,7 @@ xset (zlabel.handle_value (), "verticalalignmentmode", "auto"); xset (zlabel.handle_value (), "clipping", "off"); xset (zlabel.handle_value (), "color", get_zcolor ()); + update_zlabel_position (); } void @@ -3337,6 +3340,7 @@ xset (title.handle_value (), "verticalalignment", "bottom"); xset (title.handle_value (), "verticalalignmentmode", "auto"); xset (title.handle_value (), "clipping", "off"); + update_title_position (); } void @@ -4063,6 +4067,305 @@ xtickoffset = (mode2d ? std::max (0., xticklen) : std::abs (xticklen)) + 5; ytickoffset = (mode2d ? std::max (0., yticklen) : std::abs (yticklen)) + 5; ztickoffset = (mode2d ? std::max (0., zticklen) : std::abs (zticklen)) + 5; + + update_xlabel_position (); + update_ylabel_position (); + update_zlabel_position (); + update_title_position (); +} + +void +axes::properties::update_xlabel_position (void) +{ + graphics_xform xform = get_transform (); + + text::properties& xlabel_props = reinterpret_cast + (gh_manager::get_object (get_xlabel ()).get_properties ()); + + if (xlabel_props.horizontalalignmentmode_is ("auto")) + { + xlabel_props.set_horizontalalignment + (xstate > AXE_DEPTH_DIR + ? "center" : (xyzSym ? "left" : "right")); + + xlabel_props.set_horizontalalignmentmode ("auto"); + } + + if (xlabel_props.verticalalignmentmode_is ("auto")) + { + xlabel_props.set_verticalalignment + (xstate == AXE_VERT_DIR || x2Dtop ? "bottom" : "top"); + + xlabel_props.set_verticalalignmentmode ("auto"); + } + + if (xlabel_props.positionmode_is ("auto") + || xlabel_props.rotationmode_is ("auto")) + { + Matrix ext (1, 2, 0.0); + ext = get_ticklabel_extents (get_xtick ().matrix_value (), + get_xticklabel ().all_strings (), + get_xlim ().matrix_value ()); + + double wmax = ext(0), hmax = ext(1), angle = 0; + ColumnVector p = + graphics_xform::xform_vector ((xpTickN+xpTick)/2, ypTick, zpTick); + + bool tick_along_z = nearhoriz || xisinf (fy); + if (tick_along_z) + p(2) += (signum(zpTick-zpTickN)*fz*xtickoffset); + else + p(1) += (signum(ypTick-ypTickN)*fy*xtickoffset); + + p = xform.transform (p(0), p(1), p(2), false); + + switch (xstate) + { + case AXE_ANY_DIR: + p(0) += (xyzSym ? wmax : -wmax); + p(1) += hmax; + break; + + case AXE_VERT_DIR: + p(0) -= wmax; + angle = 90; + break; + + case AXE_HORZ_DIR: + p(1) += (x2Dtop ? -hmax : hmax); + break; + } + + if (xlabel_props.positionmode_is ("auto")) + { + p = xform.untransform (p(0), p(1), p(2), true); + xlabel_props.set_position (p.extract_n (0, 3).transpose ()); + xlabel_props.set_positionmode ("auto"); + } + + if (xlabel_props.rotationmode_is ("auto")) + { + xlabel_props.set_rotation (angle); + xlabel_props.set_rotationmode ("auto"); + } + } +} + +void +axes::properties::update_ylabel_position (void) +{ + graphics_xform xform = get_transform (); + + text::properties& ylabel_props = reinterpret_cast + (gh_manager::get_object (get_ylabel ()).get_properties ()); + + if (ylabel_props.horizontalalignmentmode_is ("auto")) + { + ylabel_props.set_horizontalalignment + (ystate > AXE_DEPTH_DIR + ? "center" : (!xyzSym ? "left" : "right")); + + ylabel_props.set_horizontalalignmentmode ("auto"); + } + + if (ylabel_props.verticalalignmentmode_is ("auto")) + { + ylabel_props.set_verticalalignment + (ystate == AXE_VERT_DIR && !y2Dright ? "bottom" : "top"); + + ylabel_props.set_verticalalignmentmode ("auto"); + } + + if (ylabel_props.positionmode_is ("auto") + || ylabel_props.rotationmode_is ("auto")) + { + Matrix ext (1, 2, 0.0); + ext = get_ticklabel_extents (get_ytick ().matrix_value (), + get_yticklabel ().all_strings (), + get_ylim ().matrix_value ()); + + double wmax = ext(0), hmax = ext(1), angle = 0; + ColumnVector p = + graphics_xform::xform_vector (xpTick, (ypTickN+ypTick)/2, zpTick); + + bool tick_along_z = nearhoriz || xisinf (fx); + if (tick_along_z) + p(2) += (signum(zpTick-zpTickN)*fz*ytickoffset); + else + p(0) += (signum(xpTick-xpTickN)*fx*ytickoffset); + + p = xform.transform (p(0), p(1), p(2), false); + + switch (ystate) + { + case AXE_ANY_DIR: + p(0) += (!xyzSym ? wmax : -wmax); + p(1) += hmax; + break; + + case AXE_VERT_DIR: + p(0) += (y2Dright ? wmax : -wmax); + angle = 90; + break; + + case AXE_HORZ_DIR: + p(1) += hmax; + break; + } + + if (ylabel_props.positionmode_is ("auto")) + { + p = xform.untransform (p(0), p(1), p(2), true); + ylabel_props.set_position (p.extract_n (0, 3).transpose ()); + ylabel_props.set_positionmode ("auto"); + } + + if (ylabel_props.rotationmode_is ("auto")) + { + ylabel_props.set_rotation (angle); + ylabel_props.set_rotationmode ("auto"); + } + } +} + +void +axes::properties::update_zlabel_position (void) +{ + graphics_xform xform = get_transform (); + + text::properties& zlabel_props = reinterpret_cast + (gh_manager::get_object (get_zlabel ()).get_properties ()); + + bool camAuto = cameraupvectormode_is ("auto"); + + if (zlabel_props.horizontalalignmentmode_is ("auto")) + { + zlabel_props.set_horizontalalignment + ((zstate > AXE_DEPTH_DIR || camAuto) ? "center" : "right"); + + zlabel_props.set_horizontalalignmentmode ("auto"); + } + + if (zlabel_props.verticalalignmentmode_is ("auto")) + { + zlabel_props.set_verticalalignment + (zstate == AXE_VERT_DIR + ? "bottom" : ((zSign || camAuto) ? "bottom" : "top")); + + zlabel_props.set_verticalalignmentmode ("auto"); + } + + if (zlabel_props.positionmode_is ("auto") + || zlabel_props.rotationmode_is ("auto")) + { + Matrix ext (1, 2, 0.0); + ext = get_ticklabel_extents (get_ztick ().matrix_value (), + get_zticklabel ().all_strings (), + get_zlim ().matrix_value ()); + + double wmax = ext(0), hmax = ext(1), angle = 0; + ColumnVector p; + + if (xySym) + { + p = graphics_xform::xform_vector (xPlaneN, yPlane, + (zpTickN+zpTick)/2); + if (xisinf (fy)) + p(0) += (signum(xPlaneN-xPlane)*fx*ztickoffset); + else + p(1) += (signum(yPlane-yPlaneN)*fy*ztickoffset); + } + else + { + p = graphics_xform::xform_vector (xPlane, yPlaneN, + (zpTickN+zpTick)/2); + if (xisinf (fx)) + p(1) += (signum(yPlaneN-yPlane)*fy*ztickoffset); + else + p(0) += (signum(xPlane-xPlaneN)*fx*ztickoffset); + } + + p = xform.transform (p(0), p(1), p(2), false); + + switch (zstate) + { + case AXE_ANY_DIR: + if (camAuto) + { + p(0) -= wmax; + angle = 90; + } + + // FIXME -- what's the correct offset? + // + // p[0] += (!xySym ? wmax : -wmax); + // p[1] += (zSign ? hmax : -hmax); + + break; + + case AXE_VERT_DIR: + p(0) -= wmax; + angle = 90; + break; + + case AXE_HORZ_DIR: + p(1) += hmax; + break; + } + + if (zlabel_props.positionmode_is ("auto")) + { + p = xform.untransform (p(0), p(1), p(2), true); + zlabel_props.set_position (p.extract_n (0, 3).transpose ()); + zlabel_props.set_positionmode ("auto"); + } + + if (zlabel_props.rotationmode_is ("auto")) + { + zlabel_props.set_rotation (angle); + zlabel_props.set_rotationmode ("auto"); + } + } +} + +void +axes::properties::update_title_position (void) +{ + graphics_xform xform = get_transform (); + + text::properties& title_props = reinterpret_cast + (gh_manager::get_object (get_title ()).get_properties ()); + + if (title_props.positionmode_is ("auto")) + { + // FIXME: bbox should be stored in axes::properties + ColumnVector bbox(4); + bbox(0) = octave_Inf; + bbox(1) = octave_Inf; + bbox(2) = -octave_Inf; + bbox(3) = -octave_Inf; + for (int i = 0; i <= 1; i++) + for (int j = 0; j <= 1; j++) + for (int k = 0; k <= 1; k++) + { + ColumnVector p = xform.transform (i ? xPlaneN : xPlane, + j ? yPlaneN : yPlane, + k ? zPlaneN : zPlane, false); + bbox(0) = std::min (bbox(0), p(0)); + bbox(1) = std::min (bbox(1), p(1)); + bbox(2) = std::max (bbox(2), p(0)); + bbox(3) = std::max (bbox(3), p(1)); + } + + bbox(2) = bbox(2)-bbox(0); + bbox(3) = bbox(3)-bbox(1); + + ColumnVector p = xform.untransform (bbox(0)+bbox(2)/2, (bbox(1)-10), + (x_zlim(0)+x_zlim(1))/2, true); + + title_props.set_position (p.extract_n(0, 3).transpose ()); + title_props.set_positionmode ("auto"); + } } static void @@ -4637,6 +4940,48 @@ labels = c; } +Matrix +axes::properties::get_ticklabel_extents (const Matrix& ticks, + const string_vector& ticklabels, + const Matrix& limits) +{ +#ifdef HAVE_FREETYPE + //FIXME: text_renderer could be cached + ft_render text_renderer; + text_renderer.set_font (get ("fontname").string_value (), + get ("fontweight").string_value (), + get ("fontangle").string_value (), + get ("fontsize").double_value ()); +#else + double fontsize = get ("fontsize").double_value (); +#endif + + Matrix ext (1, 2, 0.0); + double wmax = 0., hmax = 0.; + int n = std::min (ticklabels.numel (), ticks.numel ()); + for (int i = 0; i < n; i++) + { + double val = ticks(i); + if (limits(0) <= val && val <= limits(1)) + { +#ifdef HAVE_FREETYPE + ext = text_renderer.get_extent (ticklabels(i)); + wmax = std::max (wmax, ext(0)); + hmax = std::max (hmax, ext(1)); +#else + //FIXME: find a better approximation + int len = ticklabels(i).length(); + wmax = std::max (wmax, 0.5*fontsize*len); + hmax = fontsize; +#endif + } + } + + ext(0) = wmax; + ext(1) = hmax; + return ext; +} + void get_children_limits (double& min_val, double& max_val, double& min_pos, const Matrix& kids, char limit_type) diff -r 3458c5bba6e5 -r e23f4609d558 src/graphics.h.in --- a/src/graphics.h.in Thu Feb 03 12:47:05 2011 +0100 +++ b/src/graphics.h.in Thu Feb 03 19:30:13 2011 +0100 @@ -3311,6 +3311,11 @@ void update_ydir (void) { update_camera (); update_axes_layout (); } void update_zdir (void) { update_camera (); update_axes_layout (); } + void update_xlabel_position (void); + void update_ylabel_position (void); + void update_zlabel_position (void); + void update_title_position (void); + void update_ticklengths (void); void update_tickdir (void) { update_ticklengths (); } void update_tickdirmode (void) { update_ticklengths (); } @@ -3380,6 +3385,10 @@ void calc_ticks_and_lims (array_property& lims, array_property& ticks, array_property& mticks, bool limmode_is_auto, bool is_logscale); void calc_ticklabels (const array_property& ticks, any_property& labels, bool is_logscale); + Matrix get_ticklabel_extents (const Matrix& ticks, + const string_vector& ticklabels, + const Matrix& limits); + void fix_limits (array_property& lims) { if (lims.get ().is_empty ()) diff -r 3458c5bba6e5 -r e23f4609d558 src/txt-eng-ft.cc --- a/src/txt-eng-ft.cc Thu Feb 03 12:47:05 2011 +0100 +++ b/src/txt-eng-ft.cc Thu Feb 03 19:30:13 2011 +0100 @@ -474,6 +474,16 @@ return extent; } +Matrix +ft_render::get_extent (const std::string& txt, double rotation) +{ + text_element *elt = text_parser_none ().parse (txt); + Matrix extent = get_extent (elt, rotation); + delete elt; + + return extent; +} + int ft_render::rotation_to_mode (double rotation) const { diff -r 3458c5bba6e5 -r e23f4609d558 src/txt-eng-ft.h --- a/src/txt-eng-ft.h Thu Feb 03 12:47:05 2011 +0100 +++ b/src/txt-eng-ft.h Thu Feb 03 19:30:13 2011 +0100 @@ -66,6 +66,7 @@ int rotation = ROTATION_0); Matrix get_extent (text_element *elt, double rotation = 0.0); + Matrix get_extent (const std::string& txt, double rotation = 0.0); void set_font (const std::string& name, const std::string& weight, const std::string& angle, double size);