From 31e788548ca4875539ad59c4fbec26ab90517141 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Wed, 15 Jul 2015 23:36:54 +0300 Subject: [PATCH] Add a class for easier text rendering I've written the equivalent in various applications a few times, so might as well put it here. --- source/text.cpp | 95 +++++++++++++++++++++++++++++++++++++++++++++++++ source/text.h | 87 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 source/text.cpp create mode 100644 source/text.h diff --git a/source/text.cpp b/source/text.cpp new file mode 100644 index 00000000..e3a85400 --- /dev/null +++ b/source/text.cpp @@ -0,0 +1,95 @@ +#include "meshbuilder.h" +#include "text.h" +#include "texture2d.h" + +using namespace std; + +namespace Msp { +namespace GL { + +Text::Text(const Font &f, const Technique *tech): + font(f), + mesh((TEXCOORD2, VERTEX2)), + horz_align(0.0f), + vert_offset(0.0f) +{ + object.set_mesh(&mesh); + if(tech) + set_technique(tech); +} + +void Text::set_technique(const Technique *tech) +{ + if(tech) + { + technique = *tech; + technique.replace_texture("diffusemap", font.get_texture()); + object.set_technique(&technique); + } + else + object.set_technique(0); +} + +void Text::set_text(const string &text, StringCodec::Decoder &dec) +{ + clear(); + width = font.get_string_width(text, dec); + GL::MeshBuilder bld(mesh); + bld.matrix() *= Matrix::translation(Vector3(-horz_align*width, vert_offset, 0.0f)); + font.build_string(text, dec, bld); +} + +void Text::clear() +{ + mesh.clear(); + width = 0; +} + +void Text::set_alignment(HorizontalAlign ha, VerticalAlign va) +{ + float h; + switch(ha) + { + case LEFT: h = 0.0f; break; + case CENTER: h = 0.5f; break; + case RIGHT: h = 1.0f; break; + default: throw invalid_argument("Text::set_alignment"); + } + + float v; + switch(va) + { + case DESCENT: v = -font.get_descent(); break; + case BASELINE: v = 0.0f; break; + case MIDLINE: v = font.get_ascent()/2; break; // XXX Midline should be cap height / 2 + case ASCENT: v = font.get_ascent(); break; + default: throw invalid_argument("Text::set_alignment"); + } + + set_alignment(h, v); +} + +void Text::set_alignment(float h, float v) +{ + float horz_adjust = (horz_align-h)*width; + float vert_adjust = -v-vert_offset; + horz_align = h; + vert_offset = -v; + + unsigned pos_offset = mesh.get_vertices().get_format().offset(VERTEX2); + unsigned n_vertices = mesh.get_n_vertices(); + for(unsigned i=0; i + void set_text(const std::string &t) + { + typename C::Decoder dec; + set_text(t, dec); + } + + void set_text(const std::string &t) + { set_text(t); } + + /// Clears the object's contents. + void clear(); + + /// Sets horizontal and vertical alignment with predefined anchors. + void set_alignment(HorizontalAlign, VerticalAlign = BASELINE); + + /** Sets horizontal and vertical alignment. 0.0 means left or baseline, + 1.0 means right or top. */ + void set_alignment(float, float = 0.0f); + + float get_width() const { return width; } + + virtual void render(Renderer &, const Tag &) const; + + operator const Object &() const { return object; } +}; + +} // namespace GL +} // namespace Msp + +#endif -- 2.43.0