Attempted to clean up the Uniscribe stuff.

This commit is contained in:
Pietro Gagliardi 2015-09-14 23:08:44 -04:00
parent 9dbc8a1ba2
commit e79066fd9d
1 changed files with 107 additions and 90 deletions

View File

@ -38,6 +38,22 @@ void uiDrawFreeFont(uiDrawFont *df)
- http://www.microsoft.com/msj/1198/multilang/multilang.aspx - http://www.microsoft.com/msj/1198/multilang/multilang.aspx
Even with all this we're on our own with actual paragraph layout; see the last link for example code (which we don't use here). */ Even with all this we're on our own with actual paragraph layout; see the last link for example code (which we don't use here). */
struct uniitem {
SCRIPT_ITEM item;
int nGlyphs;
WORD *glyphs;
SCRIPT_VISATTR *visattrs;
int *advances;
GOFFSET *goffsets;
WCHAR *pwcChars;
int nChars;
WORD *clusters;
ABC abc;
};
struct uniscribe { struct uniscribe {
WCHAR *text; WCHAR *text;
size_t len; size_t len;
@ -46,26 +62,22 @@ struct uniscribe {
SCRIPT_CONTROL control; SCRIPT_CONTROL control;
SCRIPT_STATE state; SCRIPT_STATE state;
SCRIPT_ITEM *items; struct uniitem *items;
int nItems; int nItems;
SCRIPT_CACHE cache; SCRIPT_CACHE cache;
WORD **glyphs;
WORD **clusters;
SCRIPT_VISATTR **visattrs;
int *nGlyphs;
int **advances;
GOFFSET **gOffsets;
ABC *abcs;
}; };
// the step numbers in this function are according to the "Lay Out Text Using Uniscribe" section of https://msdn.microsoft.com/en-us/library/windows/desktop/dd317792%28v=vs.85%29.aspx // the step numbers in this function are according to the "Lay Out Text Using Uniscribe" section of https://msdn.microsoft.com/en-us/library/windows/desktop/dd317792%28v=vs.85%29.aspx
void initUniscribe(struct uniscribe *s, WCHAR *text, HDC dc)
// this does step 4
// steps 1 through 3 are irrelevent here
static void initUniscribe(struct uniscribe *s, WCHAR *text, HDC dc)
{ {
HRESULT hr; SCRIPT_ITEM *items;
int nAlloc; int nAlloc;
int i; int i;
HRESULT hr;
ZeroMemory(s, sizeof (struct uniscribe)); ZeroMemory(s, sizeof (struct uniscribe));
@ -73,17 +85,15 @@ void initUniscribe(struct uniscribe *s, WCHAR *text, HDC dc)
s->len = wcslen(s->text); s->len = wcslen(s->text);
s->dc = dc; s->dc = dc;
// steps 1 through 3 are irrelevent here items = NULL;
// step 4
nAlloc = 32; nAlloc = 32;
for (;;) { for (;;) {
// TODO use uiRealloc // TODO use uiRealloc
s->items = realloc(s->items, nAlloc * sizeof (SCRIPT_ITEM)); items = realloc(items, nAlloc * sizeof (SCRIPT_ITEM));
hr = ScriptItemize(s->text, s->len, hr = ScriptItemize(s->text, s->len,
nAlloc, nAlloc,
&(s->control), &(s->state), &(s->control), &(s->state),
s->items, &(s->nItems)); items, &(s->nItems));
if (hr == S_OK) if (hr == S_OK)
break; break;
if (hr == E_OUTOFMEMORY) { if (hr == E_OUTOFMEMORY) {
@ -93,40 +103,67 @@ void initUniscribe(struct uniscribe *s, WCHAR *text, HDC dc)
logHRESULT("error itemizing string in initUniscribe()", hr); logHRESULT("error itemizing string in initUniscribe()", hr);
} }
// this does part of step 6
s->items = malloc(s->nItems * sizeof (struct uniitem));
ZeroMemory(s->items, s->nItems * sizeof (struct uniitem));//TODO remove when switching to uiAlloc
for (i = 0; i < s->nItems; i++) {
s->items[i].pwcChars = s->text + items[i].iCharPos;
s->items[i].nChars = items[i + 1].iCharPos - items[i].iCharPos;
s->items[i].item = items[i];
}
free(items);
}
static void resetItem(struct uniitem *item)
{
if (item->nGlyphs == 0)
return;
item->nGlyphs = 0;
// TODO switch to uiFree
free(item->glyphs);
item->glyphs = NULL;
free(item->visattrs);
item->visattrs = NULL;
free(item->advances);
item->advances = NULL;
free(item->goffsets);
item->goffsets = NULL;
free(item->clusters);
item->clusters = NULL;
}
// step 5 // step 5
// we're not using multiple fonts; we have no lists to merge // we're not using multiple fonts; we have no lists to merge
// step 6 // step 6
s->glyphs = malloc(s->nItems * sizeof (WORD *)); static void shapeItem(struct uniscribe *s, int n)
s->clusters = malloc(s->nItems * sizeof (WORD *)); {
s->visattrs = malloc(s->nItems * sizeof (SCRIPT_VISATTR *)); struct uniitem *item;
s->nGlyphs = malloc(s->nItems * sizeof (int)); int nAlloc;
for (i = 0; i < s->nItems; i++) { HRESULT hr;
WCHAR *pwcChars;
int nChars;
pwcChars = s->text + s->items[i].iCharPos; item = &(s->items[n]);
nChars = s->items[i + 1].iCharPos - s->items[i].iCharPos; resetItem(item);
nAlloc = 1.5 * nChars + 16; item->clusters = malloc(nChars * sizeof (WORD));
s->glyphs[i] = NULL;//TODO remove when switched to uiAlloc
s->visattrs[i] = NULL; // TODO move to uiAlloc
s->clusters[i] = malloc(nChars * sizeof (WORD)); nAlloc = 1.5 * item->nChars + 16;
for (;;) { for (;;) {
s->glyphs[i] = realloc(s->glyphs[i], nAlloc * sizeof (WORD)); item->glyphs = realloc(item->glyphs, nAlloc * sizeof (WORD));
s->visattrs[i] = realloc(s->visattrs[i], nAlloc * sizeof (SCRIPT_VISATTR)); item->visattrs = realloc(item->visattrs, nAlloc * sizeof (SCRIPT_VISATTR));
hr = ScriptShape(s->dc, &(s->cache), hr = ScriptShape(s->dc, &(s->cache),
pwcChars, nChars, item->pwcChars, item->nChars,
nAlloc, nAlloc,
&(s->items[i].a), &(item->item.a),
s->glyphs[i], s->clusters[i], item->glyphs, item->clusters,
s->visattrs[i], &(s->nGlyphs[i])); item->visattrs, &(item->nGlyphs));
if (hr == S_OK) if (hr == S_OK)
break; break;
if (hr == E_OUTOFMEMORY) { if (hr == E_OUTOFMEMORY) {
nAlloc *= 2; nAlloc *= 2;
continue; continue;
} }
logHRESULT("error shaping glyphs in initUniscribe()", hr); logHRESULT("error shaping glyphs in shapeItem()", hr);
} }
} }
@ -134,55 +171,35 @@ s->visattrs[i] = NULL;
// TODO // TODO
// step 8 // step 8
s->advances = malloc(s->nItems * sizeof (int *)); static void placeItem(struct uniscribe *s, int n)
s->goffsets = malloc(s->nItems * sizeof (GOFFSET *)); {
s->abcs = malloc(s->nItems * sizeof (ABC)); struct uniitem *item;
for (i = 0; i < s->nItems; i++) { HRESULT hr;
s->advances[i] = malloc(s->nGlyphs[i] * sizeof (int));
s->goffsets[i] = malloc(s->nGlyphs[i] * sizeof (GOFFSET)); item = &(s->items[n]);
item->advances = malloc(item->nGlyphs * sizeof (int));
item->goffsets = malloc(item->nGlyphs * sizeof (GOFFSET));
hr = ScriptPlace(s->dc, &(s->cache), hr = ScriptPlace(s->dc, &(s->cache),
s->glyphs[i], s->nGlyphs[i], s->visattrs[i], item->glyphs, item->nGlyphs, item->visattrs,
&(s->items[i].a), &(item->item.a),
s->advances[i], s->goffsets[i], &(s->abcs[i])); item->advances, item->goffsets, &(item->abc));
if (hr != S_OK) if (hr != S_OK)
logHRESULT("error placing glyphs in initUniscribe()", hr); logHRESULT("error placing glyphs in placeItem()", hr);
}
} }
void uninitUniscribe(struct uniscribe *s) static void uninitUniscribe(struct uniscribe *s)
{ {
HRESULT hr; HRESULT hr;
int i; int i;
// TODO use uiFree // TODO use uiFree
free(s->abcs);
for (i = 0; i < s->goffsets; i++)
free(s->goffsets[i]);
free(s->goffsets);
for (i = 0; i < s->nItems; i++) for (i = 0; i < s->nItems; i++)
free(s->advances[i]); resetItem(&(s->items[i]));
free(s->advances); free(s->items);
free(s->nGlyphs);
for (i = 0; i < s->nItems; i++)
free(s->visattrs[i]);
free(s->visattrs);
for (i = 0; i < s->nItems; i++)
free(s->clusters[i]);
free(s->clusters);
for (i = 0; i < s->nItems; i++)
free(s->glyphs[i]);
free(s->glyphs);
hr = ScriptCacheFree(&(s->cache)); hr = ScriptCacheFree(&(s->cache));
if (hr != S_OK) if (hr != S_OK)
logHRESULT("error freeing Uniscribe cache in uninitUniscribe()"); logHRESULT("error freeing Uniscribe cache in uninitUniscribe()");
free(s->items);
} }