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:
parent
ffeda154a1
commit
300f684053
|
@ -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);
|
||||
assert(s->hFont);
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue