Bug 55494 - ScriptItemizeOpenType doesn't exists under Windows XP
Fallback to older API if OpenType variants are not available.
This commit is contained in:
parent
f8087ffbad
commit
2a17f9568d
14
configure.ac
14
configure.ac
|
@ -291,19 +291,7 @@ AC_ARG_WITH(uniscribe,
|
|||
[with_uniscribe=no])
|
||||
have_uniscribe=false
|
||||
if test "x$with_uniscribe" = "xyes" -o "x$with_uniscribe" = "xauto"; then
|
||||
AC_MSG_CHECKING([for ScriptShapeOpenType in usp10])
|
||||
saved_LIBS=$LIBS
|
||||
LIBS="$LIBS -lusp10 -lgdi32"
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM(
|
||||
[[
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#include <windows.h>
|
||||
#include <usp10.h>
|
||||
]],
|
||||
ScriptShapeOpenType)],
|
||||
[have_uniscribe=true; AC_MSG_RESULT(yes)],
|
||||
[AC_MSG_RESULT(no)])
|
||||
LIBS=$saved_LIBS
|
||||
AC_CHECK_HEADERS(usp10.h windows.h, have_uniscribe=true)
|
||||
fi
|
||||
if test "x$with_uniscribe" = "xyes" -a "x$have_uniscribe" != "xtrue"; then
|
||||
AC_MSG_ERROR([uniscribe support requested but not found])
|
||||
|
|
|
@ -44,15 +44,215 @@
|
|||
#endif
|
||||
|
||||
|
||||
/*
|
||||
DWORD GetFontData(
|
||||
__in HDC hdc,
|
||||
__in DWORD dwTable,
|
||||
__in DWORD dwOffset,
|
||||
__out LPVOID lpvBuffer,
|
||||
__in DWORD cbData
|
||||
typedef HRESULT WINAPI (*SIOT) /*ScriptItemizeOpenType*/(
|
||||
const WCHAR *pwcInChars,
|
||||
int cInChars,
|
||||
int cMaxItems,
|
||||
const SCRIPT_CONTROL *psControl,
|
||||
const SCRIPT_STATE *psState,
|
||||
SCRIPT_ITEM *pItems,
|
||||
OPENTYPE_TAG *pScriptTags,
|
||||
int *pcItems
|
||||
);
|
||||
*/
|
||||
|
||||
typedef HRESULT WINAPI (*SSOT) /*ScriptShapeOpenType*/(
|
||||
HDC hdc,
|
||||
SCRIPT_CACHE *psc,
|
||||
SCRIPT_ANALYSIS *psa,
|
||||
OPENTYPE_TAG tagScript,
|
||||
OPENTYPE_TAG tagLangSys,
|
||||
int *rcRangeChars,
|
||||
TEXTRANGE_PROPERTIES **rpRangeProperties,
|
||||
int cRanges,
|
||||
const WCHAR *pwcChars,
|
||||
int cChars,
|
||||
int cMaxGlyphs,
|
||||
WORD *pwLogClust,
|
||||
SCRIPT_CHARPROP *pCharProps,
|
||||
WORD *pwOutGlyphs,
|
||||
SCRIPT_GLYPHPROP *pOutGlyphProps,
|
||||
int *pcGlyphs
|
||||
);
|
||||
|
||||
typedef HRESULT WINAPI (*SPOT) /*ScriptPlaceOpenType*/(
|
||||
HDC hdc,
|
||||
SCRIPT_CACHE *psc,
|
||||
SCRIPT_ANALYSIS *psa,
|
||||
OPENTYPE_TAG tagScript,
|
||||
OPENTYPE_TAG tagLangSys,
|
||||
int *rcRangeChars,
|
||||
TEXTRANGE_PROPERTIES **rpRangeProperties,
|
||||
int cRanges,
|
||||
const WCHAR *pwcChars,
|
||||
WORD *pwLogClust,
|
||||
SCRIPT_CHARPROP *pCharProps,
|
||||
int cChars,
|
||||
const WORD *pwGlyphs,
|
||||
const SCRIPT_GLYPHPROP *pGlyphProps,
|
||||
int cGlyphs,
|
||||
int *piAdvance,
|
||||
GOFFSET *pGoffset,
|
||||
ABC *pABC
|
||||
);
|
||||
|
||||
|
||||
/* Fallback implementations. */
|
||||
|
||||
static HRESULT WINAPI
|
||||
hb_ScriptItemizeOpenType(
|
||||
const WCHAR *pwcInChars,
|
||||
int cInChars,
|
||||
int cMaxItems,
|
||||
const SCRIPT_CONTROL *psControl,
|
||||
const SCRIPT_STATE *psState,
|
||||
SCRIPT_ITEM *pItems,
|
||||
OPENTYPE_TAG *pScriptTags,
|
||||
int *pcItems
|
||||
)
|
||||
{
|
||||
{
|
||||
return ScriptItemize (pwcInChars,
|
||||
cInChars,
|
||||
cMaxItems,
|
||||
psControl,
|
||||
psState,
|
||||
pItems,
|
||||
pcItems);
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
hb_ScriptShapeOpenType(
|
||||
HDC hdc,
|
||||
SCRIPT_CACHE *psc,
|
||||
SCRIPT_ANALYSIS *psa,
|
||||
OPENTYPE_TAG tagScript,
|
||||
OPENTYPE_TAG tagLangSys,
|
||||
int *rcRangeChars,
|
||||
TEXTRANGE_PROPERTIES **rpRangeProperties,
|
||||
int cRanges,
|
||||
const WCHAR *pwcChars,
|
||||
int cChars,
|
||||
int cMaxGlyphs,
|
||||
WORD *pwLogClust,
|
||||
SCRIPT_CHARPROP *pCharProps,
|
||||
WORD *pwOutGlyphs,
|
||||
SCRIPT_GLYPHPROP *pOutGlyphProps,
|
||||
int *pcGlyphs
|
||||
)
|
||||
{
|
||||
SCRIPT_VISATTR *psva = (SCRIPT_VISATTR *) pOutGlyphProps;
|
||||
return ScriptShape (hdc,
|
||||
psc,
|
||||
pwcChars,
|
||||
cChars,
|
||||
cMaxGlyphs,
|
||||
psa,
|
||||
pwOutGlyphs,
|
||||
pwLogClust,
|
||||
psva,
|
||||
pcGlyphs);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
hb_ScriptPlaceOpenType(
|
||||
HDC hdc,
|
||||
SCRIPT_CACHE *psc,
|
||||
SCRIPT_ANALYSIS *psa,
|
||||
OPENTYPE_TAG tagScript,
|
||||
OPENTYPE_TAG tagLangSys,
|
||||
int *rcRangeChars,
|
||||
TEXTRANGE_PROPERTIES **rpRangeProperties,
|
||||
int cRanges,
|
||||
const WCHAR *pwcChars,
|
||||
WORD *pwLogClust,
|
||||
SCRIPT_CHARPROP *pCharProps,
|
||||
int cChars,
|
||||
const WORD *pwGlyphs,
|
||||
const SCRIPT_GLYPHPROP *pGlyphProps,
|
||||
int cGlyphs,
|
||||
int *piAdvance,
|
||||
GOFFSET *pGoffset,
|
||||
ABC *pABC
|
||||
)
|
||||
{
|
||||
SCRIPT_VISATTR *psva = (SCRIPT_VISATTR *) pGlyphProps;
|
||||
return ScriptPlace (hdc,
|
||||
psc,
|
||||
pwGlyphs,
|
||||
cGlyphs,
|
||||
psva,
|
||||
psa,
|
||||
piAdvance,
|
||||
pGoffset,
|
||||
pABC);
|
||||
}
|
||||
|
||||
|
||||
struct hb_uniscribe_shaper_funcs_t {
|
||||
SIOT ScriptItemizeOpenType;
|
||||
SSOT ScriptShapeOpenType;
|
||||
SPOT ScriptPlaceOpenType;
|
||||
|
||||
inline void init (void)
|
||||
{
|
||||
this->ScriptItemizeOpenType = NULL;
|
||||
this->ScriptShapeOpenType = NULL;
|
||||
this->ScriptPlaceOpenType = NULL;
|
||||
|
||||
HMODULE hinstLib = GetModuleHandle("usp10.dll");
|
||||
if (hinstLib)
|
||||
{
|
||||
this->ScriptItemizeOpenType = (SIOT) GetProcAddress (hinstLib, "ScriptItemizeOpenType");
|
||||
this->ScriptShapeOpenType = (SSOT) GetProcAddress (hinstLib, "ScriptShapeOpenType");
|
||||
this->ScriptPlaceOpenType = (SPOT) GetProcAddress (hinstLib, "ScriptPlaceOpenType");
|
||||
}
|
||||
if (!this->ScriptItemizeOpenType ||
|
||||
!this->ScriptShapeOpenType ||
|
||||
!this->ScriptPlaceOpenType)
|
||||
{
|
||||
DEBUG_MSG (UNISCRIBE, NULL, "OpenType versions of functions not found; falling back.");
|
||||
this->ScriptItemizeOpenType = hb_ScriptItemizeOpenType;
|
||||
this->ScriptShapeOpenType = hb_ScriptShapeOpenType;
|
||||
this->ScriptPlaceOpenType = hb_ScriptPlaceOpenType;
|
||||
}
|
||||
}
|
||||
};
|
||||
static hb_uniscribe_shaper_funcs_t *uniscribe_funcs;
|
||||
|
||||
static inline void
|
||||
free_uniscribe_funcs (void)
|
||||
{
|
||||
free (uniscribe_funcs);
|
||||
}
|
||||
|
||||
|
||||
static hb_uniscribe_shaper_funcs_t *
|
||||
hb_uniscribe_shaper_get_funcs (void)
|
||||
{
|
||||
retry:
|
||||
hb_uniscribe_shaper_funcs_t *funcs = (hb_uniscribe_shaper_funcs_t *) hb_atomic_ptr_get (&uniscribe_funcs);
|
||||
|
||||
if (unlikely (!funcs))
|
||||
{
|
||||
funcs = (hb_uniscribe_shaper_funcs_t *) calloc (1, sizeof (hb_uniscribe_shaper_funcs_t));
|
||||
if (unlikely (!funcs))
|
||||
return NULL;
|
||||
|
||||
funcs->init ();
|
||||
|
||||
if (!hb_atomic_ptr_cmpexch (&uniscribe_funcs, NULL, funcs)) {
|
||||
free (funcs);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ATEXIT
|
||||
atexit (free_uniscribe_funcs); /* First person registers atexit() callback. */
|
||||
#endif
|
||||
}
|
||||
|
||||
return funcs;
|
||||
}
|
||||
|
||||
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, face)
|
||||
|
@ -65,6 +265,7 @@ HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, font)
|
|||
|
||||
struct hb_uniscribe_shaper_face_data_t {
|
||||
HANDLE fh;
|
||||
hb_uniscribe_shaper_funcs_t *funcs;
|
||||
};
|
||||
|
||||
hb_uniscribe_shaper_face_data_t *
|
||||
|
@ -74,6 +275,13 @@ _hb_uniscribe_shaper_face_data_create (hb_face_t *face)
|
|||
if (unlikely (!data))
|
||||
return NULL;
|
||||
|
||||
data->funcs = hb_uniscribe_shaper_get_funcs ();
|
||||
if (unlikely (!data->funcs))
|
||||
{
|
||||
free (data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hb_blob_t *blob = hb_face_reference_blob (face);
|
||||
unsigned int blob_length;
|
||||
const char *blob_data = hb_blob_get_data (blob, &blob_length);
|
||||
|
@ -240,6 +448,7 @@ _hb_uniscribe_shape (hb_shape_plan_t *shape_plan,
|
|||
hb_face_t *face = font->face;
|
||||
hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
|
||||
hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
|
||||
hb_uniscribe_shaper_funcs_t *funcs = face_data->funcs;
|
||||
|
||||
#define FAIL(...) \
|
||||
HB_STMT_START { \
|
||||
|
@ -291,10 +500,19 @@ retry:
|
|||
|
||||
ALLOCATE_ARRAY (WORD, glyphs, glyphs_size);
|
||||
ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, glyphs_size);
|
||||
ALLOCATE_ARRAY (SCRIPT_VISATTR, vis_attr, glyphs_size);
|
||||
ALLOCATE_ARRAY (int, advances, glyphs_size);
|
||||
ALLOCATE_ARRAY (GOFFSET, offsets, glyphs_size);
|
||||
ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
|
||||
|
||||
/* Note:
|
||||
* We can't touch the contents of glyph_props. Our fallback
|
||||
* implementations of Shape and Place functions use that buffer
|
||||
* by casting it to a different type. It works because they
|
||||
* both agree about it, but if we want to access it here we
|
||||
* need address that issue first.
|
||||
*/
|
||||
|
||||
#undef ALLOCATE_ARRAY
|
||||
|
||||
#define MAX_ITEMS 256
|
||||
|
@ -312,14 +530,14 @@ retry:
|
|||
bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
|
||||
bidi_state.fOverrideDirection = 1;
|
||||
|
||||
hr = ScriptItemizeOpenType (wchars,
|
||||
chars_len,
|
||||
MAX_ITEMS,
|
||||
&bidi_control,
|
||||
&bidi_state,
|
||||
items,
|
||||
script_tags,
|
||||
&item_count);
|
||||
hr = funcs->ScriptItemizeOpenType (wchars,
|
||||
chars_len,
|
||||
MAX_ITEMS,
|
||||
&bidi_control,
|
||||
&bidi_state,
|
||||
items,
|
||||
script_tags,
|
||||
&item_count);
|
||||
if (unlikely (FAILED (hr)))
|
||||
FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr);
|
||||
|
||||
|
@ -344,23 +562,23 @@ retry:
|
|||
unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset;
|
||||
|
||||
retry_shape:
|
||||
hr = ScriptShapeOpenType (font_data->hdc,
|
||||
&font_data->script_cache,
|
||||
&items[i].a,
|
||||
script_tags[i],
|
||||
language_tag,
|
||||
range_char_counts,
|
||||
range_properties,
|
||||
range_count,
|
||||
wchars + chars_offset,
|
||||
item_chars_len,
|
||||
glyphs_size - glyphs_offset,
|
||||
/* out */
|
||||
log_clusters + chars_offset,
|
||||
char_props + chars_offset,
|
||||
glyphs + glyphs_offset,
|
||||
glyph_props + glyphs_offset,
|
||||
(int *) &glyphs_len);
|
||||
hr = funcs->ScriptShapeOpenType (font_data->hdc,
|
||||
&font_data->script_cache,
|
||||
&items[i].a,
|
||||
script_tags[i],
|
||||
language_tag,
|
||||
range_char_counts,
|
||||
range_properties,
|
||||
range_count,
|
||||
wchars + chars_offset,
|
||||
item_chars_len,
|
||||
glyphs_size - glyphs_offset,
|
||||
/* out */
|
||||
log_clusters + chars_offset,
|
||||
char_props + chars_offset,
|
||||
glyphs + glyphs_offset,
|
||||
glyph_props + glyphs_offset,
|
||||
(int *) &glyphs_len);
|
||||
|
||||
if (unlikely (items[i].a.fNoGlyphIndex))
|
||||
FAIL ("ScriptShapeOpenType() set fNoGlyphIndex");
|
||||
|
@ -386,25 +604,25 @@ retry:
|
|||
for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++)
|
||||
log_clusters[j] += glyphs_offset;
|
||||
|
||||
hr = ScriptPlaceOpenType (font_data->hdc,
|
||||
&font_data->script_cache,
|
||||
&items[i].a,
|
||||
script_tags[i],
|
||||
language_tag,
|
||||
range_char_counts,
|
||||
range_properties,
|
||||
range_count,
|
||||
wchars + chars_offset,
|
||||
log_clusters + chars_offset,
|
||||
char_props + chars_offset,
|
||||
item_chars_len,
|
||||
glyphs + glyphs_offset,
|
||||
glyph_props + glyphs_offset,
|
||||
glyphs_len,
|
||||
/* out */
|
||||
advances + glyphs_offset,
|
||||
offsets + glyphs_offset,
|
||||
NULL);
|
||||
hr = funcs->ScriptPlaceOpenType (font_data->hdc,
|
||||
&font_data->script_cache,
|
||||
&items[i].a,
|
||||
script_tags[i],
|
||||
language_tag,
|
||||
range_char_counts,
|
||||
range_properties,
|
||||
range_count,
|
||||
wchars + chars_offset,
|
||||
log_clusters + chars_offset,
|
||||
char_props + chars_offset,
|
||||
item_chars_len,
|
||||
glyphs + glyphs_offset,
|
||||
glyph_props + glyphs_offset,
|
||||
glyphs_len,
|
||||
/* out */
|
||||
advances + glyphs_offset,
|
||||
offsets + glyphs_offset,
|
||||
NULL);
|
||||
if (unlikely (FAILED (hr)))
|
||||
FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr);
|
||||
|
||||
|
|
Loading…
Reference in New Issue