From 0e8328eba3d2a3ce740332ae7ba0ade53ce32b8a Mon Sep 17 00:00:00 2001 From: Gheorghe Florian GLAVAN Date: Thu, 23 May 2019 12:17:30 +0300 Subject: [PATCH 1/4] fix for #440 (unicode_bidi aletter always true) --- source/unicode_bidi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/unicode_bidi.cpp b/source/unicode_bidi.cpp index 26eaf512..7b054e10 100644 --- a/source/unicode_bidi.cpp +++ b/source/unicode_bidi.cpp @@ -976,7 +976,7 @@ namespace nana return unicode_character_type::katakana; if (('A' <= ch && ch <= 'Z') || ('a' <= ch && ch <= 'z') || (0x00AA == ch || 0x00B5 == ch || 0x00BA == ch) || (0x00C0 <= ch && ch <= 0x00D6) || - (0x00D8 <= ch && ch <= 0x00F6) || (0x00F8 <= ch && ch <= 0x0236) || (0x0250 <= ch || ch <= 0x02C1)) + (0x00D8 <= ch && ch <= 0x00F6) || (0x00F8 <= ch && ch <= 0x0236) || (0x0250 <= ch && ch <= 0x02C1)) return unicode_character_type::aletter; if ('\'' == ch || 0x00AD == ch || 0x00B7 == ch || 0x05F4 == ch || 0x2019 == ch || 0x2027 == ch) From f57e8244312f9273fb5d654fcee58af4dfa29a64 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 1 Jun 2019 03:15:59 +0800 Subject: [PATCH 2/4] add support of multi-language under Linux(#439) also fix the font style issue under Linux --- include/nana/gui/programming_interface.hpp | 7 + source/detail/platform_abstraction.cpp | 486 +++++++++++++++++- source/detail/platform_abstraction.hpp | 3 +- source/gui/programming_interface.cpp | 5 + .../paint/detail/native_paint_interface.cpp | 29 +- source/paint/graphics.cpp | 10 +- 6 files changed, 514 insertions(+), 26 deletions(-) diff --git a/include/nana/gui/programming_interface.hpp b/include/nana/gui/programming_interface.hpp index 0b5e42ed..9c463521 100644 --- a/include/nana/gui/programming_interface.hpp +++ b/include/nana/gui/programming_interface.hpp @@ -183,6 +183,13 @@ namespace API }; }//end namespace detail + ///Sets languages + /** + * Specifies the languages in order to make the program display multi-languages correctly + * Under Windows, the pragram can display multi-languages correctly, so this function is useless for Windows. + */ + void font_languages(const std::string& langs); + void exit(); ///< close all windows in current thread void exit_all(); ///< close all windows diff --git a/source/detail/platform_abstraction.cpp b/source/detail/platform_abstraction.cpp index 515f6ace..ea6032b2 100644 --- a/source/detail/platform_abstraction.cpp +++ b/source/detail/platform_abstraction.cpp @@ -1,4 +1,5 @@ #include "platform_abstraction.hpp" +#include #include #include "../paint/truetype.hpp" @@ -153,6 +154,389 @@ IsWindows8OrGreater() namespace nana { +#ifdef NANA_USE_XFT + //A fallback fontset provides the multiple languages support. + class fallback_fontset + { + public: + fallback_fontset(): + disp_(::nana::detail::platform_spec::instance().open_display()) + { + } + + ~fallback_fontset() + { + for(auto xft: xftset_) + ::XftFontClose(disp_, xft); + } + + void open(const std::string& font_desc, const std::set& langs) + { + for(auto xft: xftset_) + ::XftFontClose(disp_, xft); + + xftset_.clear(); + + std::set loaded; + for(auto & lang : langs) + { + std::string patstr = "*" + font_desc + ":lang=" + lang; + + auto pat = ::XftNameParse(patstr.c_str()); + XftResult res; + auto match_pat = ::XftFontMatch(disp_, ::XDefaultScreen(disp_), pat, &res); + + if (match_pat) + { + char * sf; + if(XftResultTypeMismatch != ::XftPatternGetString(match_pat, "family", 0, &sf)) + { + //Avoid loading a some font repeatedly + if(loaded.count(sf)) + continue; + } + + auto xft = ::XftFontOpenPattern(disp_, match_pat); + if(xft) + xftset_.push_back(xft); + } + } + } + + int draw(::XftDraw* xftdraw, ::XftColor * xftcolor, ::XftFont* xft, int x, int y, const wchar_t* str, std::size_t len) + { + if(nullptr == str || 0 == len) + return 0; + + int const init_x = x; + std::unique_ptr glyph_indexes(new FT_UInt[len]); + + while(true) + { + auto preferred = _m_scan_fonts(xft, str, len, glyph_indexes.get()); + x += _m_draw(xftdraw, xftcolor, preferred.first, x, y, str, preferred.second, glyph_indexes.get()); + + if(len == preferred.second) + break; + + len -= preferred.second; + str += preferred.second; + } + + return x - init_x; + } + + std::unique_ptr glyph_pixels(::XftFont* xft, const wchar_t* str, std::size_t len) + { + if(nullptr == xft || nullptr == str || 0 == len) + return {}; + + std::unique_ptr glyph_indexes{new FT_UInt[len]}; + + std::unique_ptr pxbuf{new unsigned[len]}; + + auto pbuf = pxbuf.get(); + auto pstr = str; + auto size = len; + + while(true) + { + auto preferred = _m_scan_fonts(xft, pstr, size, glyph_indexes.get()); + + _m_glyph_px(preferred.first, pstr, preferred.second, glyph_indexes.get(), pbuf); + + if(size == preferred.second) + break; + + size -= preferred.second; + pstr += preferred.second; + pbuf += preferred.second; + } + + return pxbuf; + } + + nana::size extents(::XftFont* xft, const wchar_t* str, std::size_t len) + { + nana::size extent; + + if(nullptr == str || 0 == len) + return extent; + + std::unique_ptr glyph_indexes(new FT_UInt[len]); + + while(len > 0) + { + auto preferred = _m_scan_fonts(xft, str, len, glyph_indexes.get()); + + extent.width += _m_extents(preferred.first, str, preferred.second, glyph_indexes.get()); + + if(preferred.first->ascent + preferred.first->descent > static_cast(extent.height)) + extent.height = preferred.first->ascent + preferred.first->descent; + + len -= preferred.second; + str += preferred.second; + } + return extent; + } + private: + //Tab is a invisible character + int _m_draw(::XftDraw* xftdraw, ::XftColor* xftcolor, ::XftFont* xft, int x, int y, const wchar_t* str, std::size_t len, const FT_UInt* glyph_indexes) + { + int const init_x = x; + + auto p = str; + auto const end = str + len; + + y += xft->ascent; + + ::XGlyphInfo ext; + while(p < end) + { + auto off = p - str; + auto ptab = _m_find_tab(p, end); + if(ptab == p) + { + ++p; + //x += static_cast(tab_pixels_); + continue; + } + + auto const size = ptab - p; + ::XftDrawGlyphs(xftdraw, xftcolor, xft, x, y, glyph_indexes + off, size); + ::XftGlyphExtents(disp_, xft, glyph_indexes + off, size, &ext); + + x += ext.xOff; + + if(ptab == end) + break; + + p = ptab + 1; + } + + return x - init_x; + } + + //Tab is a invisible character + unsigned _m_extents(::XftFont* xft, const wchar_t* const str, const std::size_t len, const FT_UInt* glyph_indexes) + { + unsigned pixels = 0; + auto p = str; + auto const end = str + len; + + ::XGlyphInfo ext; + while(p < end) + { + auto off = p - str; + auto ptab = _m_find_tab(p, end); + if(ptab == p) + { + ++p; + //extents->xOff += tab_pixels_; + continue; + } + + ::XftGlyphExtents(disp_, xft, glyph_indexes + off, ptab - p, &ext); + + pixels += ext.xOff; + + if(end == ptab) + break; + p = ptab + 1; + } + + return pixels; + } + + //Tab is a invisible character + void _m_glyph_px(::XftFont* xft, const wchar_t* str, std::size_t len, const FT_UInt* glyph_indexes, unsigned* pxbuf) + { + auto const end = str + len; + + ::XGlyphInfo extent; + for(auto p = str; p < end; ++p) + { + if('\t' != *p) + { + ::XftGlyphExtents(disp_, xft, glyph_indexes, 1, &extent); + *pxbuf = extent.xOff; + } + else + *pxbuf = 0;//tab_pixels_; + + ++glyph_indexes; + } + } + + static const wchar_t* _m_find_tab(const wchar_t* begin, const wchar_t* end) + { + while(begin < end) + { + if('\t' == *begin) + return begin; + + ++begin; + } + return end; + } + + std::pair<::XftFont*, std::size_t> _m_scan_fonts(::XftFont* xft, const wchar_t* str, std::size_t len, FT_UInt* const glyphs) const + { + auto preferred = xft; + auto idx = ::XftCharIndex(disp_, xft, *str); + if(0 == idx) + { + for(auto ft : xftset_) + { + idx = ::XftCharIndex(disp_, ft, *str); + if(idx) + { + preferred = ft; + break; + } + } + } + + *glyphs = idx; + + if(0 == idx) + { + //scan the str with all fonts until a char index is found. + for(std::size_t i = 1; i < len; ++i) + { + if(::XftCharIndex(disp_, xft, str[i])) + return {preferred, i}; + + for(auto ft : xftset_) + { + if(::XftCharIndex(disp_, ft, str[i])) + return {preferred, i}; + } + glyphs[i] = 0; + } + + return {preferred, len}; + } + + //scan the str with preferred font until a char index is invalid. + for(std::size_t i = 1; i < len; ++i) + { + idx = ::XftCharIndex(disp_, preferred, str[i]); + if(0 == idx) + return {preferred, i}; + + glyphs[i] = idx; + } + + return {preferred, len}; + } + private: + Display* const disp_; + std::vector<::XftFont*> xftset_; + }; + + /// Fallback fontset manager + class fallback_manager + { + public: + fallback_manager(): + langs_(_m_split_lang("ar,hi,zh-cn,zh-tw,ja,ko,th")) + { + } + + void languages(const std::string& lang) + { + langs_ = _m_split_lang(lang); + + for(auto & xft : xft_table_) + { + xft.second->open(xft.first, langs_); + } + } + + std::shared_ptr make_fallback(const std::string& font_desc) + { + auto i = xft_table_.find(font_desc); + if(i != xft_table_.end()) + return i->second; + + auto fb = std::make_shared(); + + fb->open(font_desc, langs_); + + xft_table_[font_desc] = fb; + + return fb; + } + + void release_fallback(std::shared_ptr& p) + { + for(auto i = xft_table_.cbegin(); i != xft_table_.cend(); ++i) + { + if(i->second == p) + { + if(p.use_count() <= 2) + xft_table_.erase(i); + break; + } + } + } + + private: + static std::set _m_split_lang(const std::string& lang) + { + std::set langs; + std::size_t start_pos = 0; + while(true) + { + auto pos = lang.find(',', start_pos); + auto l = lang.substr(start_pos, lang.npos == pos? lang.npos : pos - start_pos); + + if(!l.empty()) + langs.insert(l); + + if(lang.npos == pos) + break; + + start_pos = pos + 1; + } + + return langs; + } + private: + std::set langs_; + std::map> xft_table_; + }; +#endif + + struct platform_runtime + { + std::shared_ptr font; + +#ifdef NANA_X11 + std::map fontconfig_counts; +#endif +#ifdef NANA_USE_XFT + fallback_manager fb_manager; +#endif + }; + + namespace + { + namespace data + { + static platform_runtime* storage; + } + } + + static platform_runtime& platform_storage() + { + if (nullptr == data::storage) + throw std::runtime_error("platform_abstraction is empty"); + + return *data::storage; + } + class internal_font : public font_interface @@ -160,13 +544,24 @@ namespace nana public: using path_type = std::filesystem::path; +#ifdef NANA_USE_XFT + internal_font(const path_type& ttf, const std::string& font_family, double font_size, const font_style& fs, native_font_type native_font, std::shared_ptr fallback): + ttf_(ttf), + family_(font_family), + size_(font_size), + style_(fs), + native_handle_(native_font), + fallback_(fallback) + {} +#else internal_font(const path_type& ttf, const std::string& font_family, double font_size, const font_style& fs, native_font_type native_font): ttf_(ttf), family_(font_family), size_(font_size), style_(fs), native_handle_(native_font) - {} + {} +#endif ~internal_font() { @@ -175,6 +570,7 @@ namespace nana #elif defined(NANA_X11) auto disp = ::nana::detail::platform_spec::instance().open_display(); # ifdef NANA_USE_XFT + platform_storage().fb_manager.release_fallback(fallback_); ::XftFontClose(disp, reinterpret_cast(native_handle_)); # else ::XFreeFontSet(disp, reinterpret_cast(native_handle_)); @@ -203,39 +599,58 @@ namespace nana { return native_handle_; } + +#ifdef NANA_USE_XFT + fallback_fontset* fallback() const + { + return fallback_.get(); + } +#endif private: path_type const ttf_; std::string const family_; double const size_; font_style const style_; native_font_type const native_handle_; - }; - - struct platform_runtime - { - std::shared_ptr font; - -#ifdef NANA_X11 - std::map fontconfig_counts; +#ifdef NANA_USE_XFT + std::shared_ptr fallback_; #endif }; - namespace +#ifdef NANA_USE_XFT + void nana_xft_draw_string(::XftDraw* xftdraw, ::XftColor* xftcolor, font_interface* ft, const nana::point& pos, const wchar_t * str, std::size_t len) { - namespace data - { - static platform_runtime* storage; - } + auto fallback = static_cast(ft)->fallback(); + if(nullptr == fallback) + return; + + auto xft = reinterpret_cast(static_cast(ft)->native_handle()); + fallback->draw(xftdraw, xftcolor, xft, pos.x, pos.y, str, len); } - static platform_runtime& platform_storage() - { - if (nullptr == data::storage) - throw std::runtime_error("platform_abstraction is empty"); - return *data::storage; + nana::size nana_xft_extents(font_interface* ft, const wchar_t* str, std::size_t len) + { + auto fallback = static_cast(ft)->fallback(); + if(nullptr == fallback) + return {}; + + auto xft = reinterpret_cast(static_cast(ft)->native_handle()); + return fallback->extents(xft, str, len); } + std::unique_ptr nana_xft_glyph_pixels(font_interface* ft, const wchar_t* str, std::size_t len) + { + auto fallback = static_cast(ft)->fallback(); + if(nullptr == fallback) + return {}; + + auto xft = reinterpret_cast(static_cast(ft)->native_handle()); + return fallback->glyph_pixels(xft, str, len); + } +#endif + + void platform_abstraction::initialize() { if (nullptr == data::storage) @@ -284,6 +699,13 @@ namespace nana #endif } + void platform_abstraction::font_languages(const std::string& langs) + { +#ifdef NANA_USE_XFT + platform_storage().fb_manager.languages(langs); +#endif + } + ::std::shared_ptr platform_abstraction::default_font(const ::std::shared_ptr& new_font) { auto & r = platform_storage(); @@ -364,10 +786,22 @@ namespace nana auto disp = ::nana::detail::platform_spec::instance().open_display(); # ifdef NANA_USE_XFT if(font_family.empty()) - font_family = '*'; + font_family = "*"; - std::string pat_str = font_family + '-' + std::to_string(size_pt ? size_pt : platform_abstraction::font_default_pt()); - auto pat = ::XftNameParse(pat_str.c_str()); + std::string pat_str = '-' + std::to_string(size_pt ? size_pt : platform_abstraction::font_default_pt()); + if(fs.weight < 400) + pat_str += ":light"; + else if(400 == fs.weight) + pat_str += ":medium"; + else if(fs.weight < 700) + pat_str += ":demibold"; + else + pat_str += (700 == fs.weight ? ":bold": ":black"); + + if(fs.italic) + pat_str += ":slant=italic"; + + auto pat = ::XftNameParse((font_family + pat_str).c_str()); XftResult res; auto match_pat = ::XftFontMatch(disp, ::XDefaultScreen(disp), pat, &res); @@ -387,8 +821,16 @@ namespace nana XFontSet fd = ::XCreateFontSet(display_, const_cast(pat_str.c_str()), &missing_list, &missing_count, &defstr); # endif #endif + if (fd) + { +#ifdef NANA_USE_XFT + auto fallback = platform_storage().fb_manager.make_fallback(pat_str); + return std::make_shared(std::move(ttf), std::move(font_family), size_pt, fs, reinterpret_cast(fd), fallback); +#else return std::make_shared(std::move(ttf), std::move(font_family), size_pt, fs, reinterpret_cast(fd)); +#endif + } return{}; } diff --git a/source/detail/platform_abstraction.hpp b/source/detail/platform_abstraction.hpp index 3e22112a..6af2d170 100644 --- a/source/detail/platform_abstraction.hpp +++ b/source/detail/platform_abstraction.hpp @@ -1,7 +1,7 @@ /* * Platform Abstraction * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2017 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2017-2019 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -34,6 +34,7 @@ namespace nana /// Shutdown before destruction of platform_spec static void shutdown(); static double font_default_pt(); + static void font_languages(const std::string&); static ::std::shared_ptr default_font(const ::std::shared_ptr&); static ::std::shared_ptr make_font(const ::std::string& font_family, double size_pt, const font::font_style& fs); static ::std::shared_ptr make_font_from_ttf(const path_type& ttf, double size_pt, const font::font_style& fs); diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index a73ec1bf..28b61836 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -441,6 +441,11 @@ namespace API return nullptr; } + void font_languages(const std::string& langs) + { + ::nana::platform_abstraction::font_languages(langs); + } + //close all windows in current thread void exit() { diff --git a/source/paint/detail/native_paint_interface.cpp b/source/paint/detail/native_paint_interface.cpp index 91b34a81..c31a27d7 100644 --- a/source/paint/detail/native_paint_interface.cpp +++ b/source/paint/detail/native_paint_interface.cpp @@ -1,7 +1,7 @@ /* * Platform Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -24,6 +24,12 @@ namespace nana { + //Forward-declarations + //These names are defined platform_abstraction.cpp + class font_interface; + void nana_xft_draw_string(::XftDraw* xftdraw, ::XftColor* xftcolor, font_interface* ft, const nana::point& pos, const wchar_t * str, std::size_t len); + nana::size nana_xft_extents(font_interface* ft, const wchar_t* str, std::size_t len); + namespace paint { namespace detail @@ -144,14 +150,19 @@ namespace detail if (::GetTextExtentPoint32(dw->context, text, static_cast(len), &size)) return nana::size(size.cx, size.cy); #elif defined(NANA_X11) - std::string utf8text = to_utf8(std::wstring(text, len)); #if defined(NANA_USE_XFT) + #if 0 + std::string utf8text = 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(utf8text.data())), utf8text.size(), &ext); return nana::size(ext.xOff, fs->ascent + fs->descent); + #else + return nana_xft_extents(dw->font.get(), text, len); + #endif #else + std::string utf8text = to_utf8(std::wstring(text, len)); XRectangle ink; XRectangle logic; ::XmbTextExtents(reinterpret_cast(dw->font->native_handle()), utf8text.c_str(), utf8text.size(), &ink, &logic); @@ -178,11 +189,20 @@ namespace detail return nana::size(size.cx, size.cy); #elif defined(NANA_X11) #if defined(NANA_USE_XFT) + #if 0 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 +#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 + return nana_xft_extents(dw->font.get(), wstr.data(), wstr.size()); + #endif #else XRectangle ink; XRectangle logic; @@ -240,6 +260,8 @@ namespace detail #elif defined(NANA_X11) auto disp = ::nana::detail::platform_spec::instance().open_display(); #if defined(NANA_USE_XFT) + + #if 0 auto fs = reinterpret_cast(dw->font->native_handle()); //Fixed missing array declaration by dareg @@ -251,6 +273,9 @@ namespace detail (*glyphs++) = XftCharIndex(disp, fs, *chr); } XftDrawGlyphs(dw->xftdraw, &(dw->xft_fgcolor), fs, pos.x, pos.y + fs->ascent, glyphs_ptr.get(), len); + #else + nana_xft_draw_string(dw->xftdraw, &(dw->xft_fgcolor), dw->font.get(), pos, str, len); + #endif #else XFontSet fs = reinterpret_cast(dw->font->native_handle()); XFontSetExtents * ext = ::XExtentsOfFontSet(fs); diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index c217dd70..9a89ba03 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -1,7 +1,7 @@ /* * Paint Graphics Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -28,6 +28,10 @@ namespace nana { + //Forward-declarations + //These names are defined platform_abstraction.cpp + std::unique_ptr nana_xft_glyph_pixels(font_interface*, const wchar_t* str, std::size_t len); + namespace detail { font_style::font_style(unsigned weight, bool italic, bool underline, bool strike_out) : @@ -517,6 +521,7 @@ namespace paint delete[] dx; #elif defined(NANA_X11) && defined(NANA_USE_XFT) + #if 0 auto disp = nana::detail::platform_spec::instance().open_display(); auto xft = reinterpret_cast(impl_->handle->font->native_handle()); @@ -532,6 +537,9 @@ namespace paint else pxbuf[i] = tab_pixels; } + #else + return nana_xft_glyph_pixels(impl_->handle->font.get(), text.data(), text.size()); + #endif #endif } return pxbuf; From 417071e4b531b608cf68150b5caef2cd847a6fc0 Mon Sep 17 00:00:00 2001 From: ErrorFlynn Date: Mon, 3 Jun 2019 17:51:21 -0400 Subject: [PATCH 3/4] fix for selection bug described in issue #448 --- source/gui/widgets/listbox.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 3660dce0..7dcb2b43 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -4350,6 +4350,8 @@ namespace nana } else lister.select_for_all(false, abs_item_pos); + + lister.latest_selected_abs = abs_item_pos; } } else From 3533b970921e3ee43e51c7fb8488cf2b120480f0 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Tue, 4 Jun 2019 08:45:39 +0800 Subject: [PATCH 4/4] XFT code incorrectly enabled under Windows --- source/paint/detail/native_paint_interface.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/paint/detail/native_paint_interface.cpp b/source/paint/detail/native_paint_interface.cpp index c31a27d7..db01ea30 100644 --- a/source/paint/detail/native_paint_interface.cpp +++ b/source/paint/detail/native_paint_interface.cpp @@ -24,11 +24,13 @@ namespace nana { +#ifdef NANA_USE_XFT //Forward-declarations //These names are defined platform_abstraction.cpp class font_interface; void nana_xft_draw_string(::XftDraw* xftdraw, ::XftColor* xftcolor, font_interface* ft, const nana::point& pos, const wchar_t * str, std::size_t len); nana::size nana_xft_extents(font_interface* ft, const wchar_t* str, std::size_t len); +#endif namespace paint {