Commit 300f6840 authored by Krzysztof Foltman's avatar Krzysztof Foltman Committed by Alexandre Julliard

Old font management replaced by the cache-based one, which keeps

maximum of 10 HFONTs at once, instead of one per a couple of runs.
parent ffeda154
......@@ -334,6 +334,7 @@ static LRESULT ME_StreamIn(HWND hwnd, DWORD format, EDITSTREAM *stream)
ME_TextEditor *ME_MakeEditor(HWND hWnd) {
ME_TextEditor *ed = ALLOC_OBJ(ME_TextEditor);
HDC hDC;
int i;
ed->hWnd = hWnd;
ed->pBuffer = ME_MakeText();
hDC = GetDC(hWnd);
......@@ -357,6 +358,12 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) {
ed->pUndoStack = ed->pRedoStack = NULL;
ed->nUndoMode = umAddToUndo;
ed->nParagraphs = 1;
for (i=0; i<HFONT_CACHE_SIZE; i++)
{
ed->pFontCache[i].nRefs = 0;
ed->pFontCache[i].nAge = 0;
ed->pFontCache[i].hFont = NULL;
}
ME_CheckCharOffsets(ed);
return ed;
}
......@@ -365,6 +372,7 @@ void ME_DestroyEditor(ME_TextEditor *editor)
{
ME_DisplayItem *pFirst = editor->pBuffer->pFirst;
ME_DisplayItem *p = pFirst, *pNext = NULL;
int i;
ME_ClearTempStyle(editor);
ME_EmptyUndoStack(editor);
......@@ -374,6 +382,11 @@ void ME_DestroyEditor(ME_TextEditor *editor)
p = pNext;
}
ME_ReleaseStyle(editor->pBuffer->pDefaultStyle);
for (i=0; i<HFONT_CACHE_SIZE; i++)
{
if (editor->pFontCache[i].hFont)
DeleteObject(editor->pFontCache[i].hFont);
}
FREE_OBJ(editor);
}
......@@ -597,6 +610,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
ME_Style *style;
LPWSTR wszText = ME_ToUnicode(hWnd, (void *)lParam);
size_t len = lstrlenW(wszText);
TRACE("EM_REPLACESEL - %s\n", debugstr_w(wszText));
ME_GetSelection(editor, &from, &to);
ME_CursorFromCharOfs(editor, from, &c);
......@@ -624,6 +638,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
case WM_SETTEXT:
{
LPWSTR wszText = ME_ToUnicode(hWnd, (void *)lParam);
TRACE("WM_SETTEXT - %s\n", (char *)(wszText)); /* debugstr_w() */
ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor));
/* uses default style! */
ME_InsertTextFromCursor(editor, 0, wszText, -1, editor->pBuffer->pDefaultStyle);
......
......@@ -30,10 +30,8 @@ void ME_AddRefStyle(ME_Style *item);
void ME_ReleaseStyle(ME_Style *item);
ME_Style *ME_GetInsertStyle(ME_TextEditor *editor, int nCursor);
ME_Style *ME_ApplyStyle(ME_Style *sSrc, CHARFORMAT2W *style);
void ME_PrepareStyle(ME_Context *c, ME_Style *s);
void ME_PrepareStyleFromDC(ME_Style *s, HDC hDC, int nSequence);
void ME_UnprepareStyle(ME_Style *s);
HFONT ME_SelectStyleFont(HDC hDC, ME_Style *s);
HFONT ME_SelectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s);
void ME_UnselectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s, HFONT hOldFont);
void ME_InitCharFormat2W(CHARFORMAT2W *pFmt);
void ME_SaveTempStyle(ME_TextEditor *editor);
void ME_ClearTempStyle(ME_TextEditor *editor);
......
......@@ -191,6 +191,16 @@ typedef enum {
umAddBackToUndo
} ME_UndoMode;
typedef struct tagME_FontCacheItem
{
LOGFONTW lfSpecs;
HFONT hFont;
int nRefs;
int nAge;
} ME_FontCacheItem;
#define HFONT_CACHE_SIZE 10
typedef struct tagME_TextEditor
{
HWND hWnd;
......@@ -211,6 +221,7 @@ typedef struct tagME_TextEditor
ME_DisplayItem *pUndoStack, *pRedoStack;
ME_UndoMode nUndoMode;
int nParagraphs;
ME_FontCacheItem pFontCache[HFONT_CACHE_SIZE];
} ME_TextEditor;
typedef struct tagME_Context
......
......@@ -58,14 +58,6 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew) {
FillRect(hDC, &rc, (HBRUSH)GetStockObject(LTGRAY_BRUSH));
}
ME_DestroyContext(&c);
item = editor->pBuffer->pFirst->next;
while(item != editor->pBuffer->pLast) {
if (item->type == diRun)
ME_UnprepareStyle(item->member.run.style);
item = item->next;
}
}
void ME_Repaint(ME_TextEditor *editor)
......@@ -101,8 +93,7 @@ void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, int nChar
HDC hDC = c->hDC;
HGDIOBJ hOldFont;
COLORREF rgbOld, rgbBack;
ME_PrepareStyle(c, s);
hOldFont = SelectObject(hDC, s->hFont);
hOldFont = ME_SelectStyleFont(c->editor, hDC, s);
rgbBack = ME_GetBackColor(c->editor);
if ((s->fmt.dwMask & CFM_COLOR) && (s->fmt.dwEffects & CFE_AUTOCOLOR))
rgbOld = SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
......@@ -125,11 +116,7 @@ void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, int nChar
PatBlt(hDC, x, ymin, sz.cx, cy, DSTINVERT);
}
SetTextColor(hDC, rgbOld);
SelectObject(hDC, hOldFont);
}
void ME_DrawSelection(ME_Context *c)
{
ME_UnselectStyleFont(c->editor, hDC, s, hOldFont);
}
void ME_DebugWrite(HDC hDC, POINT *pt, WCHAR *szText) {
......
......@@ -378,11 +378,10 @@ int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run)
return 1;
}
hDC = GetDC(editor->hWnd);
hOldFont = ME_SelectStyleFont(hDC, run->style);
hOldFont = ME_SelectStyleFont(editor, hDC, run->style);
GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen,
cx, &fit, NULL, &sz);
assert(run->style->hFont);
SelectObject(hDC, hOldFont);
ME_UnselectStyleFont(editor, hDC, run->style, hOldFont);
ReleaseDC(editor->hWnd, hDC);
return fit;
}
......@@ -406,7 +405,7 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run)
}
hDC = GetDC(editor->hWnd);
hOldFont = ME_SelectStyleFont(hDC, run->style);
hOldFont = ME_SelectStyleFont(editor, hDC, run->style);
GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen,
cx, &fit, NULL, &sz);
if (fit != run->strText->nLen)
......@@ -419,7 +418,7 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run)
if (cx >= (sz2.cx+sz3.cx)/2)
fit = fit1;
}
SelectObject(hDC, hOldFont);
ME_UnselectStyleFont(editor, hDC, run->style, hOldFont);
ReleaseDC(editor->hWnd, hDC);
return fit;
}
......@@ -436,9 +435,9 @@ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset)
ME_GetGraphicsSize(editor, pRun, &size);
return 1;
}
hOldFont = ME_SelectStyleFont(hDC, pRun->style);
hOldFont = ME_SelectStyleFont(editor, hDC, pRun->style);
GetTextExtentPoint32W(hDC, pRun->strText->szData, nOffset, &size);
SelectObject(hDC, hOldFont);
ME_UnselectStyleFont(editor, hDC, pRun->style, hOldFont);
ReleaseDC(editor->hWnd, hDC);
return size.cx;
}
......@@ -448,9 +447,9 @@ void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s,
{
HDC hDC = c->hDC;
HGDIOBJ hOldFont;
hOldFont = ME_SelectStyleFont(hDC, s);
hOldFont = ME_SelectStyleFont(c->editor, hDC, s);
GetTextExtentPoint32W(hDC, szText, nChars, size);
SelectObject(hDC, hOldFont);
ME_UnselectStyleFont(c->editor, hDC, s, hOldFont);
}
SIZE ME_GetRunSize(ME_Context *c, ME_Run *run, int nLen)
......
......@@ -248,68 +248,114 @@ void ME_DumpStyleToBuf(CHARFORMAT2W *pFmt, char buf[2048])
ME_DumpStyleEffect(&p, "Text protected:", pFmt, CFM_PROTECTED);
}
void ME_UnprepareStyle(ME_Style *s)
void ME_LogFontFromStyle(HDC hDC, LOGFONTW *lf, ME_Style *s)
{
if (s->hFont) {
DeleteObject(s->hFont);
s->hFont = NULL;
s->nSequence = -2;
}
}
void ME_PrepareStyleFromDC(ME_Style *s, HDC hDC, int nSequence)
{
HGDIOBJ hOldFont;
LOGFONTW lf;
int rx, ry;
if (nSequence == s->nSequence && s->hFont)
return;
/* assert(s); */
rx = GetDeviceCaps(hDC, LOGPIXELSX);
ry = GetDeviceCaps(hDC, LOGPIXELSY);
if (s->hFont) {
DeleteObject(s->hFont);
s->hFont = NULL;
}
ZeroMemory(&lf, sizeof(lf));
lstrcpyW(lf.lfFaceName, s->fmt.szFaceName);
lf.lfHeight = -s->fmt.yHeight*ry/1440;
lf.lfWeight = 400;
ZeroMemory(lf, sizeof(LOGFONTW));
lstrcpyW(lf->lfFaceName, s->fmt.szFaceName);
lf->lfHeight = -s->fmt.yHeight*ry/1440;
lf->lfWeight = 400;
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_BOLD)
lf.lfWeight = 700;
lf->lfWeight = 700;
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_WEIGHT)
lf.lfWeight = s->fmt.wWeight;
lf->lfWeight = s->fmt.wWeight;
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_ITALIC)
lf.lfItalic = 1;
lf->lfItalic = 1;
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_UNDERLINE)
lf.lfUnderline = 1;
lf->lfUnderline = 1;
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_STRIKEOUT)
lf.lfStrikeOut = 1;
lf->lfStrikeOut = 1;
/*lf.lfQuality = PROOF_QUALITY; */
lf.lfPitchAndFamily = s->fmt.bPitchAndFamily;
lf.lfCharSet = s->fmt.bCharSet;
s->hFont = CreateFontIndirectW(&lf);
assert(s->hFont);
GetObjectW(s->hFont, sizeof(LOGFONTW), &lf);
hOldFont = SelectObject(hDC, s->hFont);
GetTextMetricsW(hDC, &s->tm);
SelectObject(hDC, hOldFont);
s->nSequence = nSequence;
lf->lfPitchAndFamily = s->fmt.bPitchAndFamily;
lf->lfCharSet = s->fmt.bCharSet;
}
HFONT ME_SelectStyleFont(HDC hDC, ME_Style *s)
BOOL ME_IsFontEqual(LOGFONTW *p1, LOGFONTW *p2)
{
if (memcmp(p1, p2, sizeof(LOGFONTW)-sizeof(p1->lfFaceName)))
return FALSE;
if (lstrcmpW(p1->lfFaceName, p2->lfFaceName))
return FALSE;
return TRUE;
}
HFONT ME_SelectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s)
{
HFONT hOldFont;
ME_PrepareStyleFromDC(s, hDC, -1);
LOGFONTW lf;
int i, nEmpty, nAge = 0x7FFFFFFF;
ME_FontCacheItem *item;
assert(hDC);
assert(s);
ME_LogFontFromStyle(hDC, &lf, s);
for (i=0; i<HFONT_CACHE_SIZE; i++)
editor->pFontCache[i].nAge++;
for (i=0, nEmpty=-1, nAge=0; i<HFONT_CACHE_SIZE; i++)
{
item = &editor->pFontCache[i];
if (!item->nRefs)
{
if (item->nAge > nAge)
nEmpty = i, nAge = item->nAge;
}
if (ME_IsFontEqual(&item->lfSpecs, &lf))
break;
}
if (i < HFONT_CACHE_SIZE) /* found */
{
item = &editor->pFontCache[i];
TRACE("font reused %d\n", i);
s->hFont = item->hFont;
item->nRefs++;
}
else
{
item = &editor->pFontCache[nEmpty]; /* this legal even when nEmpty == -1, as we don't dereference it */
assert(nEmpty != -1); /* otherwise we leak cache entries or get too many fonts at once*/
if (item->hFont) {
TRACE("font deleted %d\n", nEmpty);
DeleteObject(item->hFont);
item->hFont = NULL;
}
s->hFont = CreateFontIndirectW(&lf);
assert(s->hFont);
TRACE("font created %d\n", nEmpty);
item->hFont = s->hFont;
item->nRefs = 1;
memcpy(&item->lfSpecs, &lf, sizeof(LOGFONTW));
}
hOldFont = SelectObject(hDC, s->hFont);
/* should be cached too, maybe ? */
GetTextMetricsW(hDC, &s->tm);
return hOldFont;
}
void ME_PrepareStyle(ME_Context *c, ME_Style *s)
void ME_UnselectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s, HFONT hOldFont)
{
ME_PrepareStyleFromDC(s, c->hDC, c->nSequence);
int i;
assert(hDC);
assert(s);
SelectObject(hDC, hOldFont);
for (i=0; i<HFONT_CACHE_SIZE; i++)
{
ME_FontCacheItem *pItem = &editor->pFontCache[i];
if (pItem->hFont == s->hFont && pItem->nRefs > 0)
{
pItem->nRefs--;
pItem->nAge = 0;
s->hFont = NULL;
return;
}
}
assert(0 == "UnselectStyleFont without SelectStyleFont");
}
void ME_DestroyStyle(ME_Style *s) {
......
......@@ -367,7 +367,6 @@ void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
for (p = tp->next; p!=tp->member.para.next_para; ) {
assert(p->type != diStartRow);
if (p->type == diRun) {
ME_PrepareStyle(c, p->member.run.style);
p = ME_WrapHandleRun(&wc, p);
continue;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment