From e83f9c18aa0a7c2948fac907d2d7b2b0904cb2f0 Mon Sep 17 00:00:00 2001 From: David Capello Date: Tue, 7 Mar 2017 14:52:45 -0300 Subject: [PATCH] Add support to load fonts w/Unicode filenames --- src/CMakeLists.txt | 3 +- src/ft/CMakeLists.txt | 10 +++++ src/ft/lib.cpp | 45 +++++++++++++++++++++ src/ft/lib.h | 29 +++----------- src/ft/stream.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++ src/ft/stream.h | 22 ++++++++++ src/she/CMakeLists.txt | 1 + 7 files changed, 176 insertions(+), 25 deletions(-) create mode 100644 src/ft/CMakeLists.txt create mode 100644 src/ft/lib.cpp create mode 100644 src/ft/stream.cpp create mode 100644 src/ft/stream.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ff5b21044..5b268da54 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,5 @@ # Aseprite -# Copyright (C) 2001-2016 David Capello +# Copyright (C) 2001-2017 David Capello ###################################################################### # Compiler-specific flags @@ -97,6 +97,7 @@ add_subdirectory(gfx) add_subdirectory(net) add_subdirectory(render) add_subdirectory(docio) +add_subdirectory(ft) add_subdirectory(she) add_subdirectory(ui) diff --git a/src/ft/CMakeLists.txt b/src/ft/CMakeLists.txt new file mode 100644 index 000000000..a15be60b9 --- /dev/null +++ b/src/ft/CMakeLists.txt @@ -0,0 +1,10 @@ +# Aseprite FreeType Wrapper +# Copyright (C) 2017 David Capello + +add_library(ft-lib + lib.cpp + stream.cpp) + +target_link_libraries(ft-lib + laf-base + ${FREETYPE_LIBRARIES}) diff --git a/src/ft/lib.cpp b/src/ft/lib.cpp new file mode 100644 index 000000000..1943c7425 --- /dev/null +++ b/src/ft/lib.cpp @@ -0,0 +1,45 @@ +// Aseprite FreeType Wrapper +// Copyright (c) 2016-2017 David Capello +// +// This file is released under the terms of the MIT license. +// Read LICENSE.txt for more information. + +#include "ft/lib.h" + +#include "base/log.h" +#include "ft/stream.h" + +#include + +namespace ft { + +Lib::Lib() + : m_ft(nullptr) +{ + FT_Init_FreeType(&m_ft); +} + +Lib::~Lib() +{ + if (m_ft) + FT_Done_FreeType(m_ft); +} + +FT_Face Lib::open(const std::string& filename) +{ + FT_Stream stream = ft::open_stream(m_ft, filename); + FT_Open_Args args; + memset(&args, 0, sizeof(args)); + args.flags = FT_OPEN_STREAM; + args.stream = stream; + + LOG(VERBOSE) << "FT: Loading font '" << filename << "'\n"; + + FT_Face face = nullptr; + FT_Error err = FT_Open_Face(m_ft, &args, 0, &face); + if (!err) + FT_Select_Charmap(face, FT_ENCODING_UNICODE); + return face; +} + +} // namespace ft diff --git a/src/ft/lib.h b/src/ft/lib.h index 411e803d5..792493bc1 100644 --- a/src/ft/lib.h +++ b/src/ft/lib.h @@ -1,5 +1,5 @@ // Aseprite FreeType Wrapper -// Copyright (c) 2016 David Capello +// Copyright (c) 2016-2017 David Capello // // This file is released under the terms of the MIT license. // Read LICENSE.txt for more information. @@ -17,31 +17,12 @@ namespace ft { class Lib { public: - Lib() : m_ft(nullptr) { - FT_Init_FreeType(&m_ft); - } + Lib(); + ~Lib(); - ~Lib() { - if (m_ft) - FT_Done_FreeType(m_ft); - } + operator FT_Library() { return m_ft; } - operator FT_Library() { - return m_ft; - } - - FT_Face open(const std::string& filename) { - FT_Open_Args args; - memset(&args, 0, sizeof(args)); - args.flags = FT_OPEN_PATHNAME; - args.pathname = (FT_String*)filename.c_str(); - - FT_Face face = nullptr; - FT_Error err = FT_Open_Face(m_ft, &args, 0, &face); - if (!err) - FT_Select_Charmap(face, FT_ENCODING_UNICODE); - return face; - } + FT_Face open(const std::string& filename); private: FT_Library m_ft; diff --git a/src/ft/stream.cpp b/src/ft/stream.cpp new file mode 100644 index 000000000..c58817e15 --- /dev/null +++ b/src/ft/stream.cpp @@ -0,0 +1,91 @@ +// Aseprite FreeType Wrapper +// Copyright (c) 2016-2017 David Capello +// +// This file is released under the terms of the MIT license. +// Read LICENSE.txt for more information. + +#define FT2_BUILD_LIBRARY 1 + +#include "ft/stream.h" + +#include "base/file_handle.h" + +#include FT_CONFIG_CONFIG_H +#include FT_INTERNAL_INTERNAL_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_MEMORY_H + +#define STREAM_FILE(stream) ((FILE*)stream->descriptor.pointer) + +namespace ft { + +static void ft_stream_close(FT_Stream stream) +{ + fclose(STREAM_FILE(stream)); + + stream->descriptor.pointer = nullptr; + stream->size = 0; + stream->base = nullptr; +} + +static unsigned long ft_stream_io(FT_Stream stream, + unsigned long offset, + unsigned char* buffer, + unsigned long count) +{ + if (!count && offset > stream->size) + return 1; + + FILE* file = STREAM_FILE(stream); + if (stream->pos != offset) + fseek(file, (long)offset, SEEK_SET); + + return (unsigned long)fread(buffer, 1, count, file); +} + +FT_Stream open_stream(FT_Library lib, + const std::string& utf8Filename) +{ + FT_Error error; + FT_Memory memory = lib->memory; + + FT_Stream stream = nullptr; + if (FT_NEW(stream)) + return nullptr; + + stream->memory = lib->memory; + stream->descriptor.pointer = nullptr; + stream->pathname.pointer = nullptr; + stream->base = nullptr; + stream->pos = 0; + stream->read = nullptr; + stream->close = nullptr; + + TRACE("FT: Loading font %s... ", utf8Filename.c_str()); + + FILE* file = base::open_file_raw(utf8Filename, "rb"); + if (!file) { + FT_FREE(stream); + TRACE("FAIL\n"); + return nullptr; + } + + fseek(file, 0, SEEK_END); + stream->size = (unsigned long)ftell(file); + if (!stream->size) { + fclose(file); + FT_FREE(stream); + TRACE("FAIL\n"); + return nullptr; + } + fseek(file, 0, SEEK_SET); + + stream->descriptor.pointer = file; + stream->read = ft_stream_io; + stream->close = ft_stream_close; + + TRACE("OK\n"); + return stream; +} + +} // namespace ft diff --git a/src/ft/stream.h b/src/ft/stream.h new file mode 100644 index 000000000..4fa8eee9f --- /dev/null +++ b/src/ft/stream.h @@ -0,0 +1,22 @@ +// Aseprite FreeType Wrapper +// Copyright (c) 2017 David Capello +// +// This file is released under the terms of the MIT license. +// Read LICENSE.txt for more information. + +#ifndef FT_STREAM_H_INCLUDED +#define FT_STREAM_H_INCLUDED +#pragma once + +#include "ft/freetype_headers.h" + +#include + +namespace ft { + +FT_Stream open_stream(FT_Library lib, + const std::string& utf8Filename); + +} // namespace ft + +#endif diff --git a/src/she/CMakeLists.txt b/src/she/CMakeLists.txt index 83039c7e4..c4d0c2dd8 100644 --- a/src/she/CMakeLists.txt +++ b/src/she/CMakeLists.txt @@ -240,6 +240,7 @@ endif() add_library(she ${SHE_SOURCES}) target_link_libraries(she + ft-lib gfx-lib laf-base ${FREETYPE_LIBRARIES})