add new platform_abstraction

add support of loading ttf file
This commit is contained in:
Jinhao
2017-04-26 08:04:25 +08:00
parent 4aba8e8c7f
commit 2ff8a1c729
42 changed files with 876 additions and 398 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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>

View File

@@ -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>

View File

@@ -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
View 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