-
-
Save roxlu/da3251cb2045823922fa to your computer and use it in GitHub Desktop.
Test code for caret offset calculation using Harfbuzz, Icu and Freetype.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <ft2build.h> | |
#include FT_FREETYPE_H | |
#include <harfbuzz/hb.h> | |
#include <harfbuzz/hb-ft.h> | |
#include <unicode/uchriter.h> | |
#include <unicode/schriter.h> | |
#include <unicode/ustring.h> | |
#include <unicode/ustdio.h> | |
#include <unicode/brkiter.h> | |
#include <string> | |
/* ------------------------------------------------------------- */ | |
struct Font { | |
FT_Face face; | |
hb_font_t* hb_font; | |
hb_buffer_t* hb_buffer; | |
hb_glyph_info_t* glyph_info; | |
hb_glyph_position_t* glyph_pos; | |
unsigned int glyph_count; | |
}; | |
FT_Library library = NULL; | |
/* ------------------------------------------------------------- */ | |
int main() { | |
/* Harfbuzz + Freetype vars. */ | |
std::string test_string = "Af̀fiZ"; | |
std::string fontfile; | |
int r = 0; | |
unsigned int i = 0; | |
FT_Error err; | |
Font font; | |
/* ICU */ | |
UBreakIterator* bi = NULL; | |
int32_t p = 0; | |
UErrorCode icu_err = U_ZERO_ERROR; | |
UnicodeString ts(test_string.c_str()); | |
const UChar* ts_ptr = ts.getTerminatedBuffer(); | |
printf("\n\n"); | |
printf("Testing caret offset calculation with Freetype + Harfbuzz.\n"); | |
printf("\n\n"); | |
/* Initialize + load. */ | |
font.face = NULL; | |
font.hb_font = NULL; | |
font.hb_buffer = NULL; | |
font.glyph_info = NULL; | |
font.glyph_pos = NULL; | |
font.glyph_count = 0; | |
err = FT_Init_FreeType(&library); | |
if (FT_Err_Ok != err) { | |
printf("Failed to initialize Freetype."); | |
return -1; | |
} | |
fontfile = "data/Clarendon.ttf"; | |
err = FT_New_Face(library, fontfile.c_str(), 0, &font.face); | |
if (FT_Err_Ok != err) { | |
printf("Failed to create a new ft face."); | |
r = -1; | |
goto error; | |
} | |
font.hb_font = hb_ft_font_create(font.face, 0); | |
if (NULL == font.hb_font) { | |
printf("Failed to create harfbuzz font context."); | |
r = -2; | |
goto error; | |
} | |
font.hb_buffer = hb_buffer_create(); | |
if (NULL == font.hb_buffer) { | |
printf("Failed to create the harfbuzz buffer."); | |
r = -3; | |
goto error; | |
} | |
/* Write some content. */ | |
hb_buffer_set_direction(font.hb_buffer, HB_DIRECTION_LTR); | |
hb_buffer_set_script(font.hb_buffer, HB_SCRIPT_UNKNOWN); | |
hb_buffer_add_utf8(font.hb_buffer, test_string.c_str(), test_string.size(), 0, test_string.size()); | |
hb_shape(font.hb_font, font.hb_buffer, NULL, 0); | |
font.glyph_count = hb_buffer_get_length(font.hb_buffer); | |
font.glyph_info = hb_buffer_get_glyph_infos(font.hb_buffer, NULL); | |
font.glyph_pos = hb_buffer_get_glyph_positions(font.hb_buffer, NULL); | |
/* Iterate over HB glyphs */ | |
for (i = 0; i < font.glyph_count; ++i) { | |
printf("Glyph: %u, cluster: %d\n", i, font.glyph_info[i].cluster); | |
} | |
/* Interate over graphmemes. */ | |
bi = ubrk_open(UBRK_CHARACTER, 0, ts_ptr, u_strlen(ts_ptr), &icu_err); | |
if (U_FAILURE(icu_err)) { | |
printf("Error: failed to create a break iterator."); | |
r = -4; | |
goto error; | |
} | |
p = ubrk_first(bi); | |
printf("\n"); | |
while (p != UBRK_DONE) { | |
printf("Graphmeme offset: %u\n", p); | |
p = ubrk_next(bi); | |
} | |
ubrk_close(bi); | |
printf("\n\n"); | |
error: | |
if (NULL != font.hb_buffer) { | |
hb_buffer_destroy(font.hb_buffer); | |
font.hb_buffer = NULL; | |
} | |
if (NULL != font.hb_font) { | |
hb_font_destroy(font.hb_font); | |
font.hb_font = NULL; | |
} | |
if (NULL != font.face) { | |
err = FT_Done_Face(font.face); | |
if (FT_Err_Ok != err) { | |
printf("Failed FT_Done_Face."); | |
} | |
font.face = NULL; | |
} | |
return r; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment