Author: dchapyshev
Date: Thu Feb 5 05:07:55 2009
New Revision: 39404
URL:
http://svn.reactos.org/svn/reactos?rev=39404&view=rev
Log:
- Sync usp10 with Wine head
Modified:
trunk/reactos/dll/win32/usp10/usp10.c
Modified: trunk/reactos/dll/win32/usp10/usp10.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/usp10/usp10.c?re…
==============================================================================
--- trunk/reactos/dll/win32/usp10/usp10.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/usp10/usp10.c [iso-8859-1] Thu Feb 5 05:07:55 2009
@@ -138,10 +138,16 @@
&props[73]
};
+#define GLYPH_BLOCK_SHIFT 8
+#define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT)
+#define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1)
+#define GLYPH_MAX 65536
+
typedef struct {
- HDC hdc;
LOGFONTW lf;
TEXTMETRICW tm;
+ WORD *glyphs[GLYPH_MAX / GLYPH_BLOCK_SIZE];
+ ABC *widths[GLYPH_MAX / GLYPH_BLOCK_SIZE];
} ScriptCache;
typedef struct {
@@ -155,6 +161,7 @@
} StringGlyphs;
typedef struct {
+ HDC hdc;
BOOL invalid;
int clip_len;
ScriptCache *sc;
@@ -187,68 +194,78 @@
return HeapFree(GetProcessHeap(), 0, mem);
}
-static HDC get_cache_hdc(SCRIPT_CACHE *psc)
-{
- return ((ScriptCache *)*psc)->hdc;
-}
-
-static WCHAR get_cache_default_char(SCRIPT_CACHE *psc)
+static inline WCHAR get_cache_default_char(SCRIPT_CACHE *psc)
{
return ((ScriptCache *)*psc)->tm.tmDefaultChar;
}
-static LONG get_cache_height(SCRIPT_CACHE *psc)
+static inline LONG get_cache_height(SCRIPT_CACHE *psc)
{
return ((ScriptCache *)*psc)->tm.tmHeight;
}
-static BYTE get_cache_pitch_family(SCRIPT_CACHE *psc)
+static inline BYTE get_cache_pitch_family(SCRIPT_CACHE *psc)
{
return ((ScriptCache *)*psc)->tm.tmPitchAndFamily;
}
-static HRESULT init_script_cache(const HDC hdc, ScriptCache *sc)
-{
- if (!GetTextMetricsW(hdc, &sc->tm)) return E_INVALIDARG;
- if (!GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(LOGFONTW), &sc->lf))
return E_INVALIDARG;
- sc->hdc = hdc;
- return S_OK;
-}
-
-static HRESULT get_script_cache(const HDC hdc, SCRIPT_CACHE *psc)
-{
+static inline WORD get_cache_glyph(SCRIPT_CACHE *psc, WCHAR c)
+{
+ WORD *block = ((ScriptCache *)*psc)->glyphs[c >> GLYPH_BLOCK_SHIFT];
+
+ if (!block) return 0;
+ return block[c & GLYPH_BLOCK_MASK];
+}
+
+static inline WORD set_cache_glyph(SCRIPT_CACHE *psc, WCHAR c, WORD glyph)
+{
+ WORD **block = &((ScriptCache *)*psc)->glyphs[c >> GLYPH_BLOCK_SHIFT];
+
+ if (!*block && !(*block = heap_alloc_zero(sizeof(WORD) * GLYPH_BLOCK_SIZE)))
return 0;
+ return ((*block)[c & GLYPH_BLOCK_MASK] = glyph);
+}
+
+static inline BOOL get_cache_glyph_widths(SCRIPT_CACHE *psc, WORD glyph, ABC *abc)
+{
+ static const ABC nil;
+ ABC *block = ((ScriptCache *)*psc)->widths[glyph >> GLYPH_BLOCK_SHIFT];
+
+ if (!block || !memcmp(&block[glyph & GLYPH_BLOCK_MASK], &nil,
sizeof(ABC))) return FALSE;
+ memcpy(abc, &block[glyph & GLYPH_BLOCK_MASK], sizeof(ABC));
+ return TRUE;
+}
+
+static inline BOOL set_cache_glyph_widths(SCRIPT_CACHE *psc, WORD glyph, ABC *abc)
+{
+ ABC **block = &((ScriptCache *)*psc)->widths[glyph >>
GLYPH_BLOCK_SHIFT];
+
+ if (!*block && !(*block = heap_alloc_zero(sizeof(ABC) * GLYPH_BLOCK_SIZE)))
return FALSE;
+ memcpy(&(*block)[glyph & GLYPH_BLOCK_MASK], abc, sizeof(ABC));
+ return TRUE;
+}
+
+static HRESULT init_script_cache(const HDC hdc, SCRIPT_CACHE *psc)
+{
+ ScriptCache *sc;
+
if (!psc) return E_INVALIDARG;
- if (!*psc)
- {
- HRESULT ret;
- ScriptCache *sc;
-
- if (!hdc) return E_PENDING;
- if (!(sc = heap_alloc_zero(sizeof(ScriptCache)))) return E_OUTOFMEMORY;
- if ((ret = init_script_cache(hdc, sc)))
- {
- heap_free(sc);
- return ret;
- }
- *psc = sc;
- }
- TRACE("<- %p\n", *psc);
- return S_OK;
-}
-
-static HFONT select_cached_font(SCRIPT_CACHE *psc)
-{
- HFONT old_font;
- ScriptCache *sc = *psc;
-
- old_font = SelectObject(sc->hdc, CreateFontIndirectW(&sc->lf));
- return old_font;
-}
-
-static void unselect_cached_font(SCRIPT_CACHE *psc, HFONT old_font)
-{
- ScriptCache *sc = *psc;
- DeleteObject(SelectObject(sc->hdc, old_font));
+ if (*psc) return S_OK;
+ if (!hdc) return E_PENDING;
+
+ if (!(sc = heap_alloc_zero(sizeof(ScriptCache)))) return E_OUTOFMEMORY;
+ if (!GetTextMetricsW(hdc, &sc->tm))
+ {
+ heap_free(sc);
+ return E_INVALIDARG;
+ }
+ if (!GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(LOGFONTW), &sc->lf))
+ {
+ heap_free(sc);
+ return E_INVALIDARG;
+ }
+ *psc = sc;
+ TRACE("<- %p\n", sc);
+ return S_OK;
}
/***********************************************************************
@@ -284,10 +301,16 @@
{
TRACE("%p\n", psc);
- if (psc)
- {
- heap_free(*psc);
- *psc = NULL;
+ if (psc && *psc)
+ {
+ unsigned int i;
+ for (i = 0; i < GLYPH_MAX / GLYPH_BLOCK_SIZE; i++)
+ {
+ heap_free(((ScriptCache *)*psc)->glyphs[i]);
+ heap_free(((ScriptCache *)*psc)->widths[i]);
+ }
+ heap_free(*psc);
+ *psc = NULL;
}
return S_OK;
}
@@ -337,7 +360,7 @@
TRACE("%p,%p,%p\n", hdc, psc, sfp);
if (!sfp) return E_INVALIDARG;
- if ((hr = get_script_cache(hdc, psc))) return hr;
+ if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
if (sfp->cBytes != sizeof(SCRIPT_FONTPROPERTIES))
return E_INVALIDARG;
@@ -496,6 +519,8 @@
#define Script_Arabic 6
#define Script_Latin 1
#define Script_Numeric 5
+#define Script_CR 22
+#define Script_LF 23
int cnt = 0, index = 0;
int New_Script = SCRIPT_UNDEFINED;
@@ -509,6 +534,12 @@
pItems[index].iCharPos = 0;
memset(&pItems[index].a, 0, sizeof(SCRIPT_ANALYSIS));
+ if (pwcInChars[cnt] == '\r')
+ pItems[index].a.eScript = Script_CR;
+ else
+ if (pwcInChars[cnt] == '\n')
+ pItems[index].a.eScript = Script_LF;
+ else
if (pwcInChars[cnt] >= Numeric_start && pwcInChars[cnt] <=
Numeric_stop)
pItems[index].a.eScript = Script_Numeric;
else
@@ -523,10 +554,16 @@
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++)
- {
+ pItems[index].iCharPos);
+
+ for (cnt=1; cnt < cInChars; cnt++)
+ {
+ if (pwcInChars[cnt] == '\r')
+ New_Script = Script_CR;
+ else
+ if (pwcInChars[cnt] == '\n')
+ New_Script = Script_LF;
+ else
if ((pwcInChars[cnt] >= Numeric_start && pwcInChars[cnt] <=
Numeric_stop)
|| (New_Script == Script_Numeric && pwcInChars[cnt] ==
Numeric_space))
New_Script = Script_Numeric;
@@ -535,7 +572,8 @@
|| (New_Script == Script_Arabic && pwcInChars[cnt] ==
Numeric_space))
New_Script = Script_Arabic;
else
- if ((WCHAR) pwcInChars[cnt] >= Latin_start && (WCHAR) pwcInChars[cnt]
<= Latin_stop)
+ if ((pwcInChars[cnt] >= Latin_start && pwcInChars[cnt] <=
Latin_stop)
+ || (New_Script == Script_Latin && pwcInChars[cnt] == Numeric_space))
New_Script = Script_Latin;
else
New_Script = SCRIPT_UNDEFINED;
@@ -557,7 +595,7 @@
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);
+ TRACE("index=%d cnt=%d iCharPos=%d\n", index, cnt,
pItems[index].iCharPos);
}
}
@@ -609,6 +647,7 @@
/* FIXME: handle clipping */
analysis->clip_len = cString;
+ analysis->hdc = hdc;
hr = ScriptItemize(pString, cString, num_items, psControl, psState,
analysis->pItem,
&analysis->numItems);
@@ -625,7 +664,7 @@
hr = ScriptItemize(pString, cString, num_items, psControl, psState,
analysis->pItem,
&analysis->numItems);
}
- if (hr) goto error;
+ if (hr != S_OK) goto error;
if ((analysis->logattrs = heap_alloc(sizeof(SCRIPT_LOGATTR) * cString)))
ScriptBreak(pString, cString, (SCRIPT_STRING_ANALYSIS)analysis,
analysis->logattrs);
@@ -753,7 +792,7 @@
cnt += analysis->glyphs[item].numGlyphs; /* point to the end of the copied
text */
}
- hr = ScriptTextOut(analysis->sc->hdc, (SCRIPT_CACHE *)&analysis->sc, iX,
iY,
+ hr = ScriptTextOut(analysis->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);
@@ -1006,7 +1045,7 @@
*/
HRESULT WINAPI ScriptBreak(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa,
SCRIPT_LOGATTR *la)
{
- unsigned int i;
+ int i;
TRACE("(%s, %d, %p, %p)\n", debugstr_wn(chars, count), count, sa, la);
@@ -1017,8 +1056,14 @@
memset(&la[i], 0, sizeof(SCRIPT_LOGATTR));
/* FIXME: set the other flags */
- la[i].fWhiteSpace = isspaceW(chars[i]);
+ la[i].fWhiteSpace = (chars[i] == ' ');
la[i].fCharStop = 1;
+
+ if (i > 0 && la[i - 1].fWhiteSpace)
+ {
+ la[i].fSoftBreak = 1;
+ la[i].fWordStop = 1;
+ }
}
return S_OK;
}
@@ -1196,7 +1241,8 @@
*/
HRESULT WINAPI ScriptIsComplex(const WCHAR *chars, int len, DWORD flag)
{
- unsigned int i, j;
+ int i;
+ unsigned int j;
TRACE("(%s,%d,0x%x)\n", debugstr_wn(chars, len), len, flag);
@@ -1238,47 +1284,56 @@
SCRIPT_ANALYSIS *psa, WORD *pwOutGlyphs, WORD *pwLogClust,
SCRIPT_VISATTR *psva, int *pcGlyphs)
{
- int cnt;
HRESULT hr;
- HFONT hfont;
-
- TRACE("(%p, %p, %p, %d, %d, %p)\n", hdc, psc, pwcChars, cChars,
cMaxGlyphs, psa);
+ unsigned int i;
+
+ TRACE("(%p, %p, %s, %d, %d, %p, %p, %p, %p, %p)\n", hdc, psc,
debugstr_wn(pwcChars, cChars),
+ cChars, cMaxGlyphs, psa, pwOutGlyphs, pwLogClust, psva, pcGlyphs);
+
if (psa) TRACE("psa values: %d, %d, %d, %d, %d, %d, %d\n", psa->eScript,
psa->fRTL, psa->fLayoutRTL,
psa->fLinkBefore, psa->fLinkAfter, psa->fLogicalOrder,
psa->fNoGlyphIndex);
if (!psva || !pcGlyphs) return E_INVALIDARG;
if (cChars > cMaxGlyphs) return E_OUTOFMEMORY;
- if ((hr = get_script_cache(hdc, psc))) return hr;
*pcGlyphs = cChars;
-
- hfont = select_cached_font(psc);
+ if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE) &&
!psa->fNoGlyphIndex)
{
- GetGlyphIndicesW(get_cache_hdc(psc), pwcChars, cChars, pwOutGlyphs, 0);
+ for (i = 0; i < cChars; i++)
+ {
+ if (!(pwOutGlyphs[i] = get_cache_glyph(psc, pwcChars[i])))
+ {
+ WORD glyph;
+ if (!hdc) return E_PENDING;
+ if (GetGlyphIndicesW(hdc, &pwcChars[i], 1, &glyph,
GGI_MARK_NONEXISTING_GLYPHS) == GDI_ERROR) return S_FALSE;
+ pwOutGlyphs[i] = set_cache_glyph(psc, pwcChars[i], glyph);
+ }
+ }
}
else
{
TRACE("no glyph translation\n");
- for (cnt = 0; cnt < cChars; cnt++) pwOutGlyphs[cnt] = pwcChars[cnt];
+ for (i = 0; i < cChars; i++) pwOutGlyphs[i] = pwcChars[i];
}
if (psva)
{
/* set up a valid SCRIPT_VISATTR and LogClust for each char in this run */
- for (cnt = 0; cnt < cChars; cnt++)
+ for (i = 0; i < cChars; i++)
{
/* FIXME: set to better values */
- psva[cnt].uJustification = 2;
- psva[cnt].fClusterStart = 1;
- psva[cnt].fDiacritic = 0;
- psva[cnt].fZeroWidth = 0;
-
- if (pwLogClust) pwLogClust[cnt] = cnt;
+ psva[i].uJustification = (pwcChars[i] == ' ') ? SCRIPT_JUSTIFY_BLANK
: SCRIPT_JUSTIFY_CHARACTER;
+ psva[i].fClusterStart = 1;
+ psva[i].fDiacritic = 0;
+ psva[i].fZeroWidth = 0;
+ psva[i].fReserved = 0;
+ psva[i].fShapeReserved = 0;
+
+ if (pwLogClust) pwLogClust[i] = i;
}
}
- unselect_cached_font(psc, hfont);
return S_OK;
}
@@ -1307,58 +1362,46 @@
SCRIPT_ANALYSIS *psa, int *piAdvance, GOFFSET *pGoffset, ABC
*pABC )
{
HRESULT hr;
- LPABC lpABC;
- HFONT hfont;
- unsigned int i;
-
- TRACE("(%p, %p, %p, %s, %d, %p, %p, %p)\n", hdc, psc, pwGlyphs,
- debugstr_wn(pwGlyphs, cGlyphs), cGlyphs, psva, psa, piAdvance);
+ int i;
+
+ TRACE("(%p, %p, %p, %d, %p, %p, %p, %p, %p)\n", hdc, psc, pwGlyphs,
cGlyphs, psva, psa,
+ piAdvance, pGoffset, pABC);
if (!psva) return E_INVALIDARG;
- if ((hr = get_script_cache(hdc, psc))) return hr;
-
- hfont = select_cached_font(psc);
-
- /* Here we need to calculate the width of the run unit. At this point the input
string
- * has been converted to glyphs and we still need to translate back to the original
chars
- * to get the correct ABC widths. */
-
- if (!(lpABC = heap_alloc_zero(sizeof(ABC) * cGlyphs))) return E_OUTOFMEMORY;
+ if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
+
if (pABC) memset(pABC, 0, sizeof(ABC));
-
- if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE) &&
!psa->fNoGlyphIndex)
- {
- GetCharABCWidthsI(get_cache_hdc(psc), 0, cGlyphs, (WORD *)pwGlyphs, lpABC);
- }
- else
- {
- INT width;
- for (i = 0; i < cGlyphs; i++)
+ for (i = 0; i < cGlyphs; i++)
+ {
+ ABC abc;
+ if (!get_cache_glyph_widths(psc, pwGlyphs[i], &abc))
{
- GetCharWidth32W(get_cache_hdc(psc), pwGlyphs[i], pwGlyphs[i], &width);
- lpABC[i].abcB = width;
+ if (!hdc) return E_PENDING;
+ if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE) &&
!psa->fNoGlyphIndex)
+ {
+ if (!GetCharABCWidthsI(hdc, 0, 1, (WORD *)&pwGlyphs[i], &abc))
return S_FALSE;
+ }
+ else
+ {
+ INT width;
+ if (!GetCharWidth32W(hdc, pwGlyphs[i], pwGlyphs[i], &width)) return
S_FALSE;
+ abc.abcB = width;
+ abc.abcA = abc.abcC = 0;
+ }
+ set_cache_glyph_widths(psc, pwGlyphs[i], &abc);
}
- }
-
- for (i = 0; i < cGlyphs; i++)
- {
- TRACE(" Glyph=%04x, abcA=%d, abcB=%d, abcC=%d index=%d\n",
- pwGlyphs[i], lpABC[i].abcA, lpABC[i].abcB, lpABC[i].abcC, i);
-
if (pABC)
{
- pABC->abcA += lpABC[i].abcA;
- pABC->abcB += lpABC[i].abcB;
- pABC->abcC += lpABC[i].abcC;
+ pABC->abcA += abc.abcA;
+ pABC->abcB += abc.abcB;
+ pABC->abcC += abc.abcC;
}
/* FIXME: set to more reasonable values */
if (pGoffset) pGoffset[i].du = pGoffset[i].dv = 0;
- if (piAdvance) piAdvance[i] = lpABC[i].abcA + lpABC[i].abcB + lpABC[i].abcC;
- }
+ if (piAdvance) piAdvance[i] = abc.abcA + abc.abcB + abc.abcC;
+ }
+
if (pABC) TRACE("Total for run: abcA=%d, abcB=%d, abcC=%d\n",
pABC->abcA, pABC->abcB, pABC->abcC);
-
- heap_free(lpABC);
- unselect_cached_font(psc, hfont);
return S_OK;
}
@@ -1383,19 +1426,32 @@
int cChars, DWORD dwFlags, WORD *pwOutGlyphs)
{
HRESULT hr;
- HFONT hfont;
+ int i;
TRACE("(%p,%p,%s,%d,0x%x,%p)\n", hdc, psc, debugstr_wn(pwcInChars, cChars),
cChars, dwFlags, pwOutGlyphs);
- if ((hr = get_script_cache(hdc, psc))) return hr;
-
- hfont = select_cached_font(psc);
- if (GetGlyphIndicesW(get_cache_hdc(psc), pwcInChars, cChars, pwOutGlyphs, 0) ==
GDI_ERROR)
- hr = S_FALSE;
-
- unselect_cached_font(psc, hfont);
- return hr;
+ if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
+
+ if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE))
+ {
+ for (i = 0; i < cChars; i++)
+ {
+ if (!(pwOutGlyphs[i] = get_cache_glyph(psc, pwcInChars[i])))
+ {
+ WORD glyph;
+ if (!hdc) return E_PENDING;
+ if (GetGlyphIndicesW(hdc, &pwcInChars[i], 1, &glyph,
GGI_MARK_NONEXISTING_GLYPHS) == GDI_ERROR) return S_FALSE;
+ pwOutGlyphs[i] = set_cache_glyph(psc, pwcInChars[i], glyph);
+ }
+ }
+ }
+ else
+ {
+ TRACE("no glyph translation\n");
+ for (i = 0; i < cChars; i++) pwOutGlyphs[i] = pwcInChars[i];
+ }
+ return S_OK;
}
/***********************************************************************
@@ -1447,7 +1503,7 @@
TRACE("(%p, %p, %p)\n", hdc, psc, height);
if (!height) return E_INVALIDARG;
- if ((hr = get_script_cache(hdc, psc))) return hr;
+ if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
*height = get_cache_height(psc);
return S_OK;
@@ -1470,18 +1526,29 @@
*/
HRESULT WINAPI ScriptGetGlyphABCWidth(HDC hdc, SCRIPT_CACHE *psc, WORD glyph, ABC *abc)
{
- HFONT hfont;
- HRESULT hr = S_OK;
+ HRESULT hr;
TRACE("(%p, %p, 0x%04x, %p)\n", hdc, psc, glyph, abc);
- if ((hr = get_script_cache(hdc, psc))) return hr;
-
- hfont = select_cached_font(psc);
- if (!GetCharABCWidthsI(get_cache_hdc(psc), 0, 1, &glyph, abc)) hr = E_HANDLE;
-
- unselect_cached_font(psc, hfont);
- return hr;
+ if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr;
+
+ if (!get_cache_glyph_widths(psc, glyph, abc))
+ {
+ if (!hdc) return E_PENDING;
+ if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE))
+ {
+ if (!GetCharABCWidthsI(hdc, 0, 1, &glyph, abc)) return S_FALSE;
+ }
+ else
+ {
+ INT width;
+ if (!GetCharWidth32W(hdc, glyph, glyph, &width)) return S_FALSE;
+ abc->abcB = width;
+ abc->abcA = abc->abcC = 0;
+ }
+ set_cache_glyph_widths(psc, glyph, abc);
+ }
+ return S_OK;
}
/***********************************************************************
@@ -1601,7 +1668,7 @@
*/
const SIZE * WINAPI ScriptString_pSize(SCRIPT_STRING_ANALYSIS ssa)
{
- unsigned int i, j;
+ int i, j;
StringAnalysis *analysis = ssa;
TRACE("(%p)\n", ssa);
@@ -1680,7 +1747,8 @@
*/
HRESULT WINAPI ScriptStringGetOrder(SCRIPT_STRING_ANALYSIS ssa, UINT *order)
{
- unsigned int i, j, k;
+ int i, j;
+ unsigned int k;
StringAnalysis *analysis = ssa;
TRACE("(%p)\n", ssa);
@@ -1727,9 +1795,8 @@
return S_OK;
}
-
-VOID WINAPI LpkPresent()
-{
- /* FIXME */
- ERR("LPK: %s is unimplemented, please try again later.\n", __FUNCTION__);
-}
+VOID WINAPI LpkPresent()
+{
+ /* FIXME */
+ ERR("LPK: %s is unimplemented, please try again later.\n", __FUNCTION__);
+}