This patch implements ScriptStringAnalyse, ScriptStringFree,
ScriptStringXtoCP, ScriptStringCPtoX.
Also, many todo_wine's are removed.
Thanks,
Clinton Stimpson
ChangeLog
Implement ScriptStringAnalyse, ScriptStringFree,
ScriptStringXtoCP, ScriptStringCPtoX
------------------------------------------------------------------------
Index: dlls/usp10/usp10.c
===================================================================
RCS file: /home/wine/wine/dlls/usp10/usp10.c,v
retrieving revision 1.45
diff -u -r1.45 usp10.c
--- dlls/usp10/usp10.c 12 Dec 2006 20:30:48 -0000 1.45
+++ dlls/usp10/usp10.c 13 Dec 2006 03:28:30 -0000
@@ -73,6 +73,46 @@
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;
+
+static void ME_StringAnalysisFree(StringAnalysis* analysis)
+{
+ int i;
+ for(i=0; i<analysis->numItems; i++)
+ {
+ HeapFree(GetProcessHeap(), 0, analysis->glyphs[i].glyphs);
+ HeapFree(GetProcessHeap(), 0, analysis->glyphs[i].pwLogClust);
+ HeapFree(GetProcessHeap(), 0, analysis->glyphs[i].piAdvance);
+ HeapFree(GetProcessHeap(), 0, analysis->glyphs[i].psva);
+ HeapFree(GetProcessHeap(), 0, analysis->glyphs[i].pGoffset);
+ HeapFree(GetProcessHeap(), 0, analysis->glyphs[i].abc);
+ }
+
+ HeapFree(GetProcessHeap(), 0, analysis->glyphs);
+ HeapFree(GetProcessHeap(), 0, analysis->pItem);
+
+ HeapFree(GetProcessHeap(), 0, analysis);
+}
+
/***********************************************************************
* DllMain
*
@@ -448,9 +488,16 @@
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 +505,64 @@
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; i<analysis->numItems; 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;
}
/***********************************************************************
@@ -489,9 +593,46 @@
*/
HRESULT WINAPI ScriptStringCPtoX(SCRIPT_STRING_ANALYSIS ssa, int icp, BOOL
fTrailing, int* pX)
{
- FIXME("(%p), %d, %d, (%p): stub\n", ssa, icp, fTrailing, pX);
- *pX = 0; /* Set a reasonable value */
- return S_OK;
+ int i, j;
+ int runningX = 0;
+ int runningCp = 0;
+ StringAnalysis* analysis = ssa;
+ TRACE("(%p), %d, %d, (%p)\n", ssa, icp, fTrailing, pX);
+
+ if(!ssa || !pX)
+ {
+ return 1;
+ }
+
+ /* icp out of range */
+ if(icp < 0)
+ {
+ analysis->invalid = TRUE;
+ return E_INVALIDARG;
+ }
+
+ for(i=0; i<analysis->numItems; i++)
+ {
+ for(j=0; j<analysis->glyphs[i].numGlyphs; j++)
+ {
+ if(runningCp == icp && fTrailing == FALSE)
+ {
+ *pX = runningX;
+ return S_OK;
+ }
+ runningX += analysis->glyphs[i].piAdvance[j];
+ if(runningCp == icp && fTrailing == TRUE)
+ {
+ *pX = runningX;
+ return S_OK;
+ }
+ runningCp++;
+ }
+ }
+
+ /* icp out of range */
+ analysis->invalid = TRUE;
+ return E_INVALIDARG;
}
/***********************************************************************
@@ -500,19 +641,79 @@
*/
HRESULT WINAPI ScriptStringXtoCP(SCRIPT_STRING_ANALYSIS ssa, int iX, int* piCh, int* piTrailing)
{
- FIXME("(%p), %d, (%p), (%p): stub\n", ssa, iX, piCh, piTrailing);
- *piCh = 0; /* Set a reasonable value */
- *piTrailing = 0;
+ StringAnalysis* analysis = ssa;
+ int i;
+ int j;
+ int runningX = 0;
+ int runningCp = 0;
+ int width;
+
+ TRACE("(%p), %d, (%p), (%p)\n", ssa, iX, piCh, piTrailing);
+
+ if(!ssa || !piCh || !piTrailing)
+ {
+ return 1;
+ }
+
+ /* out of range */
+ if(iX < 0)
+ {
+ *piCh = -1;
+ *piTrailing = TRUE;
return S_OK;
+ }
+
+ for(i=0; i<analysis->numItems; i++)
+ {
+ for(j=0; j<analysis->glyphs[i].numGlyphs; j++)
+ {
+ width = analysis->glyphs[i].piAdvance[j];
+ if(iX < (runningX + width))
+ {
+ *piCh = runningCp;
+ if((iX - runningX) > width/2)
+ *piTrailing = TRUE;
+ else
+ *piTrailing = FALSE;
+ return S_OK;
+ }
+ runningX += width;
+ runningCp++;
+ }
+ }
+
+ /* out of range */
+ *piCh = analysis->pItem[analysis->numItems].iCharPos;
+ *piTrailing = FALSE;
+
+ return S_OK;
}
/***********************************************************************
* ScriptStringFree (USP10.@)
*
*/
-HRESULT WINAPI ScriptStringFree(SCRIPT_STRING_ANALYSIS *pssa) {
- FIXME("(%p): stub\n",pssa);
- return S_OK;
+HRESULT WINAPI ScriptStringFree(SCRIPT_STRING_ANALYSIS *pssa)
+{
+ StringAnalysis* analysis;
+ BOOL invalid;
+ TRACE("(%p)\n",pssa);
+
+ if(!pssa)
+ return E_INVALIDARG;
+
+ analysis = *pssa;
+ if(!analysis)
+ return E_INVALIDARG;
+
+ invalid = analysis->invalid;
+
+ ME_StringAnalysisFree(analysis);
+
+ if(invalid)
+ return E_INVALIDARG;
+
+ return S_OK;
}
/***********************************************************************
Index: dlls/usp10/tests/usp10.c
===================================================================
RCS file: /home/wine/wine/dlls/usp10/tests/usp10.c,v
retrieving revision 1.30
diff -u -r1.30 usp10.c
--- dlls/usp10/tests/usp10.c 12 Dec 2006 20:30:48 -0000 1.30
+++ dlls/usp10/tests/usp10.c 13 Dec 2006 03:28:30 -0000
@@ -701,21 +701,21 @@
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 @@
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,25 @@
*/
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);
+ 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
* 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(Cp + 1 == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X = %d\n", Cp + 1, Ch, X);
+ ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n",
iTrailing, X);
}
@@ -821,12 +821,12 @@
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);
- 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",
+ ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr);
+ ok(Cp == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X =
%d\n", Cp, Ch, X);
+ ok(iTrailing == TRUE, "ScriptStringXtoCP should return iTrailing = 1 not %d for X = %d\n",
iTrailing, X);
/*
@@ -837,12 +837,12 @@
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);
- 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(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr);
+ ok(Cp + 1 == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X =
%d\n", Cp + 1, Ch, X);
+ ok(iTrailing == FALSE, "ScriptStringXtoCP should return iTrailing = 0 not %d for X = %d\n",
iTrailing, X);
/*
@@ -853,19 +853,19 @@
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);
- 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",
+ ok(hr == S_OK, "ScriptStringXtoCP should return S_OK not %08x\n", hr);
+ ok(Cp - 1 == Ch, "ScriptStringXtoCP should return Ch = %d not %d for X =
%d\n", Cp - 1, Ch, X);
+ 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,7 +874,7 @@
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
@@ -884,13 +884,13 @@
fTrailing = FALSE;
Cp = String_len + 1;
hr = ScriptStringCPtoX(ssa, Cp, fTrailing, &X);
- todo_wine ok(hr == E_INVALIDARG, "ScriptStringCPtoX should return
E_INVALIDARG not %08x\n", hr);
+ ok(hr == E_INVALIDARG, "ScriptStringCPtoX should return E_INVALIDARG not
%08x\n", hr);
hr = ScriptStringFree(&ssa);
/*
* ScriptStringCPtoX should free ssa, hence ScriptStringFree should
fail
*/
- todo_wine ok(hr == E_INVALIDARG, "ScriptStringFree should return
E_INVALIDARG not %08x\n", hr);
+ ok(hr == E_INVALIDARG, "ScriptStringFree should return E_INVALIDARG not
%08x\n", hr);
}
}
------------------------------------------------------------------------