/* * Function : libaroma_font * Return Value: byte * Descriptions: load new font */ byte libaroma_font( byte fontid, LIBAROMA_STREAMP stream) { if (!stream) { ALOGW("libaroma_font stream not found"); return 0; } if (fontid >= _LIBAROMA_FONT_MAX_FACE) { ALOGW("libaroma_font fontid(%i)>=%i", fontid, _LIBAROMA_FONT_MAX_FACE); return 0; } /* thread safe */ _libaroma_font_lock(1); /* load face */ FT_Face tmp_face; if (FT_New_Memory_Face(_libaroma_font_instance, stream->data, stream->size, 0, &tmp_face) == 0) { /* set default face size */ int def_size = libaroma_font_size_px(2); if (FT_Set_Pixel_Sizes(tmp_face, 0, def_size) == 0) { /* save it */ libaroma_font_free(fontid); _libaroma_font_faces[fontid].size = def_size; _libaroma_font_faces[fontid].id = fontid; _libaroma_font_faces[fontid].face = tmp_face; _libaroma_font_faces[fontid].stream = stream; _libaroma_font_faces[fontid].cache = libaroma_iarray(libaroma_font_freecache_cb); /* force ucs2 */ libaroma_font_set_ucs2(_libaroma_font_faces[fontid].face); /* init harfbuzz */ _libaroma_font_hb_init(fontid); /* unlock */ _libaroma_font_lock(0); ALOGV("font loaded %ibytes (%s)", stream->size, stream->uri); return 1; } else { ALOGW("libaroma_font libaroma_font_set_size error"); FT_Done_Face(tmp_face); } } else { ALOGW("libaroma_font FT_New_Memory_Face Error"); libaroma_stream_close(stream); } _libaroma_font_lock(0); return 0; } /* End of libaroma_font */
/* * Function : libaroma_font_glyph * Return Value: LIBAROMA_GLYPH * Descriptions: get font glyph */ LIBAROMA_GLYPH libaroma_font_glyph( int c, byte fontid, byte size ) { /* UTF 8 Flag */ if (c == 0xfeff) { return NULL; } /* 0 - 9 */ if (fontid >= _LIBAROMA_FONT_MAX_FACE) { ALOGW("libaroma_font_glyph fontid(%i)>=%i", fontid, _LIBAROMA_FONT_MAX_FACE); return NULL; } /* cleanup last variables */ // _libaroma_font_faces[fontid].last_cache = NULL; // _libaroma_font_faces[fontid].last_slotid = 0; if (size == 0) { size = _libaroma_font_faces[fontid].size; } /* find in cache */ int cache_id = ((c & 0xfffff) | (size << 20)); _libaroma_font_lock(1); _LIBAROMA_FONT_SLOT_CACHEP tmp_glyph = (_LIBAROMA_FONT_SLOT_CACHEP) libaroma_iarray_get(_libaroma_font_faces[fontid].cache, cache_id); if (tmp_glyph != NULL) { /* cache is available */ // _libaroma_font_faces[fontid].last_cache = tmp_glyph; // _libaroma_font_faces[fontid].last_slotid = cache_id; _libaroma_font_lock(0); return (LIBAROMA_GLYPH) tmp_glyph; } /* get freetype face */ FT_Face face = _libaroma_font_faces[fontid].face; if (face == NULL) { ALOGW("libaroma_font_glyph fontid(%i) uninitialized", fontid); _libaroma_font_lock(0); return NULL; } /* set requested font size */ libaroma_font_set_size(fontid, libaroma_font_size_px(size), 0); /* load glyph from freetype face */ if (FT_Load_Glyph(face, c, _LIBAROMA_FONT_LOAD_GLYPH_FLAG) == 0) { _LIBAROMA_FONT_SLOT_CACHE slot={0}; FT_Get_Glyph(face->glyph, &slot.glyph); memcpy(&slot.metrics, &face->glyph->metrics, sizeof(FT_Glyph_Metrics)); slot.codepoint = c; slot.size = _libaroma_font_faces[fontid].size; /* ready to return */ libaroma_iarray_set( _libaroma_font_faces[fontid].cache, cache_id, (voidp) &slot, sizeof(_LIBAROMA_FONT_SLOT_CACHE), 1 ); // _libaroma_font_faces[fontid].last_cache tmp_glyph = libaroma_iarray_get( _libaroma_font_faces[fontid].cache, cache_id ); _libaroma_font_lock(0); // _libaroma_font_faces[fontid].last_slotid = cache_id; return (LIBAROMA_GLYPH) tmp_glyph; // _libaroma_font_faces[fontid].last_cache; } _libaroma_font_lock(0); return NULL; } /* End of libaroma_font_glyph */
/* * Function : libaroma_text_shaper * Return Value: _LIBAROMA_TEXTSHAPEDP * Descriptions: text shaper with harfbuzz-ng */ _LIBAROMA_TEXTSHAPEDP libaroma_text_shaper( _LIBAROMA_TEXTPRESHAPEDP span, _LIBAROMA_TEXTCHUNKP chunk) { /* get freetype font face */ FT_Face font = libaroma_font_get(span->fontid, 1); if (font == NULL) { return NULL; } _libaroma_text_lock(1); /* set size */ byte fontsize = _LIBAROMA_TEXTCHUNK_GETFONTSIZE(chunk->curr_state.font); libaroma_font_set_size(span->fontid, libaroma_font_size_px(fontsize), 0); /* init harfbuzz font */ _LIBAROMA_FONT_FACEP afont = libaroma_font_get_face(span->fontid); /* calculating */ dword i = 0; int sizer_x = 0; int sizer_y = 0; int max_x = INT_MIN; int min_x = INT_MAX; int max_y = INT_MIN; int min_y = INT_MAX; int x = 0; int y = 0; int u = 0; #ifdef LIBAROMA_CONFIG_TEXT_NOHARFBUZZ _LIBAROMA_TEXTSHAPEDP shaped = (_LIBAROMA_TEXTSHAPEDP) malloc(sizeof(_LIBAROMA_TEXTSHAPED)); shaped->coln = span->len; shaped->cols = (_LIBAROMA_TEXTCOLUMNP) malloc(sizeof(_LIBAROMA_TEXTCOLUMN) * shaped->coln); shaped->rtl = chunk->rtl; shaped->font = _LIBAROMA_TEXT_FONT(span->fontid, fontsize); shaped->next = NULL; FT_Bool use_kerning = FT_HAS_KERNING(afont->face); int previous=0; dword ii; for (ii=0;ii<shaped->coln;ii++) { if (shaped->rtl){ i=(shaped->coln-1)-ii; } else{ i=ii; } u=FT_Get_Char_Index(afont->face, span->text[i]); _LIBAROMA_FONT_SLOT_CACHEP glp=(_LIBAROMA_FONT_SLOT_CACHEP) libaroma_font_glyph(u,span->fontid,fontsize); int xa = glp->metrics.horiAdvance>>6; int xo = 0; if (use_kerning&&previous&&u){ FT_Vector delta; if (shaped->rtl){ FT_Get_Kerning(afont->face, u, previous,FT_KERNING_DEFAULT, &delta ); } else{ FT_Get_Kerning(afont->face, previous, u,FT_KERNING_DEFAULT, &delta ); } xo = delta.x>>6; } int gx = sizer_x + xo; if (min_x > gx) { min_x = gx; } if (max_x < gx) { max_x = gx; } if (min_y > sizer_y) { min_y = sizer_y; } if (max_y < sizer_y) { max_y = sizer_y; } shaped->cols[i].id = u; shaped->cols[i].x = x + xo; shaped->cols[i].y = y; shaped->cols[i].w = xa; xa+=xo; sizer_x += xa; x += xa; previous = u; }