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])
|
[with_uniscribe=no])
|
||||||
have_uniscribe=false
|
have_uniscribe=false
|
||||||
if test "x$with_uniscribe" = "xyes" -o "x$with_uniscribe" = "xauto"; then
|
if test "x$with_uniscribe" = "xyes" -o "x$with_uniscribe" = "xauto"; then
|
||||||
AC_MSG_CHECKING([for ScriptShapeOpenType in usp10])
|
AC_CHECK_HEADERS(usp10.h windows.h, have_uniscribe=true)
|
||||||
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
|
|
||||||
fi
|
fi
|
||||||
if test "x$with_uniscribe" = "xyes" -a "x$have_uniscribe" != "xtrue"; then
|
if test "x$with_uniscribe" = "xyes" -a "x$have_uniscribe" != "xtrue"; then
|
||||||
AC_MSG_ERROR([uniscribe support requested but not found])
|
AC_MSG_ERROR([uniscribe support requested but not found])
|
||||||
|
|
|
@ -44,15 +44,215 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
typedef HRESULT WINAPI (*SIOT) /*ScriptItemizeOpenType*/(
|
||||||
DWORD GetFontData(
|
const WCHAR *pwcInChars,
|
||||||
__in HDC hdc,
|
int cInChars,
|
||||||
__in DWORD dwTable,
|
int cMaxItems,
|
||||||
__in DWORD dwOffset,
|
const SCRIPT_CONTROL *psControl,
|
||||||
__out LPVOID lpvBuffer,
|
const SCRIPT_STATE *psState,
|
||||||
__in DWORD cbData
|
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)
|
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 {
|
struct hb_uniscribe_shaper_face_data_t {
|
||||||
HANDLE fh;
|
HANDLE fh;
|
||||||
|
hb_uniscribe_shaper_funcs_t *funcs;
|
||||||
};
|
};
|
||||||
|
|
||||||
hb_uniscribe_shaper_face_data_t *
|
hb_uniscribe_shaper_face_data_t *
|
||||||
|
@ -74,6 +275,13 @@ _hb_uniscribe_shaper_face_data_create (hb_face_t *face)
|
||||||
if (unlikely (!data))
|
if (unlikely (!data))
|
||||||
return NULL;
|
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);
|
hb_blob_t *blob = hb_face_reference_blob (face);
|
||||||
unsigned int blob_length;
|
unsigned int blob_length;
|
||||||
const char *blob_data = hb_blob_get_data (blob, &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_face_t *face = font->face;
|
||||||
hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (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_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
|
||||||
|
hb_uniscribe_shaper_funcs_t *funcs = face_data->funcs;
|
||||||
|
|
||||||
#define FAIL(...) \
|
#define FAIL(...) \
|
||||||
HB_STMT_START { \
|
HB_STMT_START { \
|
||||||
|
@ -291,10 +500,19 @@ retry:
|
||||||
|
|
||||||
ALLOCATE_ARRAY (WORD, glyphs, glyphs_size);
|
ALLOCATE_ARRAY (WORD, glyphs, glyphs_size);
|
||||||
ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, 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 (int, advances, glyphs_size);
|
||||||
ALLOCATE_ARRAY (GOFFSET, offsets, glyphs_size);
|
ALLOCATE_ARRAY (GOFFSET, offsets, glyphs_size);
|
||||||
ALLOCATE_ARRAY (uint32_t, vis_clusters, 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
|
#undef ALLOCATE_ARRAY
|
||||||
|
|
||||||
#define MAX_ITEMS 256
|
#define MAX_ITEMS 256
|
||||||
|
@ -312,14 +530,14 @@ retry:
|
||||||
bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
|
bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
|
||||||
bidi_state.fOverrideDirection = 1;
|
bidi_state.fOverrideDirection = 1;
|
||||||
|
|
||||||
hr = ScriptItemizeOpenType (wchars,
|
hr = funcs->ScriptItemizeOpenType (wchars,
|
||||||
chars_len,
|
chars_len,
|
||||||
MAX_ITEMS,
|
MAX_ITEMS,
|
||||||
&bidi_control,
|
&bidi_control,
|
||||||
&bidi_state,
|
&bidi_state,
|
||||||
items,
|
items,
|
||||||
script_tags,
|
script_tags,
|
||||||
&item_count);
|
&item_count);
|
||||||
if (unlikely (FAILED (hr)))
|
if (unlikely (FAILED (hr)))
|
||||||
FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr);
|
FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr);
|
||||||
|
|
||||||
|
@ -344,23 +562,23 @@ retry:
|
||||||
unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset;
|
unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset;
|
||||||
|
|
||||||
retry_shape:
|
retry_shape:
|
||||||
hr = ScriptShapeOpenType (font_data->hdc,
|
hr = funcs->ScriptShapeOpenType (font_data->hdc,
|
||||||
&font_data->script_cache,
|
&font_data->script_cache,
|
||||||
&items[i].a,
|
&items[i].a,
|
||||||
script_tags[i],
|
script_tags[i],
|
||||||
language_tag,
|
language_tag,
|
||||||
range_char_counts,
|
range_char_counts,
|
||||||
range_properties,
|
range_properties,
|
||||||
range_count,
|
range_count,
|
||||||
wchars + chars_offset,
|
wchars + chars_offset,
|
||||||
item_chars_len,
|
item_chars_len,
|
||||||
glyphs_size - glyphs_offset,
|
glyphs_size - glyphs_offset,
|
||||||
/* out */
|
/* out */
|
||||||
log_clusters + chars_offset,
|
log_clusters + chars_offset,
|
||||||
char_props + chars_offset,
|
char_props + chars_offset,
|
||||||
glyphs + glyphs_offset,
|
glyphs + glyphs_offset,
|
||||||
glyph_props + glyphs_offset,
|
glyph_props + glyphs_offset,
|
||||||
(int *) &glyphs_len);
|
(int *) &glyphs_len);
|
||||||
|
|
||||||
if (unlikely (items[i].a.fNoGlyphIndex))
|
if (unlikely (items[i].a.fNoGlyphIndex))
|
||||||
FAIL ("ScriptShapeOpenType() set fNoGlyphIndex");
|
FAIL ("ScriptShapeOpenType() set fNoGlyphIndex");
|
||||||
|
@ -386,25 +604,25 @@ retry:
|
||||||
for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++)
|
for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++)
|
||||||
log_clusters[j] += glyphs_offset;
|
log_clusters[j] += glyphs_offset;
|
||||||
|
|
||||||
hr = ScriptPlaceOpenType (font_data->hdc,
|
hr = funcs->ScriptPlaceOpenType (font_data->hdc,
|
||||||
&font_data->script_cache,
|
&font_data->script_cache,
|
||||||
&items[i].a,
|
&items[i].a,
|
||||||
script_tags[i],
|
script_tags[i],
|
||||||
language_tag,
|
language_tag,
|
||||||
range_char_counts,
|
range_char_counts,
|
||||||
range_properties,
|
range_properties,
|
||||||
range_count,
|
range_count,
|
||||||
wchars + chars_offset,
|
wchars + chars_offset,
|
||||||
log_clusters + chars_offset,
|
log_clusters + chars_offset,
|
||||||
char_props + chars_offset,
|
char_props + chars_offset,
|
||||||
item_chars_len,
|
item_chars_len,
|
||||||
glyphs + glyphs_offset,
|
glyphs + glyphs_offset,
|
||||||
glyph_props + glyphs_offset,
|
glyph_props + glyphs_offset,
|
||||||
glyphs_len,
|
glyphs_len,
|
||||||
/* out */
|
/* out */
|
||||||
advances + glyphs_offset,
|
advances + glyphs_offset,
|
||||||
offsets + glyphs_offset,
|
offsets + glyphs_offset,
|
||||||
NULL);
|
NULL);
|
||||||
if (unlikely (FAILED (hr)))
|
if (unlikely (FAILED (hr)))
|
||||||
FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr);
|
FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue