Browse Source

Text: ability to compile the library without HarfBuzz support.

The text will be rendered without all the nifty features like kerning
and it will most probably fail on everything non-latin, but HarfBuzz is
currently PITA on some systems.

HarfBuzz usage can be configured using USE_HARFBUZZ CMake option.
pull/7/head
Vladimír Vondruš 13 years ago
parent
commit
b38ec8152b
  1. 6
      CMakeLists.txt
  2. 2
      modules/FindMagnum.cmake
  3. 12
      src/Text/CMakeLists.txt
  4. 16
      src/Text/Font.cpp
  5. 10
      src/Text/Font.h
  6. 46
      src/Text/TextRenderer.cpp
  7. 1
      src/magnumConfigure.h.cmake

6
CMakeLists.txt

@ -21,6 +21,9 @@ cmake_dependent_option(WITH_TEXTURETOOLS "Build TextureTools library" OFF "NOT W
cmake_dependent_option(WITH_MAGNUMINFO "Build magnum-info utility" OFF "NOT WITH_EVERYTHING" ON)
# Library features
cmake_dependent_option(USE_HARFBUZZ "Use HarfBuzz in Text library" ON "WITH_TEXT" OFF)
if(${CMAKE_SYSTEM_NAME} STREQUAL NaCl)
option(WITH_NACLAPPLICATION "Build NaClApplication library" OFF)
else()
@ -66,6 +69,9 @@ endif()
if(TARGET_DESKTOP_GLES)
set(MAGNUM_TARGET_DESKTOP_GLES 1)
endif()
if(USE_HARFBUZZ)
set(MAGNUM_USE_HARFBUZZ 1)
endif()
# Installation paths
set(MAGNUM_BINARY_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/bin)

2
modules/FindMagnum.cmake

@ -23,7 +23,7 @@
# SceneGraph - Scene graph library
# Shaders - Library with stock shaders
# Text - Text rendering library (depends on TextureTools component,
# HarfBuzz and FreeType library)
# FreeType library and possibly HarfBuzz library)
# TextureTools - TextureTools library
# GlxApplication - GLX application (depends on X11 libraries)
# XEglApplication - X/EGL application (depends on EGL and X11 libraries)

12
src/Text/CMakeLists.txt

@ -1,7 +1,10 @@
find_package(Freetype REQUIRED)
find_package(HarfBuzz REQUIRED)
include_directories(${FREETYPE_INCLUDE_DIRS})
include_directories(${FREETYPE_INCLUDE_DIRS} ${HARFBUZZ_INCLUDE_DIRS})
if(USE_HARFBUZZ)
find_package(HarfBuzz REQUIRED)
include_directories(${HARFBUZZ_INCLUDE_DIRS})
endif()
set(MagnumText_SRCS
Font.cpp
@ -17,7 +20,10 @@ set(MagnumText_HEADERS
add_library(MagnumText SHARED ${MagnumText_SRCS})
target_link_libraries(MagnumText Magnum MagnumTextureTools ${FREETYPE_LIBRARIES} ${HARFBUZZ_LIBRARIES})
target_link_libraries(MagnumText Magnum MagnumTextureTools ${FREETYPE_LIBRARIES})
if(USE_HARFBUZZ)
target_link_libraries(MagnumText ${HARFBUZZ_LIBRARIES})
endif()
install(TARGETS MagnumText DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(FILES ${MagnumText_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Text)

16
src/Text/Font.cpp

@ -18,7 +18,9 @@
#include <algorithm>
#include <ft2build.h>
#include FT_FREETYPE_H
#ifdef MAGNUM_USE_HARFBUZZ
#include <hb-ft.h>
#endif
#include <Utility/Unicode.h>
#include "Extensions.h"
@ -42,8 +44,10 @@ Font::Font(FontRenderer& renderer, const unsigned char* data, std::size_t dataSi
void Font::finishConstruction() {
CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Set_Char_Size(_ftFont, 0, _size*64, 100, 100) == 0);
#ifdef MAGNUM_USE_HARFBUZZ
/* Create Harfbuzz font */
_hbFont = hb_ft_font_create(_ftFont, nullptr);
#endif
#ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::texture_rg);
@ -126,18 +130,26 @@ void Font::prerender(const std::string& characters, const Vector2i& atlasSize) {
void Font::destroy() {
if(!_ftFont) return;
#ifdef MAGNUM_USE_HARFBUZZ
hb_font_destroy(_hbFont);
#endif
FT_Done_Face(_ftFont);
}
void Font::move() {
#ifdef MAGNUM_USE_HARFBUZZ
_hbFont = nullptr;
#endif
_ftFont = nullptr;
}
Font::~Font() { destroy(); }
Font::Font(Font&& other): glyphs(std::move(other.glyphs)), _texture(std::move(other._texture)), _ftFont(other._ftFont), _hbFont(other._hbFont), _size(other._size) {
Font::Font(Font&& other): glyphs(std::move(other.glyphs)), _texture(std::move(other._texture)), _ftFont(other._ftFont), _size(other._size)
#ifdef MAGNUM_USE_HARFBUZZ
, _hbFont(other._hbFont)
#endif
{
other.move();
}
@ -147,7 +159,9 @@ Font& Font::operator=(Font&& other) {
glyphs = std::move(other.glyphs);
_texture = std::move(other._texture);
_ftFont = other._ftFont;
#ifdef MAGNUM_USE_HARFBUZZ
_hbFont = other._hbFont;
#endif
_size = other._size;
other.move();

10
src/Text/Font.h

@ -122,8 +122,12 @@ class MAGNUM_TEXT_EXPORT Font {
/** @brief %Font texture atlas */
inline Texture2D& texture() { return _texture; }
/** @brief HarfBuzz font handle */
/** @brief Font handle */
#ifdef MAGNUM_USE_HARFBUZZ
inline hb_font_t* font() { return _hbFont; }
#else
inline FT_Face font() { return _ftFont; }
#endif
private:
void MAGNUM_TEXT_LOCAL finishConstruction();
@ -133,8 +137,10 @@ class MAGNUM_TEXT_EXPORT Font {
std::unordered_map<std::uint32_t, std::tuple<Rectangle, Rectangle>> glyphs;
Texture2D _texture;
FT_Face _ftFont;
hb_font_t* _hbFont;
GLfloat _size;
#ifdef MAGNUM_USE_HARFBUZZ
hb_font_t* _hbFont;
#endif
};
}}

46
src/Text/TextRenderer.cpp

@ -15,7 +15,13 @@
#include "TextRenderer.h"
#ifdef MAGNUM_USE_HARFBUZZ
#include <hb.h>
#else
#include <ft2build.h>
#include FT_FREETYPE_H
#include <Utility/Unicode.h>
#endif
#include "Math/Point2D.h"
#include "Math/Point3D.h"
@ -36,20 +42,33 @@ class TextLayouter {
~TextLayouter();
inline std::uint32_t glyphCount() { return _glyphCount; }
inline std::uint32_t glyphCount() {
#ifdef MAGNUM_USE_HARFBUZZ
return _glyphCount;
#else
return glyphs.size();
#endif
}
std::tuple<Rectangle, Rectangle, Vector2> renderGlyph(const Vector2& cursorPosition, const std::uint32_t i);
private:
#ifdef MAGNUM_USE_HARFBUZZ
const Font& font;
const GLfloat size;
hb_buffer_t* buffer;
hb_glyph_info_t* glyphInfo;
hb_glyph_position_t* glyphPositions;
std::uint32_t _glyphCount;
#else
Font& font;
std::vector<FT_UInt> glyphs;
#endif
const GLfloat size;
};
TextLayouter::TextLayouter(Font& font, const GLfloat size, const std::string& text): font(font), size(size) {
#ifdef MAGNUM_USE_HARFBUZZ
/* Prepare HarfBuzz buffer */
buffer = hb_buffer_create();
hb_buffer_set_direction(buffer, HB_DIRECTION_LTR);
@ -62,23 +81,46 @@ TextLayouter::TextLayouter(Font& font, const GLfloat size, const std::string& te
glyphInfo = hb_buffer_get_glyph_infos(buffer, &_glyphCount);
glyphPositions = hb_buffer_get_glyph_positions(buffer, &_glyphCount);
#else
/* Get glyph codes from characters */
glyphs.reserve(text.size()+1);
for(std::size_t i = 0; i != text.size(); ) {
std::uint32_t codepoint;
std::tie(codepoint, i) = Corrade::Utility::Unicode::nextChar(text, i);
glyphs.push_back(FT_Get_Char_Index(font.font(), codepoint));
}
#endif
}
TextLayouter::~TextLayouter() {
#ifdef MAGNUM_USE_HARFBUZZ
/* Destroy HarfBuzz buffer */
hb_buffer_destroy(buffer);
#endif
}
std::tuple<Rectangle, Rectangle, Vector2> TextLayouter::renderGlyph(const Vector2& cursorPosition, const std::uint32_t i) {
/* Position of the texture in the resulting glyph, texture coordinates */
Rectangle texturePosition, textureCoordinates;
#ifdef MAGNUM_USE_HARFBUZZ
std::tie(texturePosition, textureCoordinates) = font[glyphInfo[i].codepoint];
#else
std::tie(texturePosition, textureCoordinates) = font[glyphs[i]];
#endif
#ifdef MAGNUM_USE_HARFBUZZ
/* Glyph offset and advance to next glyph in normalized coordinates */
Vector2 offset = Vector2(glyphPositions[i].x_offset,
glyphPositions[i].y_offset)/(64*font.size());
Vector2 advance = Vector2(glyphPositions[i].x_advance,
glyphPositions[i].y_advance)/(64*font.size());
#else
/* Load glyph */
CORRADE_INTERNAL_ASSERT_OUTPUT(FT_Load_Glyph(font.font(), glyphs[i], FT_LOAD_DEFAULT) == 0);
const FT_GlyphSlot slot = font.font()->glyph;
Vector2 offset = Vector2(0, 0); /** @todo really? */
Vector2 advance = Vector2(slot->advance.x, slot->advance.y)/(64*font.size());
#endif
/* Absolute quad position, composed from cursor position, glyph offset
and texture position, denormalized to requested text size */

1
src/magnumConfigure.h.cmake

@ -2,3 +2,4 @@
#cmakedefine MAGNUM_TARGET_GLES2
#cmakedefine MAGNUM_TARGET_DESKTOP_GLES
#cmakedefine MAGNUM_TARGET_NACL
#cmakedefine MAGNUM_USE_HARFBUZZ

Loading…
Cancel
Save