From e79066fd9d840de105c3431eb282400446c30857 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Mon, 14 Sep 2015 23:08:44 -0400 Subject: [PATCH] Attempted to clean up the Uniscribe stuff. --- winarea/drawtext.c | 197 ++++++++++++++++++++++++--------------------- 1 file changed, 107 insertions(+), 90 deletions(-) diff --git a/winarea/drawtext.c b/winarea/drawtext.c index 59efbe81..e7197642 100644 --- a/winarea/drawtext.c +++ b/winarea/drawtext.c @@ -38,6 +38,22 @@ void uiDrawFreeFont(uiDrawFont *df) - 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). */ +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 { WCHAR *text; size_t len; @@ -46,26 +62,22 @@ struct uniscribe { SCRIPT_CONTROL control; SCRIPT_STATE state; - SCRIPT_ITEM *items; + struct uniitem *items; int nItems; 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 -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 i; + HRESULT hr; ZeroMemory(s, sizeof (struct uniscribe)); @@ -73,17 +85,15 @@ void initUniscribe(struct uniscribe *s, WCHAR *text, HDC dc) s->len = wcslen(s->text); s->dc = dc; - // steps 1 through 3 are irrelevent here - - // step 4 + items = NULL; nAlloc = 32; for (;;) { // 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, nAlloc, &(s->control), &(s->state), - s->items, &(s->nItems)); + items, &(s->nItems)); if (hr == S_OK) break; if (hr == E_OUTOFMEMORY) { @@ -93,96 +103,103 @@ void initUniscribe(struct uniscribe *s, WCHAR *text, HDC dc) logHRESULT("error itemizing string in initUniscribe()", hr); } - // step 5 - // we're not using multiple fonts; we have no lists to merge - - // step 6 - s->glyphs = malloc(s->nItems * sizeof (WORD *)); - s->clusters = malloc(s->nItems * sizeof (WORD *)); - s->visattrs = malloc(s->nItems * sizeof (SCRIPT_VISATTR *)); - s->nGlyphs = malloc(s->nItems * sizeof (int)); + // 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++) { - WCHAR *pwcChars; - int nChars; - - pwcChars = s->text + s->items[i].iCharPos; - nChars = s->items[i + 1].iCharPos - s->items[i].iCharPos; - nAlloc = 1.5 * nChars + 16; -s->glyphs[i] = NULL;//TODO remove when switched to uiAlloc -s->visattrs[i] = NULL; - s->clusters[i] = malloc(nChars * sizeof (WORD)); - for (;;) { - s->glyphs[i] = realloc(s->glyphs[i], nAlloc * sizeof (WORD)); - s->visattrs[i] = realloc(s->visattrs[i], nAlloc * sizeof (SCRIPT_VISATTR)); - hr = ScriptShape(s->dc, &(s->cache), - pwcChars, nChars, - nAlloc, - &(s->items[i].a), - s->glyphs[i], s->clusters[i], - s->visattrs[i], &(s->nGlyphs[i])); - if (hr == S_OK) - break; - if (hr == E_OUTOFMEMORY) { - nAlloc *= 2; - continue; - } - logHRESULT("error shaping glyphs in initUniscribe()", hr); - } + 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); +} - // step 7 - // TODO +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 8 - s->advances = malloc(s->nItems * sizeof (int *)); - s->goffsets = malloc(s->nItems * sizeof (GOFFSET *)); - s->abcs = malloc(s->nItems * sizeof (ABC)); - for (i = 0; i < s->nItems; i++) { - s->advances[i] = malloc(s->nGlyphs[i] * sizeof (int)); - s->goffsets[i] = malloc(s->nGlyphs[i] * sizeof (GOFFSET)); - hr = ScriptPlace(s->dc, &(s->cache), - s->glyphs[i], s->nGlyphs[i], s->visattrs[i], - &(s->items[i].a), - s->advances[i], s->goffsets[i], &(s->abcs[i])); - if (hr != S_OK) - logHRESULT("error placing glyphs in initUniscribe()", hr); +// step 5 +// we're not using multiple fonts; we have no lists to merge + +// step 6 +static void shapeItem(struct uniscribe *s, int n) +{ + struct uniitem *item; + int nAlloc; + HRESULT hr; + + item = &(s->items[n]); + resetItem(item); + item->clusters = malloc(nChars * sizeof (WORD)); + + // TODO move to uiAlloc + nAlloc = 1.5 * item->nChars + 16; + for (;;) { + item->glyphs = realloc(item->glyphs, nAlloc * sizeof (WORD)); + item->visattrs = realloc(item->visattrs, nAlloc * sizeof (SCRIPT_VISATTR)); + hr = ScriptShape(s->dc, &(s->cache), + item->pwcChars, item->nChars, + nAlloc, + &(item->item.a), + item->glyphs, item->clusters, + item->visattrs, &(item->nGlyphs)); + if (hr == S_OK) + break; + if (hr == E_OUTOFMEMORY) { + nAlloc *= 2; + continue; + } + logHRESULT("error shaping glyphs in shapeItem()", hr); } } -void uninitUniscribe(struct uniscribe *s) +// step 7 +// TODO + +// step 8 +static void placeItem(struct uniscribe *s, int n) +{ + struct uniitem *item; + HRESULT hr; + + item = &(s->items[n]); + + item->advances = malloc(item->nGlyphs * sizeof (int)); + item->goffsets = malloc(item->nGlyphs * sizeof (GOFFSET)); + hr = ScriptPlace(s->dc, &(s->cache), + item->glyphs, item->nGlyphs, item->visattrs, + &(item->item.a), + item->advances, item->goffsets, &(item->abc)); + if (hr != S_OK) + logHRESULT("error placing glyphs in placeItem()", hr); +} + +static void uninitUniscribe(struct uniscribe *s) { HRESULT hr; int i; // 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++) - free(s->advances[i]); - free(s->advances); - - 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); + resetItem(&(s->items[i])); + free(s->items); hr = ScriptCacheFree(&(s->cache)); if (hr != S_OK) logHRESULT("error freeing Uniscribe cache in uninitUniscribe()"); - - free(s->items); }