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.
This commit is contained in:
Krzysztof Foltman 2005-03-08 16:26:23 +00:00 committed by Alexandre Julliard
parent ffeda154a1
commit 300f684053
7 changed files with 127 additions and 72 deletions

View File

@ -334,6 +334,7 @@ static LRESULT ME_StreamIn(HWND hwnd, DWORD format, EDITSTREAM *stream)
ME_TextEditor *ME_MakeEditor(HWND hWnd) { ME_TextEditor *ME_MakeEditor(HWND hWnd) {
ME_TextEditor *ed = ALLOC_OBJ(ME_TextEditor); ME_TextEditor *ed = ALLOC_OBJ(ME_TextEditor);
HDC hDC; HDC hDC;
int i;
ed->hWnd = hWnd; ed->hWnd = hWnd;
ed->pBuffer = ME_MakeText(); ed->pBuffer = ME_MakeText();
hDC = GetDC(hWnd); hDC = GetDC(hWnd);
@ -357,6 +358,12 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) {
ed->pUndoStack = ed->pRedoStack = NULL; ed->pUndoStack = ed->pRedoStack = NULL;
ed->nUndoMode = umAddToUndo; ed->nUndoMode = umAddToUndo;
ed->nParagraphs = 1; 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); ME_CheckCharOffsets(ed);
return ed; return ed;
} }
@ -365,6 +372,7 @@ void ME_DestroyEditor(ME_TextEditor *editor)
{ {
ME_DisplayItem *pFirst = editor->pBuffer->pFirst; ME_DisplayItem *pFirst = editor->pBuffer->pFirst;
ME_DisplayItem *p = pFirst, *pNext = NULL; ME_DisplayItem *p = pFirst, *pNext = NULL;
int i;
ME_ClearTempStyle(editor); ME_ClearTempStyle(editor);
ME_EmptyUndoStack(editor); ME_EmptyUndoStack(editor);
@ -374,6 +382,11 @@ void ME_DestroyEditor(ME_TextEditor *editor)
p = pNext; p = pNext;
} }
ME_ReleaseStyle(editor->pBuffer->pDefaultStyle); 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); FREE_OBJ(editor);
} }
@ -597,6 +610,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
ME_Style *style; ME_Style *style;
LPWSTR wszText = ME_ToUnicode(hWnd, (void *)lParam); LPWSTR wszText = ME_ToUnicode(hWnd, (void *)lParam);
size_t len = lstrlenW(wszText); size_t len = lstrlenW(wszText);
TRACE("EM_REPLACESEL - %s\n", debugstr_w(wszText));
ME_GetSelection(editor, &from, &to); ME_GetSelection(editor, &from, &to);
ME_CursorFromCharOfs(editor, from, &c); ME_CursorFromCharOfs(editor, from, &c);
@ -624,6 +638,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP
case WM_SETTEXT: case WM_SETTEXT:
{ {
LPWSTR wszText = ME_ToUnicode(hWnd, (void *)lParam); LPWSTR wszText = ME_ToUnicode(hWnd, (void *)lParam);
TRACE("WM_SETTEXT - %s\n", (char *)(wszText)); /* debugstr_w() */
ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor)); ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor));
/* uses default style! */ /* uses default style! */
ME_InsertTextFromCursor(editor, 0, wszText, -1, editor->pBuffer->pDefaultStyle); ME_InsertTextFromCursor(editor, 0, wszText, -1, editor->pBuffer->pDefaultStyle);

View File

@ -30,10 +30,8 @@ void ME_AddRefStyle(ME_Style *item);
void ME_ReleaseStyle(ME_Style *item); void ME_ReleaseStyle(ME_Style *item);
ME_Style *ME_GetInsertStyle(ME_TextEditor *editor, int nCursor); ME_Style *ME_GetInsertStyle(ME_TextEditor *editor, int nCursor);
ME_Style *ME_ApplyStyle(ME_Style *sSrc, CHARFORMAT2W *style); ME_Style *ME_ApplyStyle(ME_Style *sSrc, CHARFORMAT2W *style);
void ME_PrepareStyle(ME_Context *c, ME_Style *s); HFONT ME_SelectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s);
void ME_PrepareStyleFromDC(ME_Style *s, HDC hDC, int nSequence); void ME_UnselectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s, HFONT hOldFont);
void ME_UnprepareStyle(ME_Style *s);
HFONT ME_SelectStyleFont(HDC hDC, ME_Style *s);
void ME_InitCharFormat2W(CHARFORMAT2W *pFmt); void ME_InitCharFormat2W(CHARFORMAT2W *pFmt);
void ME_SaveTempStyle(ME_TextEditor *editor); void ME_SaveTempStyle(ME_TextEditor *editor);
void ME_ClearTempStyle(ME_TextEditor *editor); void ME_ClearTempStyle(ME_TextEditor *editor);

View File

@ -191,6 +191,16 @@ typedef enum {
umAddBackToUndo umAddBackToUndo
} ME_UndoMode; } 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 typedef struct tagME_TextEditor
{ {
HWND hWnd; HWND hWnd;
@ -211,6 +221,7 @@ typedef struct tagME_TextEditor
ME_DisplayItem *pUndoStack, *pRedoStack; ME_DisplayItem *pUndoStack, *pRedoStack;
ME_UndoMode nUndoMode; ME_UndoMode nUndoMode;
int nParagraphs; int nParagraphs;
ME_FontCacheItem pFontCache[HFONT_CACHE_SIZE];
} ME_TextEditor; } ME_TextEditor;
typedef struct tagME_Context typedef struct tagME_Context

View File

@ -58,14 +58,6 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew) {
FillRect(hDC, &rc, (HBRUSH)GetStockObject(LTGRAY_BRUSH)); FillRect(hDC, &rc, (HBRUSH)GetStockObject(LTGRAY_BRUSH));
} }
ME_DestroyContext(&c); 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) 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; HDC hDC = c->hDC;
HGDIOBJ hOldFont; HGDIOBJ hOldFont;
COLORREF rgbOld, rgbBack; COLORREF rgbOld, rgbBack;
ME_PrepareStyle(c, s); hOldFont = ME_SelectStyleFont(c->editor, hDC, s);
hOldFont = SelectObject(hDC, s->hFont);
rgbBack = ME_GetBackColor(c->editor); rgbBack = ME_GetBackColor(c->editor);
if ((s->fmt.dwMask & CFM_COLOR) && (s->fmt.dwEffects & CFE_AUTOCOLOR)) if ((s->fmt.dwMask & CFM_COLOR) && (s->fmt.dwEffects & CFE_AUTOCOLOR))
rgbOld = SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); 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); PatBlt(hDC, x, ymin, sz.cx, cy, DSTINVERT);
} }
SetTextColor(hDC, rgbOld); SetTextColor(hDC, rgbOld);
SelectObject(hDC, hOldFont); ME_UnselectStyleFont(c->editor, hDC, s, hOldFont);
}
void ME_DrawSelection(ME_Context *c)
{
} }
void ME_DebugWrite(HDC hDC, POINT *pt, WCHAR *szText) { void ME_DebugWrite(HDC hDC, POINT *pt, WCHAR *szText) {

View File

@ -378,11 +378,10 @@ int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run)
return 1; return 1;
} }
hDC = GetDC(editor->hWnd); 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, GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen,
cx, &fit, NULL, &sz); cx, &fit, NULL, &sz);
assert(run->style->hFont); ME_UnselectStyleFont(editor, hDC, run->style, hOldFont);
SelectObject(hDC, hOldFont);
ReleaseDC(editor->hWnd, hDC); ReleaseDC(editor->hWnd, hDC);
return fit; return fit;
} }
@ -406,7 +405,7 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run)
} }
hDC = GetDC(editor->hWnd); 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, GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen,
cx, &fit, NULL, &sz); cx, &fit, NULL, &sz);
if (fit != run->strText->nLen) 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) if (cx >= (sz2.cx+sz3.cx)/2)
fit = fit1; fit = fit1;
} }
SelectObject(hDC, hOldFont); ME_UnselectStyleFont(editor, hDC, run->style, hOldFont);
ReleaseDC(editor->hWnd, hDC); ReleaseDC(editor->hWnd, hDC);
return fit; return fit;
} }
@ -436,9 +435,9 @@ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset)
ME_GetGraphicsSize(editor, pRun, &size); ME_GetGraphicsSize(editor, pRun, &size);
return 1; return 1;
} }
hOldFont = ME_SelectStyleFont(hDC, pRun->style); hOldFont = ME_SelectStyleFont(editor, hDC, pRun->style);
GetTextExtentPoint32W(hDC, pRun->strText->szData, nOffset, &size); GetTextExtentPoint32W(hDC, pRun->strText->szData, nOffset, &size);
SelectObject(hDC, hOldFont); ME_UnselectStyleFont(editor, hDC, pRun->style, hOldFont);
ReleaseDC(editor->hWnd, hDC); ReleaseDC(editor->hWnd, hDC);
return size.cx; return size.cx;
} }
@ -448,9 +447,9 @@ void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s,
{ {
HDC hDC = c->hDC; HDC hDC = c->hDC;
HGDIOBJ hOldFont; HGDIOBJ hOldFont;
hOldFont = ME_SelectStyleFont(hDC, s); hOldFont = ME_SelectStyleFont(c->editor, hDC, s);
GetTextExtentPoint32W(hDC, szText, nChars, size); 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) SIZE ME_GetRunSize(ME_Context *c, ME_Run *run, int nLen)

View File

@ -248,68 +248,114 @@ void ME_DumpStyleToBuf(CHARFORMAT2W *pFmt, char buf[2048])
ME_DumpStyleEffect(&p, "Text protected:", pFmt, CFM_PROTECTED); 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; int rx, ry;
if (nSequence == s->nSequence && s->hFont)
return;
/* assert(s); */
rx = GetDeviceCaps(hDC, LOGPIXELSX); rx = GetDeviceCaps(hDC, LOGPIXELSX);
ry = GetDeviceCaps(hDC, LOGPIXELSY); ry = GetDeviceCaps(hDC, LOGPIXELSY);
if (s->hFont) { ZeroMemory(lf, sizeof(LOGFONTW));
DeleteObject(s->hFont); lstrcpyW(lf->lfFaceName, s->fmt.szFaceName);
s->hFont = NULL; lf->lfHeight = -s->fmt.yHeight*ry/1440;
} lf->lfWeight = 400;
ZeroMemory(&lf, sizeof(lf));
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) if (s->fmt.dwEffects & s->fmt.dwMask & CFM_BOLD)
lf.lfWeight = 700; lf->lfWeight = 700;
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_WEIGHT) 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) if (s->fmt.dwEffects & s->fmt.dwMask & CFM_ITALIC)
lf.lfItalic = 1; lf->lfItalic = 1;
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_UNDERLINE) if (s->fmt.dwEffects & s->fmt.dwMask & CFM_UNDERLINE)
lf.lfUnderline = 1; lf->lfUnderline = 1;
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_STRIKEOUT) if (s->fmt.dwEffects & s->fmt.dwMask & CFM_STRIKEOUT)
lf.lfStrikeOut = 1; lf->lfStrikeOut = 1;
/*lf.lfQuality = PROOF_QUALITY; */ /*lf.lfQuality = PROOF_QUALITY; */
lf.lfPitchAndFamily = s->fmt.bPitchAndFamily; lf->lfPitchAndFamily = s->fmt.bPitchAndFamily;
lf.lfCharSet = s->fmt.bCharSet; 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;
} }
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; HFONT hOldFont;
ME_PrepareStyleFromDC(s, hDC, -1); LOGFONTW lf;
assert(s->hFont); 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); hOldFont = SelectObject(hDC, s->hFont);
/* should be cached too, maybe ? */
GetTextMetricsW(hDC, &s->tm);
return hOldFont; 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) { void ME_DestroyStyle(ME_Style *s) {

View File

@ -367,7 +367,6 @@ void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
for (p = tp->next; p!=tp->member.para.next_para; ) { for (p = tp->next; p!=tp->member.para.next_para; ) {
assert(p->type != diStartRow); assert(p->type != diStartRow);
if (p->type == diRun) { if (p->type == diRun) {
ME_PrepareStyle(c, p->member.run.style);
p = ME_WrapHandleRun(&wc, p); p = ME_WrapHandleRun(&wc, p);
continue; continue;
} }