diff --git a/include/nana/deploy.hpp b/include/nana/deploy.hpp index 686bb4ce..c9d12f88 100644 --- a/include/nana/deploy.hpp +++ b/include/nana/deploy.hpp @@ -1,7 +1,7 @@ /* * The Deploy 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 @@ -23,6 +23,10 @@ #include +#ifdef _nana_std_has_string_view +#include +#endif + namespace nana { /// move to *.h ?? @@ -44,10 +48,15 @@ namespace nana /// Checks whether a specified text is utf8 encoding +#ifdef _nana_std_has_string_view + bool is_utf8(std::string_view str); + void throw_not_utf8(std::string_view str); +#else bool is_utf8(const char* str, std::size_t len); void throw_not_utf8(const std::string& text); void throw_not_utf8(const char*, std::size_t len); void throw_not_utf8(const char*); +#endif /// this text needed change, it needed review ?? bool review_utf8(const std::string& text); @@ -58,7 +67,12 @@ namespace nana const std::string& to_utf8(const std::string&); std::string to_utf8(const std::wstring&); +#ifdef _nana_std_has_string_view + std::wstring to_wstring(std::string_view utf8_str); +#else std::wstring to_wstring(const std::string& utf8_str); +#endif + const std::wstring& to_wstring(const std::wstring& wstr); std::wstring&& to_wstring(std::wstring&& wstr); diff --git a/include/nana/paint/detail/native_paint_interface.hpp b/include/nana/paint/detail/native_paint_interface.hpp index 844427a5..a6cc4534 100644 --- a/include/nana/paint/detail/native_paint_interface.hpp +++ b/include/nana/paint/detail/native_paint_interface.hpp @@ -1,6 +1,6 @@ /* * Platform Implementation - * Copyright(C) 2003-2013 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 @@ -32,8 +32,11 @@ namespace detail //dw color = dw color * fade_rate + bdcolor * (1 - fade_rate) void blend(drawable_type dw, const nana::rectangle& r, pixel_color_t bdcolor, double fade_rate); - nana::size raw_text_extent_size(drawable_type, const wchar_t*, std::size_t len); + nana::size real_text_extent_size(drawable_type, const char*, std::size_t len); + nana::size real_text_extent_size(drawable_type, const wchar_t*, std::size_t len); + nana::size text_extent_size(drawable_type, const char*, std::size_t len); nana::size text_extent_size(drawable_type, const wchar_t*, std::size_t len); + void draw_string(drawable_type, const nana::point&, const wchar_t *, std::size_t len); }//end namespace detail }//end namespace paint diff --git a/include/nana/paint/graphics.hpp b/include/nana/paint/graphics.hpp index f3b33aa5..bea13f4b 100644 --- a/include/nana/paint/graphics.hpp +++ b/include/nana/paint/graphics.hpp @@ -21,6 +21,10 @@ #include "detail/ptdefs.hpp" +#ifdef _nana_std_has_string_view +#include +#endif + namespace nana { namespace paint @@ -108,12 +112,20 @@ namespace nana void resize(const ::nana::size&); void typeface(const font&); ///< Selects a specified font type into the graphics object. font typeface() const; + +#ifdef _nana_std_has_string_view + ::nana::size text_extent_size(std::string_view text) const; + ::nana::size text_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; + ::nana::size text_extent_size(const wchar_t*) const; ///< Computes the width and height of the specified string of text. ::nana::size text_extent_size(const ::std::wstring&) const; ///< Computes the width and height of the specified string of text. ::nana::size text_extent_size(const wchar_t*, std::size_t length) const; ///< Computes the width and height of the specified string of text with the specified length. ::nana::size text_extent_size(const ::std::wstring&, std::size_t length) const; ///< Computes the width and height of the specified string of text with the specified length. +#endif + ::nana::size glyph_extent_size(const wchar_t*, std::size_t length, std::size_t begin, std::size_t end) const; ::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; diff --git a/source/deploy.cpp b/source/deploy.cpp index a5050e77..06bbda02 100644 --- a/source/deploy.cpp +++ b/source/deploy.cpp @@ -28,6 +28,42 @@ namespace nana { +#ifdef _nana_std_has_string_view + bool is_utf8(std::string_view str) + { + auto ustr = reinterpret_cast(str.data()); + auto end = ustr + str.size(); + + while (ustr < end) + { + const auto uv = *ustr; + if (uv < 0x80) + { + ++ustr; + continue; + } + + if (uv < 0xC0) + return false; + + if ((uv < 0xE0) && (end - ustr > 1)) + ustr += 2; + else if ((uv < 0xF0) && (end - ustr > 2)) + ustr += 3; + else if ((uv < 0x1F) && (end - ustr > 3)) + ustr += 4; + else + return false; + } + return true; + } + + void throw_not_utf8(std::string_view str) + { + if (!is_utf8(str)) + return utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + std::string(str.data(), str.size())).emit(); + } +#else bool is_utf8(const char* str, std::size_t len) { auto ustr = reinterpret_cast(str); @@ -57,6 +93,23 @@ namespace nana return true; } + void throw_not_utf8(const std::string& text) + { + throw_not_utf8(text.c_str(), text.size()); + } + + void throw_not_utf8(const char* text) + { + throw_not_utf8(text, std::strlen(text)); + } + + void throw_not_utf8(const char* text, std::size_t len) + { + if (!is_utf8(text, len)) + return utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + std::string(text, len)).emit(); + } +#endif + //class utf8_Error #if defined(_MSC_VER) @@ -79,22 +132,6 @@ namespace nana bool utf8_Error::use_throw{ false }; //end class utf8_Error - void throw_not_utf8(const std::string& text) - { - throw_not_utf8(text.c_str(), text.size()); - } - - void throw_not_utf8(const char* text) - { - throw_not_utf8(text, std::strlen(text)); - } - - void throw_not_utf8(const char* text, std::size_t len) - { - if (!is_utf8(text, len)) - return utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + std::string(text, len) ).emit(); - } - std::string recode_to_utf8(std::string no_utf8) { return nana::charset(std::move(no_utf8)).to_bytes(nana::unicode::utf8); @@ -103,7 +140,11 @@ namespace nana /// this text needed change, it needed review ?? bool review_utf8(const std::string& text) { +#ifdef _nana_std_has_string_view + if (!is_utf8(text)) +#else if (!is_utf8(text.c_str(), text.length())) +#endif { utf8_Error(std::string("\nThe const text is not encoded in UTF8: ") + text).emit(); return true; /// it needed change, it needed review !! @@ -115,7 +156,11 @@ namespace nana /// this text needed change, it needed review ?? bool review_utf8(std::string& text) { +#ifdef _nana_std_has_string_view + if(!is_utf8(text)) +#else if (!is_utf8(text.c_str(), text.length())) +#endif { utf8_Error(std::string("\nThe text is not encoded in UTF8: ") + text).emit(); text=recode_to_utf8(text); @@ -135,10 +180,21 @@ namespace nana return ::nana::charset(text).to_bytes(::nana::unicode::utf8); } +#ifdef _nana_std_has_string_view + std::wstring to_wstring(std::string_view utf8_str) + { + if (utf8_str.empty()) + return{}; + + return ::nana::charset(std::string{ utf8_str.data(), utf8_str.size() }, unicode::utf8); + } +#else std::wstring to_wstring(const std::string& utf8_str) { return ::nana::charset(utf8_str, ::nana::unicode::utf8); } +#endif + const std::wstring& to_wstring(const std::wstring& wstr) { diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index ed81cef7..374b4250 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -393,8 +393,13 @@ namespace API { if (shortkey) { +#ifdef _nana_std_has_string_view + auto off_x = (shortkey_position ? graph.text_extent_size(std::string_view{ text.c_str(), shortkey_position }).width : 0); + auto key_px = static_cast(graph.text_extent_size(std::wstring_view{ &shortkey, 1 }).width); +#else auto off_x = (shortkey_position ? graph.text_extent_size(text.c_str(), shortkey_position).width : 0); auto key_px = static_cast(graph.text_extent_size(&shortkey, 1).width); +#endif unsigned ascent, descent, inleading; graph.text_metrics(ascent, descent, inleading); diff --git a/source/gui/widgets/checkbox.cpp b/source/gui/widgets/checkbox.cpp index 7fc20469..66fb22de 100644 --- a/source/gui/widgets/checkbox.cpp +++ b/source/gui/widgets/checkbox.cpp @@ -78,7 +78,11 @@ namespace nana{ namespace drawerbase } //draw crook +#ifdef _nana_std_has_string_view + auto txt_px = graph.text_extent_size(std::wstring_view( L"jN", 2 )).height + 2; +#else auto txt_px = graph.text_extent_size(L"jN", 2).height + 2; +#endif impl_->crook.draw(graph, wdg->bgcolor(), wdg->fgcolor(), rectangle(0, txt_px > 16 ? (txt_px - 16) / 2 : 0, 16, 16), API::element_state(*wdg)); } diff --git a/source/gui/widgets/label.cpp b/source/gui/widgets/label.cpp index bf670c12..8168984e 100644 --- a/source/gui/widgets/label.cpp +++ b/source/gui/widgets/label.cpp @@ -83,7 +83,11 @@ namespace nana auto pre_font = graph.typeface(); //used for restoring the font +#ifdef _nana_std_has_string_view + const unsigned def_line_pixels = graph.text_extent_size(std::wstring_view{ L" ", 1 }).height; +#else const unsigned def_line_pixels = graph.text_extent_size(L" ", 1).height; +#endif font_ = pre_font; fblock_ = nullptr; @@ -170,7 +174,11 @@ namespace nana auto ft = graph.typeface(); //used for restoring the font +#ifdef _nana_std_has_string_view + const unsigned def_line_pixels = graph.text_extent_size(std::wstring_view(L" ", 1)).height; +#else const unsigned def_line_pixels = graph.text_extent_size(L" ", 1).height; +#endif font_ = ft; fblock_ = nullptr; diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index 38a4666f..9dc06848 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -3147,7 +3147,11 @@ namespace nana{ namespace widgets maskstr.append(n, mask_char_); return graph_.text_extent_size(maskstr); } +#ifdef _nana_std_has_string_view + return graph_.text_extent_size(std::basic_string_view(str, n)); +#else return graph_.text_extent_size(str, static_cast(n)); +#endif } bool text_editor::_m_adjust_view() @@ -3500,7 +3504,12 @@ namespace nana{ namespace widgets for (auto & ent : reordered) { std::size_t len = ent.end - ent.begin; + +#ifdef _nana_std_has_string_view + unsigned str_w = graph_.text_extent_size(std::wstring_view{ ent.begin, len }).width; +#else unsigned str_w = graph_.text_extent_size(ent.begin, len).width; +#endif if ((text_draw_pos.x + static_cast(str_w) > text_area_.area.x) && (text_draw_pos.x < text_right)) { @@ -3519,7 +3528,11 @@ namespace nana{ namespace widgets for (auto & ent : reordered) { const auto len = ent.end - ent.begin; +#ifdef _nana_std_has_string_view + auto ent_px = graph_.text_extent_size(std::wstring_view(ent.begin, len)).width; +#else auto ent_px = graph_.text_extent_size(ent.begin, len).width; +#endif extra_space = false; @@ -3589,7 +3602,11 @@ namespace nana{ namespace widgets auto pos = text_coord.x + text_len; if (b.x != pos || text_coord.y != b.y) { +#ifdef _nana_std_has_string_view + auto whitespace_w = graph_.text_extent_size(std::wstring_view{ L" ", 1 }).width; +#else auto whitespace_w = graph_.text_extent_size(L" ", 1).width; +#endif graph_.rectangle(::nana::rectangle{ text_draw_pos, { whitespace_w, line_h_pixels } }, true); } } diff --git a/source/gui/widgets/treebox.cpp b/source/gui/widgets/treebox.cpp index 19873e27..c68abb4c 100644 --- a/source/gui/widgets/treebox.cpp +++ b/source/gui/widgets/treebox.cpp @@ -1163,7 +1163,11 @@ namespace nana virtual unsigned item_height(graph_reference graph) const override { +#ifdef _nana_std_has_string_view + return graph.text_extent_size(std::wstring_view{ L"jH{", 3 }).height + 8; +#else return graph.text_extent_size(L"jH{", 3).height + 8; +#endif } virtual unsigned item_width(graph_reference graph, const item_attribute_t& attr) const override diff --git a/source/paint/detail/native_paint_interface.cpp b/source/paint/detail/native_paint_interface.cpp index 6efb8169..7703747c 100644 --- a/source/paint/detail/native_paint_interface.cpp +++ b/source/paint/detail/native_paint_interface.cpp @@ -134,29 +134,80 @@ namespace detail pixbuf.paste(nana::rectangle(r.x, 0, r.width, r.height), dw, point{r.x, r.y}); } - nana::size raw_text_extent_size(drawable_type dw, const wchar_t* text, std::size_t len) + nana::size real_text_extent_size(drawable_type dw, const wchar_t* text, std::size_t len) { - if(nullptr == dw || nullptr == text || 0 == len) return nana::size(); + if (dw && text && len) + { + #if defined(NANA_WINDOWS) - ::SIZE size; - if(::GetTextExtentPoint32(dw->context, text, static_cast(len), &size)) - return nana::size(size.cx, size.cy); + ::SIZE size; + if (::GetTextExtentPoint32(dw->context, text, static_cast(len), &size)) + return nana::size(size.cx, size.cy); #elif defined(NANA_X11) - #if defined(NANA_USE_XFT) - std::string utf8str = to_utf8(std::wstring(text, len)); - XGlyphInfo ext; - XftFont * fs = reinterpret_cast(dw->font->native_handle()); - ::XftTextExtentsUtf8(nana::detail::platform_spec::instance().open_display(), fs, - reinterpret_cast(const_cast(utf8str.c_str())), utf8str.size(), &ext); - return nana::size(ext.xOff, fs->ascent + fs->descent); - #else - XRectangle ink; - XRectangle logic; - ::XmbTextExtents(reinterpret_cast(dw->font->native_handle()), text, len, &ink, &logic); - return nana::size(logic.width, logic.height); - #endif + std::string utf8str = to_utf8(std::wstring(text, len)); +#if defined(NANA_USE_XFT) + XGlyphInfo ext; + XftFont * fs = reinterpret_cast(dw->font->native_handle()); + ::XftTextExtentsUtf8(nana::detail::platform_spec::instance().open_display(), fs, + reinterpret_cast(const_cast(utf8text.data())), utf8text.size(), &ext); + return nana::size(ext.xOff, fs->ascent + fs->descent); +#else + XRectangle ink; + XRectangle logic; + ::XmbTextExtents(reinterpret_cast(dw->font->native_handle()), utf8str.c_str(), utf8str.size(), &ink, &logic); + return nana::size(logic.width, logic.height); #endif - return nana::size(); +#endif + } + return {}; + } + + nana::size real_text_extent_size(drawable_type dw, const char* text, std::size_t len) + { + if (dw && text && len) + { + +#if defined(NANA_WINDOWS) + auto wstr = to_wstring(std::string(text,len)); + ::SIZE size; + if (::GetTextExtentPoint32(dw->context, wstr.c_str(), static_cast(wstr.size()), &size)) + return nana::size(size.cx, size.cy); +#elif defined(NANA_X11) +#if defined(NANA_USE_XFT) + XGlyphInfo ext; + XftFont * fs = reinterpret_cast(dw->font->native_handle()); + ::XftTextExtentsUtf8(nana::detail::platform_spec::instance().open_display(), fs, + reinterpret_cast(const_cast(text)), len, &ext); + return nana::size(ext.xOff, fs->ascent + fs->descent); +#else + XRectangle ink; + XRectangle logic; + ::XmbTextExtents(reinterpret_cast(dw->font->native_handle()), text, len, &ink, &logic); + return nana::size(logic.width, logic.height); +#endif +#endif + } + return {}; + } + + + nana::size text_extent_size(drawable_type dw, const char * text, std::size_t len) + { + if (nullptr == dw || nullptr == text || 0 == len) + return{}; + + nana::size extents = real_text_extent_size(dw, text, len); + + auto const end = text + len; + int tabs = 0; + for (; text != end; ++text) + { + if (*text == '\t') + ++tabs; + } + if (tabs) + extents.width = static_cast(extents.width) - tabs * static_cast(dw->string.tab_pixels - dw->string.whitespace_pixels * dw->string.tab_length); + return extents; } nana::size text_extent_size(drawable_type dw, const wchar_t * text, std::size_t len) @@ -164,7 +215,7 @@ namespace detail if (nullptr == dw || nullptr == text || 0 == len) return{}; - nana::size extents = raw_text_extent_size(dw, text, len); + nana::size extents = real_text_extent_size(dw, text, len); const wchar_t* const end = text + len; int tabs = 0; diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index 2d92b435..46b685d1 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -411,8 +411,8 @@ namespace paint impl_->handle = dw.get(); impl_->size = sz; - impl_->handle->string.tab_pixels = detail::raw_text_extent_size(impl_->handle, L"\t", 1).width; - impl_->handle->string.whitespace_pixels = detail::raw_text_extent_size(impl_->handle, L" ", 1).width; + impl_->handle->string.tab_pixels = detail::real_text_extent_size(impl_->handle, L"\t", 1).width; + impl_->handle->string.whitespace_pixels = detail::real_text_extent_size(impl_->handle, L" ", 1).width; } } @@ -438,8 +438,9 @@ namespace paint #if defined(NANA_WINDOWS) ::SelectObject(impl_->handle->context, reinterpret_cast(f.impl_->real_font->native_handle())); #endif - impl_->handle->string.tab_pixels = detail::raw_text_extent_size(impl_->handle, L"\t", 1).width; - impl_->handle->string.whitespace_pixels = detail::raw_text_extent_size(impl_->handle, L" ", 1).width; + + impl_->handle->string.tab_pixels = detail::real_text_extent_size(impl_->handle, L"\t", 1).width; + impl_->handle->string.whitespace_pixels = detail::real_text_extent_size(impl_->handle, L" ", 1).width; if (impl_->changed == false) impl_->changed = true; @@ -453,6 +454,20 @@ namespace paint return (impl_->handle ? font(impl_->handle) : impl_->font_shadow); } +#ifdef _nana_std_has_string_view + size graphics::text_extent_size(std::string_view text) const + { + throw_not_utf8(text); + return detail::text_extent_size(impl_->handle, text.data(), text.length()); + } + + size graphics::text_extent_size(std::wstring_view text) const + { + return detail::text_extent_size(impl_->handle, text.data(), text.length()); + } + + +#else ::nana::size graphics::text_extent_size(const ::std::string& text) const { throw_not_utf8(text); @@ -483,6 +498,7 @@ namespace paint { return detail::text_extent_size(impl_->handle, str.c_str(), len); } +#endif nana::size graphics::glyph_extent_size(const wchar_t * str, std::size_t len, std::size_t begin, std::size_t end) const { @@ -562,7 +578,11 @@ namespace paint auto const reordered = unicode_reorder(str.c_str(), str.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; @@ -1011,7 +1031,11 @@ namespace paint 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); } @@ -1076,7 +1100,7 @@ namespace paint { //Render a part that does not contains a tab detail::draw_string(impl_->handle, pos, str, len); - pos.x += detail::raw_text_extent_size(impl_->handle, str, len).width; + pos.x += detail::real_text_extent_size(impl_->handle, str, len).width; } str = i; diff --git a/source/paint/text_renderer.cpp b/source/paint/text_renderer.cpp index 07b71e0f..b2848c2f 100644 --- a/source/paint/text_renderer.cpp +++ b/source/paint/text_renderer.cpp @@ -52,6 +52,7 @@ namespace nana { std::size_t len = ent.end - ent.begin; nana::size ts = detail::text_extent_size(dw, ent.begin, len); + if(ts.height > pixels) pixels = ts.height; if(pos.x + static_cast(ts.width) > 0) @@ -128,7 +129,11 @@ namespace nana draw_string_omitted(graphics& graph, int x, int endpos, bool omitted) : graph(graph), x(x), endpos(endpos) { +#ifdef _nana_std_has_string_view + omitted_pixels = (omitted ? graph.text_extent_size(std::string_view{ "...", 3 }).width : 0); +#else omitted_pixels = (omitted ? graph.text_extent_size("...", 3).width : 0); +#endif if (endpos - x > static_cast(omitted_pixels)) this->endpos -= omitted_pixels; else @@ -629,7 +634,11 @@ namespace nana return; } +#ifdef _nana_std_has_string_view + const auto ellipsis = graph_.text_extent_size(std::string_view{ "...", 3 }).width; +#else const auto ellipsis = graph_.text_extent_size("...", 3).width; +#endif std::unique_ptr pixels(new unsigned[text.size()]); graph_.glyph_pixels(text.c_str(), text.size(), pixels.get());