📄 usp10.c
字号:
* Success: S_OK
* Failure: E_INVALIDARG if sds is invalid. Otherwise an HRESULT.
*/
HRESULT WINAPI ScriptApplyDigitSubstitution(const SCRIPT_DIGITSUBSTITUTE *sds,
SCRIPT_CONTROL *sc, SCRIPT_STATE *ss)
{
SCRIPT_DIGITSUBSTITUTE psds;
TRACE("%p, %p, %p\n", sds, sc, ss);
if (!sc || !ss) return E_POINTER;
if (!sds)
{
sds = &psds;
if (ScriptRecordDigitSubstitution(LOCALE_USER_DEFAULT, &psds) != S_OK)
return E_INVALIDARG;
}
sc->uDefaultLanguage = LANG_ENGLISH;
sc->fContextDigits = 0;
ss->fDigitSubstitute = 0;
switch (sds->DigitSubstitute) {
case SCRIPT_DIGITSUBSTITUTE_CONTEXT:
case SCRIPT_DIGITSUBSTITUTE_NATIONAL:
case SCRIPT_DIGITSUBSTITUTE_NONE:
case SCRIPT_DIGITSUBSTITUTE_TRADITIONAL:
return S_OK;
default:
return E_INVALIDARG;
}
}
/***********************************************************************
* ScriptItemize (USP10.@)
*
* Split a Unicode string into shapeable parts.
*
* PARAMS
* pwcInChars [I] String to split.
* cInChars [I] Number of characters in pwcInChars.
* cMaxItems [I] Maximum number of items to return.
* psControl [I] Pointer to a SCRIPT_CONTROL structure.
* psState [I] Pointer to a SCRIPT_STATE structure.
* pItems [O] Buffer to receive SCRIPT_ITEM structures.
* pcItems [O] Number of script items returned.
*
* RETURNS
* Success: S_OK
* Failure: Non-zero HRESULT value.
*/
HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItems,
const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState,
SCRIPT_ITEM *pItems, int *pcItems)
{
#define Numeric_start 0x0030
#define Numeric_stop 0x0039
#define Numeric_space 0x0020
#define Arabic_start 0x0600
#define Arabic_stop 0x06ff
#define Latin_start 0x0001
#define Latin_stop 0x024f
#define Script_Arabic 6
#define Script_Latin 1
#define Script_Numeric 5
int cnt = 0, index = 0;
int New_Script = SCRIPT_UNDEFINED;
TRACE("%s,%d,%d,%p,%p,%p,%p\n", debugstr_wn(pwcInChars, cInChars), cInChars, cMaxItems,
psControl, psState, pItems, pcItems);
if (!pwcInChars || !cInChars || !pItems || cMaxItems < 2)
return E_INVALIDARG;
pItems[index].iCharPos = 0;
memset(&pItems[index].a, 0, sizeof(SCRIPT_ANALYSIS));
if (pwcInChars[cnt] >= Numeric_start && pwcInChars[cnt] <= Numeric_stop)
pItems[index].a.eScript = Script_Numeric;
else
if (pwcInChars[cnt] >= Arabic_start && pwcInChars[cnt] <= Arabic_stop)
pItems[index].a.eScript = Script_Arabic;
else
if (pwcInChars[cnt] >= Latin_start && pwcInChars[cnt] <= Latin_stop)
pItems[index].a.eScript = Script_Latin;
if (pItems[index].a.eScript == Script_Arabic)
pItems[index].a.s.uBidiLevel = 1;
TRACE("New_Script=%d, eScript=%d index=%d cnt=%d iCharPos=%d\n",
New_Script, pItems[index].a.eScript, index, cnt,
pItems[index].iCharPos = cnt);
for (cnt=0; cnt < cInChars; cnt++)
{
if ((pwcInChars[cnt] >= Numeric_start && pwcInChars[cnt] <= Numeric_stop)
|| (New_Script == Script_Numeric && pwcInChars[cnt] == Numeric_space))
New_Script = Script_Numeric;
else
if ((pwcInChars[cnt] >= Arabic_start && pwcInChars[cnt] <= Arabic_stop)
|| (New_Script == Script_Arabic && pwcInChars[cnt] == Numeric_space))
New_Script = Script_Arabic;
else
if ((WCHAR) pwcInChars[cnt] >= Latin_start && (WCHAR) pwcInChars[cnt] <= Latin_stop)
New_Script = Script_Latin;
else
New_Script = SCRIPT_UNDEFINED;
if (New_Script != pItems[index].a.eScript)
{
TRACE("New_Script=%d, eScript=%d ", New_Script, pItems[index].a.eScript);
index++;
if (index+1 > cMaxItems)
return E_OUTOFMEMORY;
pItems[index].iCharPos = cnt;
memset(&pItems[index].a, 0, sizeof(SCRIPT_ANALYSIS));
if (New_Script == Script_Arabic)
pItems[index].a.s.uBidiLevel = 1;
pItems[index].a.eScript = New_Script;
if (New_Script == Script_Arabic)
pItems[index].a.s.uBidiLevel = 1;
TRACE("index=%d cnt=%d iCharPos=%d\n", index, cnt, pItems[index].iCharPos = cnt);
}
}
/* While not strictly necessary according to the spec, make sure the n+1
* item is set up to prevent random behaviour if the caller erroneously
* checks the n+1 structure */
memset(&pItems[index+1].a, 0, sizeof(SCRIPT_ANALYSIS));
TRACE("index=%d cnt=%d iCharPos=%d\n", index+1, cnt, pItems[index+1].iCharPos = cnt);
/* Set one SCRIPT_STATE item being returned */
*pcItems = index + 1;
/* Set SCRIPT_ITEM */
pItems[index+1].iCharPos = cnt; /* the last + 1 item
contains the ptr to the lastchar */
return S_OK;
}
/***********************************************************************
* ScriptStringAnalyse (USP10.@)
*
*/
HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString,
int cGlyphs, int iCharset, DWORD dwFlags,
int iReqWidth, SCRIPT_CONTROL *psControl,
SCRIPT_STATE *psState, const int *piDx,
SCRIPT_TABDEF *pTabdef, const BYTE *pbInClass,
SCRIPT_STRING_ANALYSIS *pssa)
{
HRESULT hr = E_OUTOFMEMORY;
StringAnalysis *analysis = NULL;
int i, num_items = 255;
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 (iCharset != -1)
{
FIXME("Only Unicode strings are supported\n");
return E_INVALIDARG;
}
if (cString < 1 || !pString) return E_INVALIDARG;
if ((dwFlags & SSA_GLYPHS) && !hdc) return E_PENDING;
if (!(analysis = usp_zero_alloc(sizeof(StringAnalysis)))) return E_OUTOFMEMORY;
if (!(analysis->pItem = usp_zero_alloc(num_items * sizeof(SCRIPT_ITEM) + 1))) goto error;
/* FIXME: handle clipping */
analysis->clip_len = cString;
hr = ScriptItemize(pString, cString, num_items, psControl, psState, analysis->pItem,
&analysis->numItems);
while (hr == E_OUTOFMEMORY)
{
SCRIPT_ITEM *tmp;
num_items *= 2;
if (!(tmp = usp_zero_realloc(analysis->pItem, num_items * sizeof(SCRIPT_ITEM) + 1)))
goto error;
analysis->pItem = tmp;
hr = ScriptItemize(pString, cString, num_items, psControl, psState, analysis->pItem,
&analysis->numItems);
}
if (hr) goto error;
if ((analysis->logattrs = usp_alloc(sizeof(SCRIPT_LOGATTR) * cString)))
ScriptBreak(pString, cString, (SCRIPT_STRING_ANALYSIS)analysis, analysis->logattrs);
else
goto error;
if (!(analysis->glyphs = usp_zero_alloc(sizeof(StringGlyphs) * analysis->numItems)))
goto error;
for (i = 0; i < analysis->numItems; i++)
{
SCRIPT_CACHE *sc = (SCRIPT_CACHE *)&analysis->sc;
int cChar = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos;
int numGlyphs = 1.5 * cChar + 16;
WORD *glyphs = usp_zero_alloc(sizeof(WORD) * numGlyphs);
WORD *pwLogClust = usp_zero_alloc(sizeof(WORD) * cChar);
int *piAdvance = usp_zero_alloc(sizeof(int) * numGlyphs);
SCRIPT_VISATTR *psva = usp_zero_alloc(sizeof(SCRIPT_VISATTR) * cChar);
GOFFSET *pGoffset = usp_zero_alloc(sizeof(GOFFSET) * numGlyphs);
ABC *abc = usp_zero_alloc(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;
}
*pssa = analysis;
return S_OK;
error:
usp_free(analysis->glyphs);
usp_free(analysis->logattrs);
usp_free(analysis->pItem);
usp_free(analysis);
return hr;
}
/***********************************************************************
* ScriptStringOut (USP10.@)
*
* This function takes the output of ScriptStringAnalyse and joins the segments
* of glyphs and passes the resulting string to ScriptTextOut. ScriptStringOut
* only processes glyphs.
*
* Parameters:
* ssa [I] buffer to hold the analysed string components
* iX [I] X axis displacement for output
* iY [I] Y axis displacement for output
* uOptions [I] flags controling output processing
* prc [I] rectangle coordinates
* iMinSel [I] starting pos for substringing output string
* iMaxSel [I] ending pos for substringing output string
* fDisabled [I] controls text highlighting
*
* RETURNS
* Success: S_OK
* Failure: is the value returned by ScriptTextOut
*/
HRESULT WINAPI ScriptStringOut(SCRIPT_STRING_ANALYSIS ssa,
int iX,
int iY,
UINT uOptions,
const RECT *prc,
int iMinSel,
int iMaxSel,
BOOL fDisabled)
{
StringAnalysis *analysis;
WORD *glyphs;
int item, cnt, x;
HRESULT hr;
TRACE("(%p,%d,%d,0x%1x,%p,%d,%d,%d)\n",
ssa, iX, iY, uOptions, prc, iMinSel, iMaxSel, fDisabled);
if (!(analysis = ssa)) return E_INVALIDARG;
/*
* Get storage for the output buffer for the consolidated strings
*/
cnt = 0;
for (item = 0; item < analysis->numItems; item++)
{
cnt += analysis->glyphs[item].numGlyphs;
}
if (!(glyphs = usp_alloc(sizeof(WCHAR) * cnt))) return E_OUTOFMEMORY;
/*
* ScriptStringOut only processes glyphs hence set ETO_GLYPH_INDEX
*/
uOptions |= ETO_GLYPH_INDEX;
analysis->pItem[0].a.fNoGlyphIndex = FALSE; /* say that we have glyphs */
/*
* Copy the string items into the output buffer
*/
TRACE("numItems %d\n", analysis->numItems);
cnt = 0;
for (item = 0; item < analysis->numItems; item++)
{
memcpy(&glyphs[cnt], analysis->glyphs[item].glyphs,
sizeof(WCHAR) * analysis->glyphs[item].numGlyphs);
TRACE("Item %d, Glyphs %d ", item, analysis->glyphs[item].numGlyphs);
for (x = cnt; x < analysis->glyphs[item].numGlyphs + cnt; x ++)
TRACE("%04x", glyphs[x]);
TRACE("\n");
cnt += analysis->glyphs[item].numGlyphs; /* point to the end of the copied text */
}
hr = ScriptTextOut(analysis->sc->hdc, (SCRIPT_CACHE *)&analysis->sc, iX, iY,
uOptions, prc, &analysis->pItem->a, NULL, 0, glyphs, cnt,
analysis->glyphs->piAdvance, NULL, analysis->glyphs->pGoffset);
TRACE("ScriptTextOut hr=%08x\n", hr);
/*
* Free the output buffer and script cache
*/
usp_free(glyphs);
return hr;
}
/***********************************************************************
* ScriptStringCPtoX (USP10.@)
*
*/
HRESULT WINAPI ScriptStringCPtoX(SCRIPT_STRING_ANALYSIS ssa, int icp, BOOL fTrailing, int* pX)
{
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 S_FALSE;
/* 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;
}
/***********************************************************************
* ScriptStringXtoCP (USP10.@)
*
*/
HRESULT WINAPI ScriptStringXtoCP(SCRIPT_STRING_ANALYSIS ssa, int iX, int* piCh, int* piTrailing)
{
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 S_FALSE;
/* 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++;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -