diff --git a/include/nana/paint/graphics.hpp b/include/nana/paint/graphics.hpp index c0a8f56d..c50714a3 100644 --- a/include/nana/paint/graphics.hpp +++ b/include/nana/paint/graphics.hpp @@ -120,8 +120,17 @@ namespace nana ///Only supports the wide string, because it is very hard to specify the begin and end position in a UTF-8 string. ::nana::size glyph_extent_size(std::wstring_view text, std::size_t begin, std::size_t end) const; - bool glyph_pixels(std::wstring_view text, unsigned* pxbuf) const; + //bool glyph_pixels(std::wstring_view text, unsigned* pxbuf) const; //deprecated + + /// Returns a buffer which stores the pixel of each charater stored in text. + /** + * @param text The text to be requested. + * @return A buffer which stores the pixel of each character stored in text, its length is same with text's length. If text is empty, it returns a buffer with a senseless value. + */ std::unique_ptr glyph_pixels(std::wstring_view text) const; + + ::nana::size bidi_extent_size(std::string_view utf8_text) const; + ::nana::size bidi_extent_size(std::wstring_view text) const; #else ::nana::size text_extent_size(const ::std::string&) const; ::nana::size text_extent_size(const char*, std::size_t len) const; @@ -135,9 +144,10 @@ namespace nana ::nana::size glyph_extent_size(const ::std::wstring&, std::size_t length, std::size_t begin, std::size_t end) const; bool glyph_pixels(const wchar_t *, std::size_t length, unsigned* pxbuf) const; -#endif + ::nana::size bidi_extent_size(const std::wstring&) const; ::nana::size bidi_extent_size(const std::string&) const; +#endif bool text_metrics(unsigned & ascent, unsigned& descent, unsigned& internal_leading) const; @@ -180,12 +190,22 @@ namespace nana ::nana::color palette(bool for_text) const; graphics& palette(bool for_text, const ::nana::color&); - unsigned bidi_string(const nana::point&, const wchar_t *, std::size_t len); - unsigned bidi_string(const point& pos, const char*, std::size_t len); - void set_pixel(int x, int y, const ::nana::color&); void set_pixel(int x, int y); +#ifdef _nana_std_has_string_view + unsigned bidi_string(const point&, std::string_view utf8str); + unsigned bidi_string(const point& pos, std::wstring_view str); + + void string(const point&, std::string_view utf8str); + void string(const point&, std::string_view utf8str, const nana::color&); + + void string(const point&, std::wstring_view str); + void string(const point&, std::wstring_view str, const nana::color&); +#else + unsigned bidi_string(const nana::point&, const wchar_t *, std::size_t len); + unsigned bidi_string(const point& pos, const char*, std::size_t len); + void string(const point&, const std::string& text_utf8); void string(const point&, const std::string& text_utf8, const color&); @@ -193,6 +213,7 @@ namespace nana void string(const point&, const wchar_t*); void string(const point&, const ::std::wstring&); void string(const point&, const ::std::wstring&, const color&); +#endif void line(const point&, const point&); void line(const point&, const point&, const color&); diff --git a/source/gui/widgets/button.cpp b/source/gui/widgets/button.cpp index b7d3214b..c9ba1221 100644 --- a/source/gui/widgets/button.cpp +++ b/source/gui/widgets/button.cpp @@ -1,7 +1,7 @@ /* * A Button Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -262,7 +262,11 @@ namespace nana{ namespace drawerbase if (attr_.omitted) tr.render(pos, txtptr, txtlen, omitted_pixels, true); else +#ifdef _nana_std_has_string_view + graph.bidi_string(pos, { txtptr, txtlen }); +#else graph.bidi_string(pos, txtptr, txtlen); +#endif API::dev::draw_shortkey_underline(graph, mbstr, shortkey, shortkey_pos, pos, text_color); } @@ -277,9 +281,15 @@ namespace nana{ namespace drawerbase } else { +#ifdef _nana_std_has_string_view + graph.bidi_string(point{ pos.x + 1, pos.y + 1 }, { txtptr, txtlen }); + graph.palette(true, color{ colors::gray }); + graph.bidi_string(pos, { txtptr, txtlen }); +#else graph.bidi_string(point{ pos.x + 1, pos.y + 1 }, txtptr, txtlen); graph.palette(true, color{ colors::gray }); graph.bidi_string(pos, txtptr, txtlen); +#endif } } } diff --git a/source/gui/widgets/label.cpp b/source/gui/widgets/label.cpp index 8168984e..7f4f2a4e 100644 --- a/source/gui/widgets/label.cpp +++ b/source/gui/widgets/label.cpp @@ -1,7 +1,7 @@ /* * A Label Control Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-208 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -564,6 +564,16 @@ namespace nana _m_change_font(graph, fblock_ptr); +#ifdef _nana_std_has_string_view + std::wstring_view text_sv{ data_ptr->text() }; + if (text_range.second != text_sv.size()) + { + text_sv = text_sv.substr(text_range.first, text_range.second); + sz = graph.text_extent_size(text_sv); + } + + graph.string({ rs.pos.x, y }, text_sv, _m_fgcolor(fblock_ptr)); +#else if (text_range.second == data_ptr->text().length()) { graph.string({ rs.pos.x, y }, data_ptr->text(), _m_fgcolor(fblock_ptr)); @@ -575,6 +585,7 @@ namespace nana graph.string({ rs.pos.x, y }, str, _m_fgcolor(fblock_ptr)); } +#endif _m_insert_if_traceable(rs.pos.x, y, sz, fblock_ptr); diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index d68b2159..16963195 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -3309,8 +3309,12 @@ namespace nana{ namespace widgets void text_editor::_m_draw_parse_string(const keyword_parser& parser, bool rtl, ::nana::point pos, const ::nana::color& fgcolor, const wchar_t* str, std::size_t len) const { +#ifdef _nana_std_has_string_view + graph_.string(pos, { str, len }, fgcolor); +#else graph_.palette(true, fgcolor); graph_.string(pos, str, len); +#endif if (parser.entities().empty()) return; @@ -3359,7 +3363,20 @@ namespace nana{ namespace widgets ent_pos.x = pos.x + ent_off; - +#ifdef _nana_std_has_string_view + std::wstring_view ent_sv; + if (rtl) + { + //draw the whole text if it is a RTL text, because Arbic language is transformable. + ent_sv = { str, len }; + } + else + { + ent_sv = { ent_begin, static_cast(ent_end - ent_begin) }; + ent_off = 0; + } + canvas.string({}, ent_sv); +#else if (rtl) { //draw the whole text if it is a RTL text, because Arbic language is transformable. @@ -3370,6 +3387,7 @@ namespace nana{ namespace widgets canvas.string({}, ent_begin, ent_end - ent_begin); ent_off = 0; } +#endif graph_.bitblt(rectangle{ ent_pos, size{ ent_pixels, canvas.height() } }, canvas, point{ ent_off, 0 }); } } @@ -3395,12 +3413,19 @@ namespace nana{ namespace widgets void write_selection(const point& text_pos, unsigned text_px, const wchar_t* text, std::size_t len, bool has_focused) { +#ifdef _nana_std_has_string_view + graph_.rectangle(::nana::rectangle{ text_pos,{ text_px, line_px_ } }, true, + selection_color(false, has_focused)); + + graph_.string(text_pos, { text, len }, selection_color(true, has_focused)); +#else graph_.palette(true, selection_color(true, has_focused)); graph_.rectangle(::nana::rectangle{ text_pos, { text_px, line_px_ } }, true, selection_color(false, has_focused)); graph_.string(text_pos, text, len); +#endif } void rtl_string(point strpos, const wchar_t* str, std::size_t len, std::size_t str_px, unsigned glyph_front, unsigned glyph_selected, bool has_focused) @@ -3414,9 +3439,12 @@ namespace nana{ namespace widgets int sel_xpos = static_cast(str_px - (glyph_front + glyph_selected)); +#ifdef _nana_std_has_string_view + graph.string({ -sel_xpos, 0 }, { str, len }, selection_color(true, has_focused)); +#else graph.palette(true, selection_color(true, has_focused)); - graph.string({ -sel_xpos, 0 }, str, len); +#endif graph_.bitblt(nana::rectangle(strpos.x + sel_xpos, strpos.y, glyph_selected, line_px_), graph); }; private: @@ -3646,11 +3674,11 @@ namespace nana{ namespace widgets unsigned text_editor::_m_char_by_pixels(const unicode_bidi::entity& ent, unsigned pos) const { auto len = static_cast(ent.end - ent.begin); - - std::unique_ptr pxbuf(new unsigned[len]); #ifdef _nana_std_has_string_view - if (graph_.glyph_pixels({ent.begin, len}, pxbuf.get())) + auto pxbuf = graph_.glyph_pixels({ ent.begin, len }); + if (pxbuf) #else + std::unique_ptr pxbuf(new unsigned[len]); if (graph_.glyph_pixels(ent.begin, len, pxbuf.get())) #endif { @@ -3710,10 +3738,10 @@ namespace nana{ namespace widgets { //Characters of some bidi languages may transform in a word. //RTL - std::unique_ptr pxbuf(new unsigned[len]); #ifdef _nana_std_has_string_view - graph_.glyph_pixels({ent.begin, len}, pxbuf.get()); + auto pxbuf = graph_.glyph_pixels({ent.begin, len}); #else + std::unique_ptr pxbuf(new unsigned[len]); graph_.glyph_pixels(ent.begin, len, pxbuf.get()); #endif return std::accumulate(pxbuf.get() + (target - ent.begin), pxbuf.get() + len, text_w); diff --git a/source/gui/widgets/tabbar.cpp b/source/gui/widgets/tabbar.cpp index 2337f468..f0a972c9 100644 --- a/source/gui/widgets/tabbar.cpp +++ b/source/gui/widgets/tabbar.cpp @@ -1,6 +1,6 @@ /* * A Tabbar Implementation - * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -1489,7 +1489,12 @@ namespace nana } graph.rectangle(r, true); +#ifdef _nana_std_has_string_view + graph.bidi_string({ m.pos_ends.first + 5, 0 }, m.text); + +#else graph.bidi_string({ m.pos_ends.first + 5, 0 }, m.text.data(), m.text.size()); +#endif ++pos; } diff --git a/source/paint/detail/native_paint_interface.cpp b/source/paint/detail/native_paint_interface.cpp index f14c7a64..91b34a81 100644 --- a/source/paint/detail/native_paint_interface.cpp +++ b/source/paint/detail/native_paint_interface.cpp @@ -168,7 +168,11 @@ namespace detail { #if defined(NANA_WINDOWS) +#ifdef _nana_std_has_string_view + auto wstr = to_wstring(std::string_view(text, len)); +#else auto wstr = to_wstring(std::string(text,len)); +#endif ::SIZE size; if (::GetTextExtentPoint32(dw->context, wstr.c_str(), static_cast(wstr.size()), &size)) return nana::size(size.cx, size.cy); diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index 14a76b0e..ec2aa75b 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -494,7 +494,8 @@ namespace paint return sz; } - bool graphics::glyph_pixels(std::wstring_view text, unsigned* pxbuf) const +#if 0 + bool graphics::glyph_pixels(std::wstring_view text, unsigned* pxbuf) const //deprecated { if (nullptr == impl_->handle || nullptr == impl_->handle->context || nullptr == pxbuf) return false; @@ -533,6 +534,7 @@ namespace paint #endif return true; } +#endif std::unique_ptr graphics::glyph_pixels(std::wstring_view text) const { @@ -575,6 +577,32 @@ namespace paint #endif return pxbuf; } + + ::nana::size graphics::bidi_extent_size(std::string_view utf8str) const + { + return bidi_extent_size(to_wstring(utf8str)); + } + + nana::size graphics::bidi_extent_size(std::wstring_view text) const + { + nana::size sz; + if (impl_->handle && impl_->handle->context && text.size()) + { + auto const reordered = unicode_reorder(text.data(), text.size()); + for (auto & i : reordered) + { +#ifdef _nana_std_has_string_view + nana::size t = text_extent_size(std::wstring_view(i.begin, i.end - i.begin)); +#else + nana::size t = text_extent_size(i.begin, i.end - i.begin); +#endif + sz.width += t.width; + if (sz.height < t.height) + sz.height = t.height; + } + } + return sz; + } #else ::nana::size graphics::text_extent_size(const ::std::string& text) const { @@ -677,24 +705,21 @@ namespace paint return true; } -#endif - - nana::size graphics::bidi_extent_size(const std::wstring& str) const { nana::size sz; - if(impl_->handle && impl_->handle->context && str.size()) + if (impl_->handle && impl_->handle->context && str.size()) { auto const reordered = unicode_reorder(str.c_str(), str.size()); - for(auto & i: reordered) + for (auto & i : reordered) { #ifdef _nana_std_has_string_view - nana::size t = text_extent_size(std::wstring_view( i.begin, i.end - i.begin )); + nana::size t = text_extent_size(std::wstring_view(i.begin, i.end - i.begin)); #else nana::size t = text_extent_size(i.begin, i.end - i.begin); #endif sz.width += t.width; - if(sz.height < t.height) + if (sz.height < t.height) sz.height = t.height; } } @@ -705,6 +730,7 @@ namespace paint { return bidi_extent_size(static_cast(::nana::charset(str, ::nana::unicode::utf8))); } +#endif //end _nana_std_has_string_view bool graphics::text_metrics(unsigned & ascent, unsigned& descent, unsigned& internal_leading) const { @@ -1133,29 +1159,6 @@ namespace paint return *this; } - unsigned graphics::bidi_string(const nana::point& pos, const wchar_t * str, std::size_t len) - { - auto moved_pos = pos; - - auto const reordered = unicode_reorder(str, len); - for (auto & i : reordered) - { - string(moved_pos, i.begin, i.end - i.begin); -#ifdef _nana_std_has_string_view - moved_pos.x += static_cast(text_extent_size(std::wstring_view( i.begin, i.end - i.begin )).width); -#else - moved_pos.x += static_cast(text_extent_size(i.begin, i.end - i.begin).width); -#endif - } - return static_cast(moved_pos.x - pos.x); - } - - unsigned graphics::bidi_string(const point& pos, const char* str, std::size_t len) - { - std::wstring wstr = ::nana::charset(std::string(str, str + len), ::nana::unicode::utf8); - return bidi_string(pos, wstr.data(), wstr.size()); - } - void graphics::set_pixel(int x, int y, const ::nana::color& clr) { if (impl_->handle) @@ -1180,6 +1183,116 @@ namespace paint } } +#ifdef _nana_std_has_string_view + unsigned graphics::bidi_string(const point& pos, std::string_view utf8str) + { + return bidi_string(pos, to_wstring(utf8str)); + } + + unsigned graphics::bidi_string(const nana::point& pos, std::wstring_view str) + { + auto moved_pos = pos; + + auto const reordered = unicode_reorder(str.data(), str.size()); + for (auto & i : reordered) + { + +#ifdef _nana_std_has_string_view + this->string(moved_pos, std::wstring_view{ i.begin, static_cast(i.end - i.begin) }); + moved_pos.x += static_cast(text_extent_size(std::wstring_view(i.begin, i.end - i.begin)).width); +#else + this->string(moved_pos, i.begin, i.end - i.begin); + moved_pos.x += static_cast(text_extent_size(i.begin, i.end - i.begin).width); +#endif + } + return static_cast(moved_pos.x - pos.x); + } + + void graphics::string(const point& pos, std::string_view utf8str) + { + this->string(pos, to_wstring(utf8str)); + } + + void graphics::string(const point& pos, std::string_view utf8str, const nana::color& text_color) + { + palette(true, text_color); + string(pos, utf8str); + } + + void graphics::string(const nana::point& text_pos, std::wstring_view str) + { + if (impl_->handle && !str.empty()) + { +#if defined(NANA_POSIX) + impl_->handle->update_text_color(); +#endif + auto begin = str.data(); + auto const end = begin + str.size(); + auto i = std::find(begin, end, '\t'); + + if (i != end) + { + auto pos = text_pos; + std::size_t tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.tab_pixels; + while (true) + { + auto len = i - begin; + if (len) + { + //Render a part that does not contains a tab + detail::draw_string(impl_->handle, pos, begin, len); + pos.x += detail::real_text_extent_size(impl_->handle, begin, len).width; + } + + begin = i; + while (begin != end && (*begin == '\t')) + ++begin; + + if (begin != end) + { + //Now i_tab is not a tab, but a non-tab character following the previous tabs + pos.x += static_cast(tab_pixels * (begin - i)); + i = std::find(begin, end, '\t'); + } + else + break; + } + } + else + detail::draw_string(impl_->handle, text_pos, str.data(), str.size()); + if (impl_->changed == false) impl_->changed = true; + } + } + + void graphics::string(const point& pos, std::wstring_view str, const nana::color& text_color) + { + palette(true, text_color); + string(pos, str); + } +#else + unsigned graphics::bidi_string(const nana::point& pos, const wchar_t * str, std::size_t len) + { + auto moved_pos = pos; + + auto const reordered = unicode_reorder(str, len); + for (auto & i : reordered) + { + string(moved_pos, i.begin, i.end - i.begin); +#ifdef _nana_std_has_string_view + moved_pos.x += static_cast(text_extent_size(std::wstring_view(i.begin, i.end - i.begin)).width); +#else + moved_pos.x += static_cast(text_extent_size(i.begin, i.end - i.begin).width); +#endif + } + return static_cast(moved_pos.x - pos.x); + } + + unsigned graphics::bidi_string(const point& pos, const char* str, std::size_t len) + { + std::wstring wstr = ::nana::charset(std::string(str, str + len), ::nana::unicode::utf8); + return bidi_string(pos, wstr.data(), wstr.size()); + } + void graphics::string(const point& pos, const std::string& text_utf8) { string(pos, to_wstring(text_utf8)); @@ -1248,6 +1361,7 @@ namespace paint palette(true, clr); string(pos, text.data(), text.size()); } +#endif //_nana_std_has_string_view void graphics::line(const nana::point& pos1, const nana::point& pos2) { diff --git a/source/paint/text_renderer.cpp b/source/paint/text_renderer.cpp index 21a9157a..6f5654dd 100644 --- a/source/paint/text_renderer.cpp +++ b/source/paint/text_renderer.cpp @@ -169,8 +169,12 @@ namespace nana dum_graph.bitblt(r, graph, pos); +#ifdef _nana_std_has_string_view + dum_graph.string({}, { i.begin, len }, graph.palette(true)); +#else dum_graph.palette(true, graph.palette(true)); dum_graph.string({}, i.begin, len); +#endif r.x = pos.x; r.y = top; @@ -233,12 +237,11 @@ namespace nana const std::size_t len = i.end - i.begin; if(len > 1) { - std::unique_ptr pixel_buf(new unsigned[len]); - //Find the char that should be splitted #ifdef _nana_std_has_string_view - graph.glyph_pixels({ i.begin, len }, pixel_buf.get()); + auto pixel_buf = graph.glyph_pixels({ i.begin, len }); #else + std::unique_ptr pixel_buf(new unsigned[len]); graph.glyph_pixels(i.begin, len, pixel_buf.get()); #endif @@ -458,14 +461,16 @@ namespace nana std::size_t len = i.end - i.begin; if(len > 1) { - std::unique_ptr scope_res(new unsigned[len]); - auto pxbuf = scope_res.get(); //Find the char that should be splitted #ifdef _nana_std_has_string_view - graph.glyph_pixels({ i.begin, len }, pxbuf); + auto scope_res = graph.glyph_pixels({ i.begin, len }); + auto pxbuf = scope_res.get(); #else + std::unique_ptr scope_res(new unsigned[len]); + auto pxbuf = scope_res.get(); graph.glyph_pixels(i.begin, len, pxbuf); #endif + std::size_t idx_head = 0, idx_splitted; do @@ -639,15 +644,17 @@ namespace nana break; } +#ifdef _nana_std_has_string_view + graph_.bidi_string(pos, text); +#else graph_.bidi_string(pos, text.c_str(), text.size()); +#endif return; } #ifdef _nana_std_has_string_view const auto ellipsis = graph_.text_extent_size(std::string_view{ "...", 3 }).width; - - std::unique_ptr pixels(new unsigned[text.size()]); - graph_.glyph_pixels({ text.c_str(), text.size() }, pixels.get()); + auto pixels = graph_.glyph_pixels({ text.c_str(), text.size() }); #else const auto ellipsis = graph_.text_extent_size("...", 3).width; @@ -674,7 +681,11 @@ namespace nana } while (p != end); pos.x += static_cast(width - ellipsis - substr_px) + ellipsis; +#ifdef _nana_std_has_string_view + graph_.bidi_string(pos, { text.c_str() + substr_len, text.size() - substr_len }); +#else graph_.bidi_string(pos, text.c_str() + substr_len, text.size() - substr_len); +#endif pos.x -= ellipsis; } else @@ -691,8 +702,11 @@ namespace nana if (align::center == text_align_ex_) pos.x += (width - substr_px - ellipsis) / 2; - +#ifdef _nana_std_has_string_view + graph_.bidi_string(pos, { text.c_str(), substr_len }); +#else graph_.bidi_string(pos, text.c_str(), substr_len); +#endif pos.x += substr_px; }