Mercurial > octave-nkf
diff src/graphics.cc @ 12334:63dc132a1000
Move axes labels and title positioning to axes::properties
author | Konstantinos Poulios <logari81@gmail.com> |
---|---|
date | Thu, 03 Feb 2011 19:30:13 +0100 |
parents | 2ad37783bf01 |
children | f6763ab98609 |
line wrap: on
line diff
--- 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<text::properties&> + (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<text::properties&> + (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<text::properties&> + (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<text::properties&> + (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)