From b91eb5a11001b0f496bbcd47af775523bc5665df Mon Sep 17 00:00:00 2001 From: Clinton Stimpson Date: Fri, 15 Dec 2006 19:28:07 -0700 Subject: [PATCH] usp10: Implement ScriptStringAnalyse. --- dlls/usp10/tests/usp10.c | 57 ++++++++++++------------ dlls/usp10/usp10.c | 93 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 119 insertions(+), 31 deletions(-) diff --git a/dlls/usp10/tests/usp10.c b/dlls/usp10/tests/usp10.c index dd264921fb4..b522b88dd79 100644 --- a/dlls/usp10/tests/usp10.c +++ b/dlls/usp10/tests/usp10.c @@ -701,21 +701,21 @@ static void test_ScriptString(void) hr = ScriptStringAnalyse( hdc, teststr, String, Glyphs, Charset, Flags, ReqWidth, &Control, &State, Dx, &Tabdef, &InClass, &ssa); - todo_wine ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr); + ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr); /* test makes sure that a call with a valid pssa still works */ hr = ScriptStringAnalyse( hdc, teststr, String, Glyphs, Charset, Flags, ReqWidth, &Control, &State, Dx, &Tabdef, &InClass, &ssa); - todo_wine ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr); - todo_wine ok(ssa != NULL, "ScriptStringAnalyse pssa should not be NULL\n"); + ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr); + ok(ssa != NULL, "ScriptStringAnalyse pssa should not be NULL\n"); if (hr == 0) { hr = ScriptStringOut(ssa, X, Y, Options, &rc, MinSel, MaxSel, Disabled); todo_wine ok(hr == S_OK, "ScriptStringOut should return S_OK not %08x\n", hr); hr = ScriptStringFree(&ssa); - todo_wine ok(hr == S_OK, "ScriptStringFree should return S_OK not %08x\n", hr); + ok(hr == S_OK, "ScriptStringFree should return S_OK not %08x\n", hr); } } @@ -774,8 +774,8 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc) hr = ScriptStringAnalyse( hdc, String, String_len, Glyphs, Charset, Flags, ReqWidth, &Control, &State, NULL, &Tabdef, &InClass, &ssa); - todo_wine ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr); - todo_wine ok(ssa != NULL, "ScriptStringAnalyse ssa should not be NULL\n"); + ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr); + ok(ssa != NULL, "ScriptStringAnalyse ssa should not be NULL\n"); if (hr == 0) { /* @@ -792,25 +792,28 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc) */ fTrailing = FALSE; hr = ScriptStringCPtoX(ssa, Cp, fTrailing, &X); - todo_wine ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); + ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing); - todo_wine ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); - todo_wine ok(Cp == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp, Ch, X); - todo_wine ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n", + ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); + if(Cp == 0) + ok(Cp == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp, Ch, X); + else + todo_wine ok(Cp == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp, Ch, X); + ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n", iTrailing, X); fTrailing = TRUE; hr = ScriptStringCPtoX(ssa, Cp, fTrailing, &X); - todo_wine ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); + ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing); - todo_wine ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); + ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); /* - * Check that character position returned by ScriptStringXtoCP in Ch matches the + * Check that character position returned by ScriptStringXtoCP in Ch matches the * one input to ScriptStringCPtoX. This means that the Cp to X position and back * again works */ todo_wine ok(Cp + 1 == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp + 1, Ch, X); - todo_wine ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n", + ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n", iTrailing, X); } @@ -821,12 +824,12 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc) fTrailing = TRUE; Cp = 3; hr = ScriptStringCPtoX(ssa, Cp, fTrailing, &X); - todo_wine ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); + ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); X--; /* put X just inside the trailing edge */ hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing); - todo_wine ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); + ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); todo_wine ok(Cp == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp, Ch, X); - todo_wine ok(iTrailing == TRUE, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n", + todo_wine ok(iTrailing == TRUE, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n", iTrailing, X); /* @@ -837,12 +840,12 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc) fTrailing = TRUE; Cp = 3; hr = ScriptStringCPtoX(ssa, Cp, fTrailing, &X); - todo_wine ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); + ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); X++; /* put X just outside the trailing edge */ hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing); - todo_wine ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); + ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); todo_wine ok(Cp + 1 == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp + 1, Ch, X); - todo_wine ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n", + ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n", iTrailing, X); /* @@ -853,19 +856,19 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc) fTrailing = FALSE; Cp = 3; hr = ScriptStringCPtoX(ssa, Cp, fTrailing, &X); - todo_wine ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); + ok(hr == S_OK, "ScriptStringCPtoX should return S_OK not %08x\n", hr); X--; /* put X just outside the leading edge */ hr = ScriptStringXtoCP(ssa, X, &Ch, &iTrailing); - todo_wine ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); + ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr); todo_wine ok(Cp - 1 == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp - 1, Ch, X); - todo_wine ok(iTrailing == TRUE, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n", + todo_wine ok(iTrailing == TRUE, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n", iTrailing, X); /* * Cleanup the the SSA for the next round of tests - */ + */ hr = ScriptStringFree(&ssa); - todo_wine ok(hr == S_OK, "ScriptStringFree should return S_OK not %08x\n", hr); + ok(hr == S_OK, "ScriptStringFree should return S_OK not %08x\n", hr); /* * Test to see that exceeding the number of chars returns E_INVALIDARG. First @@ -874,10 +877,10 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc) hr = ScriptStringAnalyse( hdc, String, String_len, Glyphs, Charset, Flags, ReqWidth, &Control, &State, NULL, &Tabdef, &InClass, &ssa); - todo_wine ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr); + ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr); /* - * When ScriptStringCPtoX is called with a character position Cp that exceeds the + * When ScriptStringCPtoX is called with a character position Cp that exceeds the * string length, return E_INVALIDARG. This also invalidates the ssa so a * ScriptStringFree should also fail. */ diff --git a/dlls/usp10/usp10.c b/dlls/usp10/usp10.c index 7472218b195..ea5339bf0f1 100644 --- a/dlls/usp10/usp10.c +++ b/dlls/usp10/usp10.c @@ -73,6 +73,27 @@ typedef struct scriptcache { HDC hdc; } Scriptcache; +typedef struct { + int numGlyphs; + WORD* glyphs; + WORD* pwLogClust; + int* piAdvance; + SCRIPT_VISATTR* psva; + GOFFSET* pGoffset; + ABC* abc; +} StringGlyphs; + +typedef struct { + BOOL invalid; + HDC hdc; + int cItems; + int cMaxGlyphs; + SCRIPT_ITEM* pItem; + int numItems; + StringGlyphs* glyphs; + SIZE* sz; +} StringAnalysis; + /*********************************************************************** * DllMain * @@ -448,9 +469,16 @@ HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const BYTE *pbInClass, SCRIPT_STRING_ANALYSIS *pssa) { - FIXME("(%p,%p,%d,%d,%d,0x%x,%d,%p,%p,%p,%p,%p,%p): stub\n", - hdc, pString, cString, cGlyphs, iCharset, dwFlags, - iReqWidth, psControl, psState, piDx, pTabdef, pbInClass, pssa); + HRESULT hr; + StringAnalysis* analysis; + int numItemizedItems; + int i; + SCRIPT_CACHE* sc = 0; + + TRACE("(%p,%p,%d,%d,%d,0x%x,%d,%p,%p,%p,%p,%p,%p)\n", + hdc, pString, cString, cGlyphs, iCharset, dwFlags, + iReqWidth, psControl, psState, piDx, pTabdef, pbInClass, pssa); + if (1 > cString || NULL == pString) { return E_INVALIDARG; } @@ -458,7 +486,64 @@ HRESULT WINAPI ScriptStringAnalyse(HDC hdc, return E_PENDING; } - return E_NOTIMPL; + analysis = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(StringAnalysis)); + + analysis->hdc = hdc; + numItemizedItems = 255; + analysis->pItem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + numItemizedItems*sizeof(SCRIPT_ITEM)+1); + + hr = ScriptItemize(pString, cString, numItemizedItems, psControl, + psState, analysis->pItem, &analysis->numItems); + + while(hr == E_OUTOFMEMORY) + { + numItemizedItems *= 2; + HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, analysis->pItem, + numItemizedItems*sizeof(SCRIPT_ITEM)+1); + hr = ScriptItemize(pString, cString, numItemizedItems, psControl, + psState, analysis->pItem, &analysis->numItems); + } + + analysis->glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(StringGlyphs)*analysis->numItems); + sc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SCRIPT_CACHE)); + + for(i=0; inumItems; i++) + { + int cChar = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos; + int numGlyphs = 1.5 * cChar + 16; + WORD* glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WORD)*numGlyphs); + WORD* pwLogClust = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WORD)*cChar); + int* piAdvance = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(int)*numGlyphs); + SCRIPT_VISATTR* psva = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SCRIPT_VISATTR)*cChar); + GOFFSET* pGoffset = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GOFFSET)*numGlyphs); + ABC* abc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ABC)); + int numGlyphsReturned; + + /* FIXME: non unicode strings */ + WCHAR* pStr = (WCHAR*)pString; + hr = ScriptShape(hdc, sc, &pStr[analysis->pItem[i].iCharPos], + cChar, numGlyphs, &analysis->pItem[i].a, + glyphs, pwLogClust, psva, &numGlyphsReturned); + hr = ScriptPlace(hdc, sc, glyphs, numGlyphsReturned, psva, &analysis->pItem[i].a, + piAdvance, pGoffset, abc); + + analysis->glyphs[i].numGlyphs = numGlyphsReturned; + analysis->glyphs[i].glyphs = glyphs; + analysis->glyphs[i].pwLogClust = pwLogClust; + analysis->glyphs[i].piAdvance = piAdvance; + analysis->glyphs[i].psva = psva; + analysis->glyphs[i].pGoffset = pGoffset; + analysis->glyphs[i].abc = abc; + } + + HeapFree(GetProcessHeap(), 0, sc); + + *pssa = analysis; + + return S_OK; } /***********************************************************************