add new platform_abstraction
add support of loading ttf file
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
* @contributors: dareg
|
||||
*/
|
||||
|
||||
#include <nana/detail/platform_spec_selector.hpp>
|
||||
#include "../../detail/platform_spec_selector.hpp"
|
||||
#include <nana/paint/detail/native_paint_interface.hpp>
|
||||
#include <nana/paint/pixel_buffer.hpp>
|
||||
#include <nana/gui/layout_utility.hpp>
|
||||
@@ -145,14 +145,14 @@ namespace detail
|
||||
#if defined(NANA_USE_XFT)
|
||||
std::string utf8str = to_utf8(std::wstring(text, len));
|
||||
XGlyphInfo ext;
|
||||
XftFont * fs = reinterpret_cast<XftFont*>(dw->font->handle);
|
||||
XftFont * fs = reinterpret_cast<XftFont*>(dw->font->native_handle());
|
||||
::XftTextExtentsUtf8(nana::detail::platform_spec::instance().open_display(), fs,
|
||||
reinterpret_cast<XftChar8*>(const_cast<char*>(utf8str.c_str())), utf8str.size(), &ext);
|
||||
return nana::size(ext.xOff, fs->ascent + fs->descent);
|
||||
#else
|
||||
XRectangle ink;
|
||||
XRectangle logic;
|
||||
::XmbTextExtents(reinterpret_cast<XFontSet>(dw->font->handle), text, len, &ink, &logic);
|
||||
::XmbTextExtents(reinterpret_cast<XFontSet>(dw->font->native_handle()), text, len, &ink, &logic);
|
||||
return nana::size(logic.width, logic.height);
|
||||
#endif
|
||||
#endif
|
||||
@@ -185,7 +185,7 @@ namespace detail
|
||||
#elif defined(NANA_X11)
|
||||
auto disp = ::nana::detail::platform_spec::instance().open_display();
|
||||
#if defined(NANA_USE_XFT)
|
||||
auto fs = reinterpret_cast<XftFont*>(dw->font->handle);
|
||||
auto fs = reinterpret_cast<XftFont*>(dw->font->native_handle());
|
||||
|
||||
//Fixed missing array declaration by dareg
|
||||
std::unique_ptr<FT_UInt[]> glyphs_ptr(new FT_UInt[len]);
|
||||
@@ -197,7 +197,7 @@ namespace detail
|
||||
}
|
||||
XftDrawGlyphs(dw->xftdraw, &(dw->xft_fgcolor), fs, pos.x, pos.y + fs->ascent, glyphs_ptr.get(), len);
|
||||
#else
|
||||
XFontSet fs = reinterpret_cast<XFontSet>(dw->font->handle);
|
||||
XFontSet fs = reinterpret_cast<XFontSet>(dw->font->native_handle());
|
||||
XFontSetExtents * ext = ::XExtentsOfFontSet(fs);
|
||||
XFontStruct ** fontstructs;
|
||||
char ** font_names;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Paint Graphics Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -10,7 +10,7 @@
|
||||
* @file: nana/paint/graphics.cpp
|
||||
*/
|
||||
|
||||
#include <nana/detail/platform_spec_selector.hpp>
|
||||
#include "../detail/platform_spec_selector.hpp"
|
||||
#include <nana/gui/detail/bedrock.hpp>
|
||||
#include <nana/paint/graphics.hpp>
|
||||
#include <nana/paint/detail/native_paint_interface.hpp>
|
||||
@@ -24,8 +24,19 @@
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
#include "../detail/platform_abstraction.hpp"
|
||||
|
||||
namespace nana
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
font_style::font_style(unsigned weight, bool italic, bool underline, bool strike_out) :
|
||||
weight(weight),
|
||||
italic(italic),
|
||||
underline(underline),
|
||||
strike_out(strike_out)
|
||||
{}
|
||||
}
|
||||
namespace paint
|
||||
{
|
||||
namespace detail
|
||||
@@ -56,33 +67,39 @@ namespace paint
|
||||
//class font
|
||||
struct font::impl_type
|
||||
{
|
||||
typedef nana::detail::platform_spec::font_ptr_t ptr_t;
|
||||
ptr_t font_ptr;
|
||||
std::shared_ptr<font_interface> real_font;
|
||||
};
|
||||
|
||||
font::font()
|
||||
: impl_(new impl_type)
|
||||
{
|
||||
impl_->font_ptr = nana::detail::platform_spec::instance().default_native_font();
|
||||
impl_->real_font = platform_abstraction::default_font(nullptr);
|
||||
}
|
||||
|
||||
font::font(drawable_type dw)
|
||||
: impl_(new impl_type)
|
||||
{
|
||||
impl_->font_ptr = dw->font;
|
||||
impl_->real_font = dw->font;
|
||||
}
|
||||
|
||||
font::font(const font& rhs)
|
||||
: impl_(new impl_type)
|
||||
{
|
||||
if(rhs.impl_)
|
||||
impl_->font_ptr = rhs.impl_->font_ptr;
|
||||
impl_->real_font = rhs.impl_->real_font;
|
||||
}
|
||||
|
||||
font::font(const std::string& name, unsigned size, bool bold, bool italic, bool underline, bool strike_out)
|
||||
: impl_(new impl_type)
|
||||
font::font(const std::string& font_family, double size_pt, const font_style& fs):
|
||||
impl_(new impl_type)
|
||||
{
|
||||
make(name, size, bold, italic, underline, strike_out);
|
||||
impl_->real_font = platform_abstraction::make_font(font_family, size_pt, fs);
|
||||
}
|
||||
|
||||
|
||||
font::font(double size_pt, const path_type& truetype, const font_style& fs) :
|
||||
impl_(new impl_type)
|
||||
{
|
||||
impl_->real_font = platform_abstraction::make_font_from_ttf(truetype, size_pt, fs);
|
||||
}
|
||||
|
||||
font::~font()
|
||||
@@ -92,23 +109,7 @@ namespace paint
|
||||
|
||||
bool font::empty() const
|
||||
{
|
||||
return ((nullptr == impl_) || (nullptr == impl_->font_ptr));
|
||||
}
|
||||
|
||||
void font::make(const std::string& name, unsigned size, bool bold, bool italic, bool underline, bool strike_out)
|
||||
{
|
||||
size = nana::detail::platform_spec::instance().font_size_to_height(size);
|
||||
make_raw(name, size, bold ? 700 : 400, italic, underline, strike_out);
|
||||
}
|
||||
|
||||
void font::make_raw(const std::string& name, unsigned height, unsigned weight, bool italic, bool underline, bool strike_out)
|
||||
{
|
||||
if(impl_)
|
||||
{
|
||||
auto t = nana::detail::platform_spec::instance().make_native_font(name.c_str(), height, weight, italic, underline, strike_out);
|
||||
if(t)
|
||||
impl_->font_ptr = t;
|
||||
}
|
||||
return ((nullptr == impl_) || (nullptr == impl_->real_font));
|
||||
}
|
||||
|
||||
void font::set_default() const
|
||||
@@ -116,74 +117,69 @@ namespace paint
|
||||
if(empty())
|
||||
return;
|
||||
|
||||
nana::detail::platform_spec::instance().default_native_font(impl_->font_ptr);
|
||||
platform_abstraction::default_font(impl_->real_font);
|
||||
}
|
||||
|
||||
std::string font::name() const
|
||||
{
|
||||
if(empty()) return std::string();
|
||||
|
||||
return to_utf8(impl_->font_ptr->name);
|
||||
return impl_->real_font->family();
|
||||
}
|
||||
|
||||
unsigned font::size() const
|
||||
double font::size() const
|
||||
{
|
||||
if(empty()) return 0;
|
||||
return nana::detail::platform_spec::instance().font_height_to_size(impl_->font_ptr->height);
|
||||
|
||||
return impl_->real_font->size();
|
||||
}
|
||||
|
||||
bool font::bold() const
|
||||
{
|
||||
if(empty()) return false;
|
||||
return (impl_->font_ptr->weight >= 700);
|
||||
}
|
||||
|
||||
unsigned font::height() const
|
||||
{
|
||||
if(empty()) return 0;
|
||||
return (impl_->font_ptr->height);
|
||||
return (impl_->real_font->style().weight >= 700);
|
||||
}
|
||||
|
||||
unsigned font::weight() const
|
||||
{
|
||||
if(empty()) return 0;
|
||||
return (impl_->font_ptr->weight);
|
||||
return impl_->real_font->style().weight;
|
||||
}
|
||||
|
||||
bool font::italic() const
|
||||
{
|
||||
if(empty()) return false;
|
||||
return (impl_->font_ptr->italic);
|
||||
return impl_->real_font->style().italic;
|
||||
}
|
||||
|
||||
bool font::underline() const
|
||||
{
|
||||
if(empty()) return false;
|
||||
return (impl_->font_ptr->underline);
|
||||
return impl_->real_font->style().underline;
|
||||
}
|
||||
|
||||
bool font::strikeout() const
|
||||
{
|
||||
if(empty()) return false;
|
||||
return (impl_->font_ptr->strikeout);
|
||||
return impl_->real_font->style().strike_out;
|
||||
}
|
||||
|
||||
native_font_type font::handle() const
|
||||
{
|
||||
if(empty()) return nullptr;
|
||||
return reinterpret_cast<native_font_type>(impl_->font_ptr->handle);
|
||||
return impl_->real_font->native_handle();
|
||||
}
|
||||
|
||||
void font::release()
|
||||
{
|
||||
if(impl_)
|
||||
impl_->font_ptr.reset();
|
||||
impl_->real_font.reset();
|
||||
}
|
||||
|
||||
font & font::operator=(const font& rhs)
|
||||
{
|
||||
if(impl_ && rhs.impl_ && (this != &rhs))
|
||||
impl_->font_ptr = rhs.impl_->font_ptr;
|
||||
impl_->real_font = rhs.impl_->real_font;
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -191,7 +187,7 @@ namespace paint
|
||||
bool font::operator==(const font& rhs) const
|
||||
{
|
||||
if(empty() == rhs.empty())
|
||||
return (empty() || (impl_->font_ptr->handle == rhs.impl_->font_ptr->handle));
|
||||
return (empty() || (impl_->real_font == rhs.impl_->real_font));
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -199,7 +195,7 @@ namespace paint
|
||||
bool font::operator!=(const font& rhs) const
|
||||
{
|
||||
if(empty() == rhs.empty())
|
||||
return ((empty() == false) && (impl_->font_ptr->handle != rhs.impl_->font_ptr->handle));
|
||||
return ((empty() == false) && (impl_->real_font != rhs.impl_->real_font));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -305,7 +301,7 @@ namespace paint
|
||||
dw->string.tab_length = reuse->string.tab_length;
|
||||
}
|
||||
else
|
||||
dw->font = impl_->font_shadow.impl_->font_ptr;
|
||||
dw->font = impl_->font_shadow.impl_->real_font;
|
||||
|
||||
#if defined(NANA_WINDOWS)
|
||||
HDC hdc = ::GetDC(0);
|
||||
@@ -325,7 +321,7 @@ namespace paint
|
||||
if(bmp)
|
||||
{
|
||||
::DeleteObject((HBITMAP)::SelectObject(cdc, bmp));
|
||||
::DeleteObject(::SelectObject(cdc, dw->font->handle));
|
||||
::DeleteObject(::SelectObject(cdc, dw->font->native_handle()));
|
||||
|
||||
dw->context = cdc;
|
||||
dw->pixmap = bmp;
|
||||
@@ -388,9 +384,9 @@ namespace paint
|
||||
impl_->font_shadow = f;
|
||||
if(impl_->handle && (false == f.empty()))
|
||||
{
|
||||
impl_->handle->font = f.impl_->font_ptr;
|
||||
impl_->handle->font = f.impl_->real_font;
|
||||
#if defined(NANA_WINDOWS)
|
||||
::SelectObject(impl_->handle->context, reinterpret_cast<HFONT>(f.impl_->font_ptr->handle));
|
||||
::SelectObject(impl_->handle->context, reinterpret_cast<HFONT>(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;
|
||||
@@ -489,8 +485,8 @@ namespace paint
|
||||
delete [] dx;
|
||||
#elif defined(NANA_X11) && defined(NANA_USE_XFT)
|
||||
|
||||
Display * disp = nana::detail::platform_spec::instance().open_display();
|
||||
XftFont * xft = impl_->handle->font->handle;
|
||||
auto disp = nana::detail::platform_spec::instance().open_display();
|
||||
auto xft = reinterpret_cast<XftFont*>(impl_->handle->font->native_handle());
|
||||
|
||||
XGlyphInfo extents;
|
||||
for(std::size_t i = 0; i < len; ++i)
|
||||
@@ -547,12 +543,12 @@ namespace paint
|
||||
if(impl_->handle->font)
|
||||
{
|
||||
#if defined(NANA_USE_XFT)
|
||||
XftFont * fs = reinterpret_cast<XftFont*>(impl_->handle->font->handle);
|
||||
auto fs = reinterpret_cast<XftFont*>(impl_->handle->font->native_handle());
|
||||
ascent = fs->ascent;
|
||||
descent = fs->descent;
|
||||
internal_leading = 0;
|
||||
#else
|
||||
XFontSet fs = reinterpret_cast<XFontSet>(impl_->handle->font->handle);
|
||||
auto fs = reinterpret_cast<XFontSet>(impl_->handle->font->native_handle());
|
||||
XFontSetExtents * ext = ::XExtentsOfFontSet(fs);
|
||||
XFontStruct ** fontstructs;
|
||||
char ** font_names;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
#include <nana/push_ignore_diagnostic>
|
||||
#include <nana/detail/platform_spec_selector.hpp>
|
||||
#include "../detail/platform_spec_selector.hpp"
|
||||
#include <nana/paint/image.hpp>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* @note: The format of Xorg 16bits depth is 565
|
||||
*/
|
||||
|
||||
#include <nana/detail/platform_spec_selector.hpp>
|
||||
#include "../detail/platform_spec_selector.hpp"
|
||||
#include <nana/paint/pixel_buffer.hpp>
|
||||
#include <nana/gui/layout_utility.hpp>
|
||||
#include <nana/paint/detail/native_paint_interface.hpp>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
#include <nana/detail/platform_spec_selector.hpp>
|
||||
#include "../detail/platform_spec_selector.hpp"
|
||||
#include <nana/paint/text_renderer.hpp>
|
||||
#include <nana/unicode_bidi.hpp>
|
||||
#include <nana/paint/detail/native_paint_interface.hpp>
|
||||
|
||||
161
source/paint/truetype.hpp
Normal file
161
source/paint/truetype.hpp
Normal file
@@ -0,0 +1,161 @@
|
||||
#ifndef TTF_HEADER_INCLUDED
|
||||
#define TTF_HEADER_INCLUDED
|
||||
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <nana/charset.hpp>
|
||||
#include <nana/filesystem/filesystem.hpp>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
namespace spec
|
||||
{
|
||||
class truetype
|
||||
{
|
||||
struct tt_offset_table
|
||||
{
|
||||
std::uint16_t major_version;
|
||||
std::uint16_t minor_version;
|
||||
std::uint16_t num_of_tables;
|
||||
std::uint16_t search_range;
|
||||
std::uint16_t entry_selector;
|
||||
std::uint16_t range_shift;
|
||||
};
|
||||
|
||||
struct tt_table_directory
|
||||
{
|
||||
char name[4]; //table name
|
||||
std::uint32_t checksum; //Check sum
|
||||
std::uint32_t offset; //Offset from beginning of file
|
||||
std::uint32_t length; //length of the table in bytes
|
||||
};
|
||||
|
||||
struct tt_name_table_header
|
||||
{
|
||||
std::uint16_t format_selector; //format selector. Always 0
|
||||
std::uint16_t name_records_count; //Name Records count
|
||||
std::uint16_t storage_offset; //Offset for strings storage, from start of the table
|
||||
};
|
||||
|
||||
struct tt_name_record
|
||||
{
|
||||
std::uint16_t platform_id;
|
||||
std::uint16_t encoding_id;
|
||||
std::uint16_t language_id;
|
||||
std::uint16_t name_id;
|
||||
std::uint16_t string_length;
|
||||
std::uint16_t string_offset; //from start of storage area
|
||||
};
|
||||
public:
|
||||
using path_type = ::std::experimental::filesystem::path;
|
||||
|
||||
truetype(const path_type& filename)
|
||||
{
|
||||
std::ifstream ifs{ filename, std::ios::binary };
|
||||
if (!ifs.is_open())
|
||||
return;
|
||||
|
||||
tt_offset_table offset_table;
|
||||
if (ifs.read(reinterpret_cast<char*>(&offset_table), sizeof offset_table).gcount() != sizeof offset_table)
|
||||
return;
|
||||
|
||||
const std::size_t num_of_tables = _m_swap(offset_table.num_of_tables);
|
||||
for (std::size_t i = 0; i < num_of_tables; ++i)
|
||||
{
|
||||
tt_table_directory table_directory;
|
||||
if (ifs.read(reinterpret_cast<char*>(&table_directory), sizeof table_directory).gcount() != sizeof table_directory)
|
||||
return;
|
||||
|
||||
if (reinterpret_cast<const std::uint32_t&>("name") == reinterpret_cast<std::uint32_t&>(table_directory.name))
|
||||
{
|
||||
//const std::size_t length = _m_swap(table_directory.length);
|
||||
const std::size_t directory_offset = _m_swap(table_directory.offset);
|
||||
|
||||
ifs.seekg(directory_offset, std::ios::beg);
|
||||
|
||||
tt_name_table_header name_table;
|
||||
if (ifs.read(reinterpret_cast<char*>(&name_table), sizeof name_table).gcount() != sizeof name_table)
|
||||
return;
|
||||
|
||||
const std::size_t name_records_count = _m_swap(name_table.name_records_count);
|
||||
const std::size_t storage_offset = _m_swap(name_table.storage_offset);
|
||||
|
||||
for (std::size_t u = 0; u < name_records_count; ++u)
|
||||
{
|
||||
tt_name_record record;
|
||||
if (ifs.read(reinterpret_cast<char*>(&record), sizeof record).gcount() != sizeof record)
|
||||
return;
|
||||
|
||||
if ((0 == record.string_length) || (0x100 != record.name_id))
|
||||
continue;
|
||||
|
||||
std::size_t string_length = _m_swap(record.string_length);
|
||||
|
||||
auto const filepos = ifs.tellg();
|
||||
ifs.seekg(directory_offset + _m_swap(record.string_offset) + storage_offset, std::ios::beg);
|
||||
|
||||
std::string text;
|
||||
|
||||
//Check if it is unicode
|
||||
if ((0 == record.platform_id) || (record.platform_id == 0x300 && record.encoding_id == 0x100))
|
||||
{
|
||||
if (0 == (string_length & 1)) //the string_length must be
|
||||
{
|
||||
//This is unicode
|
||||
text.resize(string_length);
|
||||
ifs.read(&text.front(), string_length);
|
||||
|
||||
for (auto i = 0; i < string_length; i += 2)
|
||||
{
|
||||
std::swap(text[i], text[i + 1]);
|
||||
}
|
||||
text = nana::charset(text, nana::unicode::utf16).to_bytes(nana::unicode::utf8);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
text.resize(string_length);
|
||||
ifs.read(&text.front(), string_length);
|
||||
}
|
||||
|
||||
if (!text.empty())
|
||||
{
|
||||
switch (record.name_id)
|
||||
{
|
||||
case 0x100:
|
||||
font_family_.swap(text);
|
||||
break;
|
||||
case 0x400:
|
||||
text.clear();
|
||||
}
|
||||
}
|
||||
ifs.seekg(filepos, std::ios::beg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const std::string& font_family() const
|
||||
{
|
||||
return font_family_;
|
||||
}
|
||||
private:
|
||||
static std::uint16_t _m_swap(std::uint16_t val)
|
||||
{
|
||||
return (val << 8) | (val >> 8);
|
||||
}
|
||||
|
||||
static std::uint32_t _m_swap(std::uint32_t val)
|
||||
{
|
||||
return (static_cast<std::uint32_t>(_m_swap(std::uint16_t(val & 0xFFFF))) << 16) | _m_swap(std::uint16_t(val >> 16));
|
||||
}
|
||||
private:
|
||||
std::string font_family_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user