[uniscribe] Cleanup backend
This commit is contained in:
parent
f1f848e2e4
commit
bf3eef540f
2
TODO
2
TODO
|
@ -29,6 +29,8 @@ API issues to fix before 1.0:
|
||||||
API to add (maybe after 1.0):
|
API to add (maybe after 1.0):
|
||||||
============================
|
============================
|
||||||
|
|
||||||
|
- Add Uniscribe face / font get API
|
||||||
|
|
||||||
- BCP 47 language handling / API (language_matches?)
|
- BCP 47 language handling / API (language_matches?)
|
||||||
|
|
||||||
- Add hb_face_get_glyph_count()?
|
- Add hb_face_get_glyph_count()?
|
||||||
|
|
|
@ -91,6 +91,108 @@ populate_log_font (LOGFONTW *lf,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct hb_uniscribe_face_data_t{
|
||||||
|
HANDLE fh;
|
||||||
|
} _hb_uniscribe_face_data_nil = {0};
|
||||||
|
|
||||||
|
static hb_user_data_key_t uniscribe_face_data_key;
|
||||||
|
|
||||||
|
static void
|
||||||
|
_hb_uniscribe_face_data_destroy (hb_uniscribe_face_data_t *data)
|
||||||
|
{
|
||||||
|
if (data->fh)
|
||||||
|
RemoveFontMemResourceEx (data->fh);
|
||||||
|
free (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static hb_uniscribe_face_data_t *
|
||||||
|
_hb_uniscribe_face_get_data (hb_face_t *face)
|
||||||
|
{
|
||||||
|
hb_uniscribe_face_data_t *data = (hb_uniscribe_face_data_t *) hb_face_get_user_data (face, &uniscribe_face_data_key);
|
||||||
|
if (likely (data)) return data;
|
||||||
|
|
||||||
|
data = (hb_uniscribe_face_data_t *) calloc (1, sizeof (hb_uniscribe_face_data_t));
|
||||||
|
if (unlikely (!data))
|
||||||
|
return &_hb_uniscribe_face_data_nil;
|
||||||
|
|
||||||
|
hb_blob_t *blob = hb_face_reference_blob (face);
|
||||||
|
unsigned int blob_length;
|
||||||
|
const char *blob_data = hb_blob_get_data (blob, &blob_length);
|
||||||
|
if (unlikely (!blob_length))
|
||||||
|
DEBUG_MSG (UNISCRIBE, face, "Face has empty blob");
|
||||||
|
|
||||||
|
DWORD num_fonts_installed;
|
||||||
|
data->fh = AddFontMemResourceEx ((void *) blob_data, blob_length, 0, &num_fonts_installed);
|
||||||
|
hb_blob_destroy (blob);
|
||||||
|
if (unlikely (!data->fh))
|
||||||
|
DEBUG_MSG (UNISCRIBE, face, "Face AddFontMemResourceEx() failed");
|
||||||
|
|
||||||
|
if (unlikely (!hb_face_set_user_data (face, &uniscribe_face_data_key, data,
|
||||||
|
(hb_destroy_func_t) _hb_uniscribe_face_data_destroy)))
|
||||||
|
{
|
||||||
|
_hb_uniscribe_face_data_destroy (data);
|
||||||
|
return &_hb_uniscribe_face_data_nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct hb_uniscribe_font_data_t {
|
||||||
|
HDC hdc;
|
||||||
|
HFONT hfont;
|
||||||
|
SCRIPT_CACHE script_cache;
|
||||||
|
} _hb_uniscribe_font_data_nil = {NULL, NULL, NULL};
|
||||||
|
|
||||||
|
static hb_user_data_key_t uniscribe_font_data_key;
|
||||||
|
|
||||||
|
static void
|
||||||
|
_hb_uniscribe_font_data_destroy (hb_uniscribe_font_data_t *data)
|
||||||
|
{
|
||||||
|
if (data->hdc)
|
||||||
|
ReleaseDC (NULL, data->hdc);
|
||||||
|
if (data->hfont)
|
||||||
|
DeleteObject (data->hfont);
|
||||||
|
if (data->script_cache)
|
||||||
|
ScriptFreeCache (&data->script_cache);
|
||||||
|
free (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static hb_uniscribe_font_data_t *
|
||||||
|
_hb_uniscribe_font_get_data (hb_font_t *font)
|
||||||
|
{
|
||||||
|
hb_uniscribe_font_data_t *data = (hb_uniscribe_font_data_t *) hb_font_get_user_data (font, &uniscribe_font_data_key);
|
||||||
|
if (likely (data)) return data;
|
||||||
|
|
||||||
|
data = (hb_uniscribe_font_data_t *) calloc (1, sizeof (hb_uniscribe_font_data_t));
|
||||||
|
if (unlikely (!data))
|
||||||
|
return &_hb_uniscribe_font_data_nil;
|
||||||
|
|
||||||
|
data->hdc = GetDC (NULL);
|
||||||
|
|
||||||
|
LOGFONTW log_font;
|
||||||
|
if (unlikely (!populate_log_font (&log_font, data->hdc, font)))
|
||||||
|
DEBUG_MSG (UNISCRIBE, font, "Font populate_log_font() failed");
|
||||||
|
else {
|
||||||
|
data->hfont = CreateFontIndirectW (&log_font);
|
||||||
|
if (unlikely (!data->hfont))
|
||||||
|
DEBUG_MSG (UNISCRIBE, font, "Font CreateFontIndirectW() failed");
|
||||||
|
if (!SelectObject (data->hdc, data->hfont))
|
||||||
|
DEBUG_MSG (UNISCRIBE, font, "Font SelectObject() failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely (!hb_font_set_user_data (font, &uniscribe_font_data_key, data,
|
||||||
|
(hb_destroy_func_t) _hb_uniscribe_font_data_destroy)))
|
||||||
|
{
|
||||||
|
_hb_uniscribe_font_data_destroy (data);
|
||||||
|
return &_hb_uniscribe_font_data_nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
hb_bool_t
|
hb_bool_t
|
||||||
hb_uniscribe_shape (hb_font_t *font,
|
hb_uniscribe_shape (hb_font_t *font,
|
||||||
hb_buffer_t *buffer,
|
hb_buffer_t *buffer,
|
||||||
|
@ -100,11 +202,25 @@ hb_uniscribe_shape (hb_font_t *font,
|
||||||
{
|
{
|
||||||
buffer->guess_properties ();
|
buffer->guess_properties ();
|
||||||
|
|
||||||
HRESULT hr;
|
#define FAIL(...) \
|
||||||
|
HB_STMT_START { \
|
||||||
|
DEBUG_MSG (UNISCRIBE, NULL, __VA_ARGS__); \
|
||||||
|
return FALSE; \
|
||||||
|
} HB_STMT_END;
|
||||||
|
|
||||||
|
hb_uniscribe_face_data_t *face_data = _hb_uniscribe_face_get_data (font->face);
|
||||||
|
if (unlikely (!face_data))
|
||||||
|
FAIL ("Couldn't get face data");
|
||||||
|
|
||||||
|
hb_uniscribe_font_data_t *font_data = _hb_uniscribe_font_get_data (font);
|
||||||
|
if (unlikely (!font_data))
|
||||||
|
FAIL ("Couldn't get font font");
|
||||||
|
|
||||||
if (unlikely (!buffer->len))
|
if (unlikely (!buffer->len))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
|
|
||||||
unsigned int scratch_size;
|
unsigned int scratch_size;
|
||||||
|
@ -152,13 +268,6 @@ retry:
|
||||||
ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
|
ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
|
||||||
|
|
||||||
|
|
||||||
#define FAIL(...) \
|
|
||||||
HB_STMT_START { \
|
|
||||||
DEBUG_MSG (UNISCRIBE, NULL, __VA_ARGS__); \
|
|
||||||
return FALSE; \
|
|
||||||
} HB_STMT_END;
|
|
||||||
|
|
||||||
|
|
||||||
#define MAX_ITEMS 10
|
#define MAX_ITEMS 10
|
||||||
|
|
||||||
SCRIPT_ITEM items[MAX_ITEMS + 1];
|
SCRIPT_ITEM items[MAX_ITEMS + 1];
|
||||||
|
@ -189,30 +298,6 @@ retry:
|
||||||
/* XXX setup ranges */
|
/* XXX setup ranges */
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_blob_t *blob = hb_face_reference_blob (font->face);
|
|
||||||
unsigned int blob_length;
|
|
||||||
const char *blob_data = hb_blob_get_data (blob, &blob_length);
|
|
||||||
if (unlikely (!blob_length))
|
|
||||||
FAIL ("Empty font blob");
|
|
||||||
|
|
||||||
DWORD num_fonts_installed;
|
|
||||||
HANDLE fh = AddFontMemResourceEx ((void *) blob_data, blob_length, 0, &num_fonts_installed);
|
|
||||||
hb_blob_destroy (blob);
|
|
||||||
if (unlikely (!fh))
|
|
||||||
FAIL ("AddFontMemResourceEx() failed");
|
|
||||||
|
|
||||||
/* FREE stuff, specially when taking fallback... */
|
|
||||||
|
|
||||||
HDC hdc = GetDC (NULL); /* XXX The DC should be cached on the face I guess? */
|
|
||||||
|
|
||||||
LOGFONTW log_font;
|
|
||||||
if (unlikely (!populate_log_font (&log_font, hdc, font)))
|
|
||||||
FAIL ("populate_log_font() failed");
|
|
||||||
|
|
||||||
HFONT hfont = CreateFontIndirectW (&log_font);
|
|
||||||
SelectObject (hdc, hfont);
|
|
||||||
|
|
||||||
SCRIPT_CACHE script_cache = NULL;
|
|
||||||
OPENTYPE_TAG language_tag = hb_ot_tag_from_language (buffer->props.language);
|
OPENTYPE_TAG language_tag = hb_ot_tag_from_language (buffer->props.language);
|
||||||
|
|
||||||
unsigned int glyphs_offset = 0;
|
unsigned int glyphs_offset = 0;
|
||||||
|
@ -223,8 +308,8 @@ retry:
|
||||||
unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset;
|
unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset;
|
||||||
OPENTYPE_TAG script_tag = script_tags[i]; /* XXX buffer->props.script */
|
OPENTYPE_TAG script_tag = script_tags[i]; /* XXX buffer->props.script */
|
||||||
|
|
||||||
hr = ScriptShapeOpenType (hdc,
|
hr = ScriptShapeOpenType (font_data->hdc,
|
||||||
&script_cache,
|
&font_data->script_cache,
|
||||||
&items[i].a,
|
&items[i].a,
|
||||||
script_tag,
|
script_tag,
|
||||||
language_tag,
|
language_tag,
|
||||||
|
@ -255,8 +340,8 @@ retry:
|
||||||
if (unlikely (FAILED (hr)))
|
if (unlikely (FAILED (hr)))
|
||||||
FAIL ("ScriptShapeOpenType() failed: 0x%08xL", hr);
|
FAIL ("ScriptShapeOpenType() failed: 0x%08xL", hr);
|
||||||
|
|
||||||
hr = ScriptPlaceOpenType (hdc,
|
hr = ScriptPlaceOpenType (font_data->hdc,
|
||||||
&script_cache,
|
&font_data->script_cache,
|
||||||
&items[i].a,
|
&items[i].a,
|
||||||
script_tag,
|
script_tag,
|
||||||
language_tag,
|
language_tag,
|
||||||
|
@ -281,10 +366,6 @@ retry:
|
||||||
}
|
}
|
||||||
glyphs_len = glyphs_offset;
|
glyphs_len = glyphs_offset;
|
||||||
|
|
||||||
ReleaseDC (NULL, hdc);
|
|
||||||
DeleteObject (hfont);
|
|
||||||
RemoveFontMemResourceEx (fh);
|
|
||||||
|
|
||||||
/* Ok, we've got everything we need, now compose output buffer,
|
/* Ok, we've got everything we need, now compose output buffer,
|
||||||
* very, *very*, carefully! */
|
* very, *very*, carefully! */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue