From 58d517d166eb2f6584ab1f5c14f71e62cafec3ef Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 18 Jun 2016 07:23:01 +0800 Subject: [PATCH] add a new helper class text_aligner --- include/nana/paint/text_renderer.hpp | 31 +++++++++- source/paint/text_renderer.cpp | 92 ++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 1 deletion(-) diff --git a/include/nana/paint/text_renderer.hpp b/include/nana/paint/text_renderer.hpp index 7234c57c..96fbbfdb 100644 --- a/include/nana/paint/text_renderer.hpp +++ b/include/nana/paint/text_renderer.hpp @@ -9,7 +9,7 @@ namespace nana class text_renderer { public: - typedef graphics & graph_reference; + using graph_reference = graphics &; text_renderer(graph_reference graph, align = align::left); @@ -22,6 +22,35 @@ namespace nana graph_reference graph_; align text_align_; }; + + /// Draw aligned string + class aligner + { + public: + using graph_reference = graphics&; + + /// Constructor + /** + * @param graph Reference to a graphics object + * @param text_align Alignment of text + * @param text_align_if_too_long Alignment of text if the pixels of string is larger than text area + */ + aligner(graph_reference graph, align text_align = align::left); + aligner(graph_reference graph, align text_align, align text_align_if_too_long); + + /// Draws a text with specified text alignment. + /** + * @param text Text to draw + * @param pos Postion where the text to draw + * @param width The width of text area. If the pixels of text is larger than this parameter, it draws ellipsis + */ + void draw(const std::string& text, point pos, unsigned width); + void draw(const std::wstring& text, point pos, unsigned width); + private: + graph_reference graph_; + align text_align_; + align text_align_ex_; + }; } } diff --git a/source/paint/text_renderer.cpp b/source/paint/text_renderer.cpp index 4acd0f36..1716b34c 100644 --- a/source/paint/text_renderer.cpp +++ b/source/paint/text_renderer.cpp @@ -582,5 +582,97 @@ namespace nana } } //end class text_renderer + + //class aligner + + //Constructor + aligner::aligner(graph_reference graph, align text_align) + : aligner{ graph, text_align, text_align } + {} + + aligner::aligner(graph_reference graph, align text_align, align text_align_ex) : + graph_(graph), + text_align_(text_align), + text_align_ex_(text_align_ex) + {} + + // Draws a text with specified text alignment. + void aligner::draw(const std::string& text, point pos, unsigned width) + { + draw(to_wstring(text), pos, width); + } + + void aligner::draw(const std::wstring& text, point pos, unsigned width) + { + auto text_px = graph_.text_extent_size(text).width; + if (text_px <= width) + { + switch (text_align_) + { + case align::center: + pos.x += static_cast(width - text_px) / 2; + break; + case align::right: + pos.x += static_cast(width - text_px); + default: + break; + } + + graph_.bidi_string(pos, text.c_str(), text.size()); + return; + } + + const auto ellipsis = graph_.text_extent_size("...", 3).width; + + std::unique_ptr pixels(new unsigned[text.size()]); + graph_.glyph_pixels(text.c_str(), text.size(), pixels.get()); + + unsigned substr_len = 0; + unsigned substr_px = 0; + + if (align::right == text_align_ex_) + { + auto end = pixels.get(); + auto p = end + text.size(); + do + { + --p; + if (substr_px + *p + ellipsis > width) + { + substr_len = p - pixels.get() + 1; + break; + } + substr_px += *p; + } while (p != end); + + pos.x += static_cast(width - ellipsis - substr_px); + + graph_.string(pos, "..."); + pos.x += ellipsis; + graph_.bidi_string(pos, text.c_str() + substr_len, text.size() - substr_len); + } + else + { + for (auto p = pixels.get(), end = pixels.get() + text.size(); p != end; ++p) + { + if (substr_px + *p + ellipsis > width) + { + substr_len = p - pixels.get(); + break; + } + substr_px += *p; + } + + if (align::center == text_align_ex_) + pos.x += (width - substr_px - ellipsis) / 2; + + graph_.bidi_string(pos, text.c_str(), substr_len); + + pos.x += substr_px; + graph_.string(pos, "..."); + } + } + + //end class string } }