Merge branch 'hotfix-1.7.1' into develop
This commit is contained in:
commit
7d27f152f4
@ -183,6 +183,13 @@ namespace API
|
|||||||
};
|
};
|
||||||
}//end namespace detail
|
}//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(); ///< close all windows in current thread
|
||||||
void exit_all(); ///< close all windows
|
void exit_all(); ///< close all windows
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "platform_abstraction.hpp"
|
#include "platform_abstraction.hpp"
|
||||||
|
#include <set>
|
||||||
#include <nana/deploy.hpp>
|
#include <nana/deploy.hpp>
|
||||||
#include "../paint/truetype.hpp"
|
#include "../paint/truetype.hpp"
|
||||||
|
|
||||||
@ -153,6 +154,389 @@ IsWindows8OrGreater()
|
|||||||
|
|
||||||
namespace nana
|
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<std::string>& langs)
|
||||||
|
{
|
||||||
|
for(auto xft: xftset_)
|
||||||
|
::XftFontClose(disp_, xft);
|
||||||
|
|
||||||
|
xftset_.clear();
|
||||||
|
|
||||||
|
std::set<std::string> 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<FT_UInt[]> 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<unsigned[]> glyph_pixels(::XftFont* xft, const wchar_t* str, std::size_t len)
|
||||||
|
{
|
||||||
|
if(nullptr == xft || nullptr == str || 0 == len)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
std::unique_ptr<FT_UInt[]> glyph_indexes{new FT_UInt[len]};
|
||||||
|
|
||||||
|
std::unique_ptr<unsigned[]> 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<FT_UInt[]> 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<int>(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<int>(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<fallback_fontset> 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<fallback_fontset>();
|
||||||
|
|
||||||
|
fb->open(font_desc, langs_);
|
||||||
|
|
||||||
|
xft_table_[font_desc] = fb;
|
||||||
|
|
||||||
|
return fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release_fallback(std::shared_ptr<fallback_fontset>& 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<std::string> _m_split_lang(const std::string& lang)
|
||||||
|
{
|
||||||
|
std::set<std::string> 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<std::string> langs_;
|
||||||
|
std::map<std::string, std::shared_ptr<fallback_fontset>> xft_table_;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct platform_runtime
|
||||||
|
{
|
||||||
|
std::shared_ptr<font_interface> font;
|
||||||
|
|
||||||
|
#ifdef NANA_X11
|
||||||
|
std::map<std::string, std::size_t> 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
|
class internal_font
|
||||||
: public font_interface
|
: public font_interface
|
||||||
@ -160,6 +544,16 @@ namespace nana
|
|||||||
public:
|
public:
|
||||||
using path_type = std::filesystem::path;
|
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_fontset> 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):
|
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),
|
ttf_(ttf),
|
||||||
family_(font_family),
|
family_(font_family),
|
||||||
@ -167,6 +561,7 @@ namespace nana
|
|||||||
style_(fs),
|
style_(fs),
|
||||||
native_handle_(native_font)
|
native_handle_(native_font)
|
||||||
{}
|
{}
|
||||||
|
#endif
|
||||||
|
|
||||||
~internal_font()
|
~internal_font()
|
||||||
{
|
{
|
||||||
@ -175,6 +570,7 @@ namespace nana
|
|||||||
#elif defined(NANA_X11)
|
#elif defined(NANA_X11)
|
||||||
auto disp = ::nana::detail::platform_spec::instance().open_display();
|
auto disp = ::nana::detail::platform_spec::instance().open_display();
|
||||||
# ifdef NANA_USE_XFT
|
# ifdef NANA_USE_XFT
|
||||||
|
platform_storage().fb_manager.release_fallback(fallback_);
|
||||||
::XftFontClose(disp, reinterpret_cast<XftFont*>(native_handle_));
|
::XftFontClose(disp, reinterpret_cast<XftFont*>(native_handle_));
|
||||||
# else
|
# else
|
||||||
::XFreeFontSet(disp, reinterpret_cast<XFontSet>(native_handle_));
|
::XFreeFontSet(disp, reinterpret_cast<XFontSet>(native_handle_));
|
||||||
@ -203,39 +599,58 @@ namespace nana
|
|||||||
{
|
{
|
||||||
return native_handle_;
|
return native_handle_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NANA_USE_XFT
|
||||||
|
fallback_fontset* fallback() const
|
||||||
|
{
|
||||||
|
return fallback_.get();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
private:
|
private:
|
||||||
path_type const ttf_;
|
path_type const ttf_;
|
||||||
std::string const family_;
|
std::string const family_;
|
||||||
double const size_;
|
double const size_;
|
||||||
font_style const style_;
|
font_style const style_;
|
||||||
native_font_type const native_handle_;
|
native_font_type const native_handle_;
|
||||||
};
|
#ifdef NANA_USE_XFT
|
||||||
|
std::shared_ptr<fallback_fontset> fallback_;
|
||||||
struct platform_runtime
|
|
||||||
{
|
|
||||||
std::shared_ptr<font_interface> font;
|
|
||||||
|
|
||||||
#ifdef NANA_X11
|
|
||||||
std::map<std::string, std::size_t> fontconfig_counts;
|
|
||||||
#endif
|
#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
|
auto fallback = static_cast<internal_font*>(ft)->fallback();
|
||||||
{
|
if(nullptr == fallback)
|
||||||
static platform_runtime* storage;
|
return;
|
||||||
}
|
|
||||||
|
auto xft = reinterpret_cast<XftFont*>(static_cast<internal_font*>(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<internal_font*>(ft)->fallback();
|
||||||
|
if(nullptr == fallback)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto xft = reinterpret_cast<XftFont*>(static_cast<internal_font*>(ft)->native_handle());
|
||||||
|
return fallback->extents(xft, str, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<unsigned[]> nana_xft_glyph_pixels(font_interface* ft, const wchar_t* str, std::size_t len)
|
||||||
|
{
|
||||||
|
auto fallback = static_cast<internal_font*>(ft)->fallback();
|
||||||
|
if(nullptr == fallback)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto xft = reinterpret_cast<XftFont*>(static_cast<internal_font*>(ft)->native_handle());
|
||||||
|
return fallback->glyph_pixels(xft, str, len);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void platform_abstraction::initialize()
|
void platform_abstraction::initialize()
|
||||||
{
|
{
|
||||||
if (nullptr == data::storage)
|
if (nullptr == data::storage)
|
||||||
@ -284,6 +699,13 @@ namespace nana
|
|||||||
#endif
|
#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::font> platform_abstraction::default_font(const ::std::shared_ptr<font>& new_font)
|
::std::shared_ptr<platform_abstraction::font> platform_abstraction::default_font(const ::std::shared_ptr<font>& new_font)
|
||||||
{
|
{
|
||||||
auto & r = platform_storage();
|
auto & r = platform_storage();
|
||||||
@ -364,10 +786,22 @@ namespace nana
|
|||||||
auto disp = ::nana::detail::platform_spec::instance().open_display();
|
auto disp = ::nana::detail::platform_spec::instance().open_display();
|
||||||
# ifdef NANA_USE_XFT
|
# ifdef NANA_USE_XFT
|
||||||
if(font_family.empty())
|
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());
|
std::string pat_str = '-' + std::to_string(size_pt ? size_pt : platform_abstraction::font_default_pt());
|
||||||
auto pat = ::XftNameParse(pat_str.c_str());
|
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;
|
XftResult res;
|
||||||
auto match_pat = ::XftFontMatch(disp, ::XDefaultScreen(disp), pat, &res);
|
auto match_pat = ::XftFontMatch(disp, ::XDefaultScreen(disp), pat, &res);
|
||||||
|
|
||||||
@ -387,8 +821,16 @@ namespace nana
|
|||||||
XFontSet fd = ::XCreateFontSet(display_, const_cast<char*>(pat_str.c_str()), &missing_list, &missing_count, &defstr);
|
XFontSet fd = ::XCreateFontSet(display_, const_cast<char*>(pat_str.c_str()), &missing_list, &missing_count, &defstr);
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (fd)
|
if (fd)
|
||||||
|
{
|
||||||
|
#ifdef NANA_USE_XFT
|
||||||
|
auto fallback = platform_storage().fb_manager.make_fallback(pat_str);
|
||||||
|
return std::make_shared<internal_font>(std::move(ttf), std::move(font_family), size_pt, fs, reinterpret_cast<native_font_type>(fd), fallback);
|
||||||
|
#else
|
||||||
return std::make_shared<internal_font>(std::move(ttf), std::move(font_family), size_pt, fs, reinterpret_cast<native_font_type>(fd));
|
return std::make_shared<internal_font>(std::move(ttf), std::move(font_family), size_pt, fs, reinterpret_cast<native_font_type>(fd));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
return{};
|
return{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Platform Abstraction
|
* Platform Abstraction
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* 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.
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
@ -34,6 +34,7 @@ namespace nana
|
|||||||
/// Shutdown before destruction of platform_spec
|
/// Shutdown before destruction of platform_spec
|
||||||
static void shutdown();
|
static void shutdown();
|
||||||
static double font_default_pt();
|
static double font_default_pt();
|
||||||
|
static void font_languages(const std::string&);
|
||||||
static ::std::shared_ptr<font> default_font(const ::std::shared_ptr<font>&);
|
static ::std::shared_ptr<font> default_font(const ::std::shared_ptr<font>&);
|
||||||
static ::std::shared_ptr<font> make_font(const ::std::string& font_family, double size_pt, const font::font_style& fs);
|
static ::std::shared_ptr<font> make_font(const ::std::string& font_family, double size_pt, const font::font_style& fs);
|
||||||
static ::std::shared_ptr<font> make_font_from_ttf(const path_type& ttf, double size_pt, const font::font_style& fs);
|
static ::std::shared_ptr<font> make_font_from_ttf(const path_type& ttf, double size_pt, const font::font_style& fs);
|
||||||
|
@ -441,6 +441,11 @@ namespace API
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void font_languages(const std::string& langs)
|
||||||
|
{
|
||||||
|
::nana::platform_abstraction::font_languages(langs);
|
||||||
|
}
|
||||||
|
|
||||||
//close all windows in current thread
|
//close all windows in current thread
|
||||||
void exit()
|
void exit()
|
||||||
{
|
{
|
||||||
|
@ -4353,6 +4353,8 @@ namespace nana
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
lister.select_for_all(false, abs_item_pos);
|
lister.select_for_all(false, abs_item_pos);
|
||||||
|
|
||||||
|
lister.latest_selected_abs = abs_item_pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Platform Implementation
|
* Platform Implementation
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* 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.
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
@ -24,6 +24,14 @@
|
|||||||
|
|
||||||
namespace nana
|
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
|
namespace paint
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
@ -144,14 +152,19 @@ namespace detail
|
|||||||
if (::GetTextExtentPoint32(dw->context, text, static_cast<int>(len), &size))
|
if (::GetTextExtentPoint32(dw->context, text, static_cast<int>(len), &size))
|
||||||
return nana::size(size.cx, size.cy);
|
return nana::size(size.cx, size.cy);
|
||||||
#elif defined(NANA_X11)
|
#elif defined(NANA_X11)
|
||||||
std::string utf8text = to_utf8(std::wstring(text, len));
|
|
||||||
#if defined(NANA_USE_XFT)
|
#if defined(NANA_USE_XFT)
|
||||||
|
#if 0
|
||||||
|
std::string utf8text = to_utf8(std::wstring(text, len));
|
||||||
XGlyphInfo ext;
|
XGlyphInfo ext;
|
||||||
XftFont * fs = reinterpret_cast<XftFont*>(dw->font->native_handle());
|
XftFont * fs = reinterpret_cast<XftFont*>(dw->font->native_handle());
|
||||||
::XftTextExtentsUtf8(nana::detail::platform_spec::instance().open_display(), fs,
|
::XftTextExtentsUtf8(nana::detail::platform_spec::instance().open_display(), fs,
|
||||||
reinterpret_cast<XftChar8*>(const_cast<char*>(utf8text.data())), utf8text.size(), &ext);
|
reinterpret_cast<XftChar8*>(const_cast<char*>(utf8text.data())), utf8text.size(), &ext);
|
||||||
return nana::size(ext.xOff, fs->ascent + fs->descent);
|
return nana::size(ext.xOff, fs->ascent + fs->descent);
|
||||||
#else
|
#else
|
||||||
|
return nana_xft_extents(dw->font.get(), text, len);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
std::string utf8text = to_utf8(std::wstring(text, len));
|
||||||
XRectangle ink;
|
XRectangle ink;
|
||||||
XRectangle logic;
|
XRectangle logic;
|
||||||
::XmbTextExtents(reinterpret_cast<XFontSet>(dw->font->native_handle()), utf8text.c_str(), utf8text.size(), &ink, &logic);
|
::XmbTextExtents(reinterpret_cast<XFontSet>(dw->font->native_handle()), utf8text.c_str(), utf8text.size(), &ink, &logic);
|
||||||
@ -178,12 +191,21 @@ namespace detail
|
|||||||
return nana::size(size.cx, size.cy);
|
return nana::size(size.cx, size.cy);
|
||||||
#elif defined(NANA_X11)
|
#elif defined(NANA_X11)
|
||||||
#if defined(NANA_USE_XFT)
|
#if defined(NANA_USE_XFT)
|
||||||
|
#if 0
|
||||||
XGlyphInfo ext;
|
XGlyphInfo ext;
|
||||||
XftFont * fs = reinterpret_cast<XftFont*>(dw->font->native_handle());
|
XftFont * fs = reinterpret_cast<XftFont*>(dw->font->native_handle());
|
||||||
::XftTextExtentsUtf8(nana::detail::platform_spec::instance().open_display(), fs,
|
::XftTextExtentsUtf8(nana::detail::platform_spec::instance().open_display(), fs,
|
||||||
reinterpret_cast<XftChar8*>(const_cast<char*>(text)), len, &ext);
|
reinterpret_cast<XftChar8*>(const_cast<char*>(text)), len, &ext);
|
||||||
return nana::size(ext.xOff, fs->ascent + fs->descent);
|
return nana::size(ext.xOff, fs->ascent + fs->descent);
|
||||||
#else
|
#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 ink;
|
||||||
XRectangle logic;
|
XRectangle logic;
|
||||||
::XmbTextExtents(reinterpret_cast<XFontSet>(dw->font->native_handle()), text, len, &ink, &logic);
|
::XmbTextExtents(reinterpret_cast<XFontSet>(dw->font->native_handle()), text, len, &ink, &logic);
|
||||||
@ -240,6 +262,8 @@ namespace detail
|
|||||||
#elif defined(NANA_X11)
|
#elif defined(NANA_X11)
|
||||||
auto disp = ::nana::detail::platform_spec::instance().open_display();
|
auto disp = ::nana::detail::platform_spec::instance().open_display();
|
||||||
#if defined(NANA_USE_XFT)
|
#if defined(NANA_USE_XFT)
|
||||||
|
|
||||||
|
#if 0
|
||||||
auto fs = reinterpret_cast<XftFont*>(dw->font->native_handle());
|
auto fs = reinterpret_cast<XftFont*>(dw->font->native_handle());
|
||||||
|
|
||||||
//Fixed missing array declaration by dareg
|
//Fixed missing array declaration by dareg
|
||||||
@ -251,6 +275,9 @@ namespace detail
|
|||||||
(*glyphs++) = XftCharIndex(disp, fs, *chr);
|
(*glyphs++) = XftCharIndex(disp, fs, *chr);
|
||||||
}
|
}
|
||||||
XftDrawGlyphs(dw->xftdraw, &(dw->xft_fgcolor), fs, pos.x, pos.y + fs->ascent, glyphs_ptr.get(), len);
|
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
|
#else
|
||||||
XFontSet fs = reinterpret_cast<XFontSet>(dw->font->native_handle());
|
XFontSet fs = reinterpret_cast<XFontSet>(dw->font->native_handle());
|
||||||
XFontSetExtents * ext = ::XExtentsOfFontSet(fs);
|
XFontSetExtents * ext = ::XExtentsOfFontSet(fs);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Paint Graphics Implementation
|
* Paint Graphics Implementation
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* 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.
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
@ -28,6 +28,10 @@
|
|||||||
|
|
||||||
namespace nana
|
namespace nana
|
||||||
{
|
{
|
||||||
|
//Forward-declarations
|
||||||
|
//These names are defined platform_abstraction.cpp
|
||||||
|
std::unique_ptr<unsigned[]> nana_xft_glyph_pixels(font_interface*, const wchar_t* str, std::size_t len);
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
font_style::font_style(unsigned weight, bool italic, bool underline, bool strike_out) :
|
font_style::font_style(unsigned weight, bool italic, bool underline, bool strike_out) :
|
||||||
@ -517,6 +521,7 @@ namespace paint
|
|||||||
delete[] dx;
|
delete[] dx;
|
||||||
#elif defined(NANA_X11) && defined(NANA_USE_XFT)
|
#elif defined(NANA_X11) && defined(NANA_USE_XFT)
|
||||||
|
|
||||||
|
#if 0
|
||||||
auto disp = nana::detail::platform_spec::instance().open_display();
|
auto disp = nana::detail::platform_spec::instance().open_display();
|
||||||
auto xft = reinterpret_cast<XftFont*>(impl_->handle->font->native_handle());
|
auto xft = reinterpret_cast<XftFont*>(impl_->handle->font->native_handle());
|
||||||
|
|
||||||
@ -532,6 +537,9 @@ namespace paint
|
|||||||
else
|
else
|
||||||
pxbuf[i] = tab_pixels;
|
pxbuf[i] = tab_pixels;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
return nana_xft_glyph_pixels(impl_->handle->font.get(), text.data(), text.size());
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return pxbuf;
|
return pxbuf;
|
||||||
|
@ -976,7 +976,7 @@ namespace nana
|
|||||||
return unicode_character_type::katakana;
|
return unicode_character_type::katakana;
|
||||||
|
|
||||||
if (('A' <= ch && ch <= 'Z') || ('a' <= ch && ch <= 'z') || (0x00AA == ch || 0x00B5 == ch || 0x00BA == ch) || (0x00C0 <= ch && ch <= 0x00D6) ||
|
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;
|
return unicode_character_type::aletter;
|
||||||
|
|
||||||
if ('\'' == ch || 0x00AD == ch || 0x00B7 == ch || 0x05F4 == ch || 0x2019 == ch || 0x2027 == ch)
|
if ('\'' == ch || 0x00AD == ch || 0x00B7 == ch || 0x05F4 == ch || 0x2019 == ch || 0x2027 == ch)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user