From 97a83147b3ce867604088fec0072290c044ed30e Mon Sep 17 00:00:00 2001 From: Dylan Smith Date: Fri, 19 Dec 2008 09:54:58 -0500 Subject: [PATCH] richedit: Avoid re-calculating positions found in wrapping for painting. When the text is wrapped, the positions for all the runs, paragraphs, and cells are already calculated and stored. The only thing left to do for painting is to offset them by the formatting rectangle and the scroll position. --- dlls/riched20/paint.c | 203 ++++++++++++++++++++------------------------------ dlls/riched20/wrap.c | 3 +- 2 files changed, 81 insertions(+), 125 deletions(-) diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c index 0e12191128e..94a1f87d9cf 100644 --- a/dlls/riched20/paint.c +++ b/dlls/riched20/paint.c @@ -23,10 +23,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit); -void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *rcUpdate) { +void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *rcUpdate) +{ ME_DisplayItem *item; ME_Context c; int yoffset; + int ys, ye; editor->nSequence++; yoffset = ME_GetYScrollPos(editor); @@ -34,115 +36,70 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT * SetBkMode(hDC, TRANSPARENT); ME_MoveCaret(editor); /* Calls ME_WrapMarkedParagraphs */ item = editor->pBuffer->pFirst->next; - c.pt.y -= yoffset; - while(item != editor->pBuffer->pLast) { - int yTextOffset = 0; - int ys, ye; + /* This context point is an offset for the paragraph positions stored + * during wrapping. It shouldn't be modified during painting. */ + c.pt.x = c.rcView.left; + c.pt.y = c.rcView.top - yoffset; + while(item != editor->pBuffer->pLast) + { assert(item->type == diParagraph); + + ys = c.pt.y + item->member.para.pt.y; if (item->member.para.pCell != item->member.para.next_para->member.para.pCell) { ME_Cell *cell = NULL; cell = &ME_FindItemBack(item->member.para.next_para, diCell)->member.cell; - ye = cell->pt.y + cell->nHeight - yoffset; + ye = c.pt.y + cell->pt.y + cell->nHeight; } else { - ye = c.pt.y + item->member.para.nHeight; + ye = ys + item->member.para.nHeight; } - if (!(item->member.para.nFlags & MEPF_ROWEND) && + if (item->member.para.pCell && !(item->member.para.nFlags & MEPF_ROWEND) && item->member.para.pCell != item->member.para.prev_para->member.para.pCell) { - ME_DisplayItem *cell; - if (item->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART) - cell = item->member.para.pCell; - else - cell = item->member.para.prev_para->member.para.pCell; - assert(cell); /* the border shifts the text down */ - yTextOffset = cell->member.cell.yTextOffset; - ye += yTextOffset; + ys -= item->member.para.pCell->member.cell.yTextOffset; } + if (!bOnlyNew || (item->member.para.nFlags & MEPF_REPAINT)) { /* Draw the pargraph if any of the paragraph is in the update region. */ BOOL bPaint = (rcUpdate == NULL); - ys = c.pt.y; if (rcUpdate) - bPaint = ys + c.rcView.top < rcUpdate->bottom && - ye + c.rcView.top > rcUpdate->top; + bPaint = ys < rcUpdate->bottom && ye > rcUpdate->top; if (bPaint) { - c.pt.y += yTextOffset; ME_DrawParagraph(&c, item); /* Clear the repaint flag if the whole paragraph is in the * update region. */ - if (!rcUpdate || (rcUpdate->top <= ys + c.rcView.top && - rcUpdate->bottom >= ye + c.rcView.top)) + if (!rcUpdate || (rcUpdate->top <= ys && rcUpdate->bottom >= ye)) item->member.para.nFlags &= ~MEPF_REPAINT; } } - if (item->member.para.pCell) - { - ME_Cell *cell = &item->member.para.pCell->member.cell; - ME_DisplayItem *next_para = item->member.para.next_para; - c.pt.x = cell->pt.x + cell->nWidth; - if (item->member.para.pCell == next_para->member.para.pCell && - !(next_para->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND))) - { - c.pt.y = ye; - } else { - if (next_para->member.para.nFlags & MEPF_ROWSTART) - { - cell = &ME_FindItemFwd(next_para, diCell)->member.cell; - } - else if (next_para->member.para.nFlags & MEPF_ROWEND) - { - cell = &cell->next_cell->member.cell; - } - else - { - cell = &next_para->member.para.pCell->member.cell; - } - c.pt.y = cell->pt.y - yoffset; - } - } else if (!(item->member.para.nFlags & MEPF_ROWSTART)) { - c.pt.y = ye; - } item = item->member.para.next_para; } - if (c.pt.y < c.rcView.bottom - c.rcView.top) + if (c.pt.y + editor->nTotalLength < c.rcView.bottom) { /* Fill space after the end of the text. */ - int xs = c.rcView.left, xe = c.rcView.right; - int ys = c.rcView.top + c.pt.y, ye = c.rcView.bottom; + RECT rc; + rc.top = c.pt.y + editor->nTotalLength; + rc.left = c.rcView.left; + rc.bottom = c.rcView.bottom; + rc.right = c.rcView.right; if (bOnlyNew) { /* Only erase region drawn from previous call to ME_PaintContent */ - int y1 = editor->nTotalLength-yoffset, y2 = editor->nLastTotalLength-yoffset; - if (y1nTotalLength < editor->nLastTotalLength) + rc.bottom = c.pt.y + editor->nLastTotalLength; else - ys = ye; /* empty fill area */ + SetRectEmpty(&rc); } - if (rcUpdate) - { - /* Clip to update region */ - xs = max(xs, rcUpdate->left); - xe = min(xe, rcUpdate->right); - ys = max(ys, rcUpdate->top); - ye = min(ye, rcUpdate->bottom); - } + IntersectRect(&rc, &rc, rcUpdate); - if (xe > xs && ye > ys) - { - RECT rc; - rc.left = xs; - rc.top = ys; - rc.right = xe; - rc.bottom = ye; + if (!IsRectEmpty(&rc)) FillRect(hDC, &rc, c.editor->hbrBackground); - } } if (editor->nTotalLength != editor->nLastTotalLength) ME_SendRequestResize(editor, FALSE); @@ -451,7 +408,7 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa if (runofs >= nSelFrom && runofs < nSelTo) { ME_HighlightSpace(c, x, y, wszSpace, 1, run->style, 0, 0, 1, - c->rcView.top + c->pt.y + start->member.row.pt.y, + c->pt.y + para->pt.y + start->member.row.pt.y, start->member.row.nHeight); } return; @@ -463,7 +420,7 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa * an unwanted symbol can be inserted instead. */ ME_DrawTextWithStyle(c, x, y, wszSpace, 1, run->style, run->nWidth, nSelFrom-runofs, nSelTo-runofs, - c->rcView.top + c->pt.y + start->member.row.pt.y, + c->pt.y + para->pt.y + start->member.row.pt.y, start->member.row.nHeight); return; } @@ -478,7 +435,7 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa ME_DrawTextWithStyle(c, x, y, szMasked->szData, ME_StrVLen(szMasked), run->style, run->nWidth, nSelFrom-runofs,nSelTo-runofs, - c->rcView.top + c->pt.y + start->member.row.pt.y, + c->pt.y + para->pt.y + start->member.row.pt.y, start->member.row.nHeight); ME_DestroyString(szMasked); } @@ -486,7 +443,7 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa ME_DrawTextWithStyle(c, x, y, run->strText->szData, ME_StrVLen(run->strText), run->style, run->nWidth, nSelFrom-runofs,nSelTo-runofs, - c->rcView.top + c->pt.y + start->member.row.pt.y, + c->pt.y + para->pt.y + start->member.row.pt.y, start->member.row.nHeight); } } @@ -742,11 +699,11 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph) int width; BOOL atTop = (para->pCell != para->prev_para->member.para.pCell); BOOL atBottom = (para->pCell != para->next_para->member.para.pCell); - int top = c->rcView.top + (atTop ? cell->pt.y : para->pt.y) - ME_GetYScrollPos(c->editor); + int top = c->pt.y + (atTop ? cell->pt.y : para->pt.y); int bottom = (atBottom ? - c->rcView.top + cell->pt.y + cell->nHeight - ME_GetYScrollPos(c->editor): + c->pt.y + cell->pt.y + cell->nHeight : top + para->nHeight + (atTop ? cell->yTextOffset : 0)); - rc.left = c->rcView.left + cell->pt.x; + rc.left = c->pt.x + cell->pt.x; rc.right = rc.left + cell->nWidth; if (atTop) { /* Erase gap before text if not all borders are the same height. */ @@ -759,7 +716,7 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph) } } /* Draw cell borders. - * The borders borders are draw in is left, top, bottom, right in order + * The order borders are draw in is left, top, bottom, right in order * to be consistent with native richedit. This is noticeable from the * overlap of borders of different colours. */ if (!(para->nFlags & MEPF_ROWEND)) { @@ -812,7 +769,7 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph) ME_DisplayItem *nextEndCell; nextEndCell = ME_FindItemBack(ME_GetTableRowEnd(paraAfterRow), diCell); assert(nextEndCell && !nextEndCell->member.cell.next_cell); - rc.left = c->rcView.left + nextEndCell->member.cell.pt.x; + rc.left = c->pt.x + nextEndCell->member.cell.pt.x; /* FIXME: Native draws FROM the bottom of the table rather than * TO the bottom of the table in this case, but just doing so here * will cause the next row to erase the border. */ @@ -874,12 +831,12 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph) oldpen = SelectObject(c->hDC, pen); /* Find the start relative to the text */ - firstX = c->rcView.left + ME_FindItemFwd(paragraph, diRun)->member.run.pt.x; + firstX = c->pt.x + ME_FindItemFwd(paragraph, diRun)->member.run.pt.x; /* Go back by the horizontal gap, which is stored in dxOffset */ firstX -= ME_twips2pointsX(c, para->pFmt->dxOffset); /* The left edge, stored in dxStartIndent affected just the first edge */ startX = firstX - ME_twips2pointsX(c, para->pFmt->dxStartIndent); - rowY = c->rcView.top + c->pt.y; + rowY = c->pt.y + para->pt.y; if (para->pFmt->dwMask & PFM_SPACEBEFORE) rowY += ME_twips2pointsY(c, para->pFmt->dySpaceBefore); nHeight = ME_FindItemFwd(paragraph, diStartRow)->member.row.nHeight; @@ -928,45 +885,45 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) ME_Run *run; ME_Paragraph *para = NULL; RECT rc, bounds; - int y = c->rcView.top + c->pt.y; + int y; int height = 0, baseline = 0, no=0; BOOL visible = FALSE; - c->pt.x = c->rcView.left; - rc.left = c->rcView.left; + rc.left = c->pt.x; rc.right = c->rcView.right; - for (p = paragraph; p!=paragraph->member.para.next_para; p = p->next) { + + assert(paragraph); + para = ¶graph->member.para; + y = c->pt.y + para->pt.y; + if (para->pCell) + { + ME_Cell *cell = ¶->pCell->member.cell; + rc.left = c->pt.x + cell->pt.x; + rc.right = rc.left + cell->nWidth; + } + if (para->nFlags & MEPF_ROWSTART) { + ME_Cell *cell = ¶->next_para->member.para.pCell->member.cell; + rc.right = c->pt.x + cell->pt.x; + } else if (para->nFlags & MEPF_ROWEND) { + ME_Cell *cell = ¶->prev_para->member.para.pCell->member.cell; + rc.left = c->pt.x + cell->pt.x + cell->nWidth; + } + ME_DrawParaDecoration(c, para, y, &bounds); + y += bounds.top; + rc.left += bounds.left; + rc.right -= bounds.right; + + for (p = paragraph->next; p != para->next_para; p = p->next) + { switch(p->type) { case diParagraph: - para = &p->member.para; - assert(para); - if (para->pCell) - { - ME_Cell *cell = ¶->pCell->member.cell; - rc.left = c->rcView.left + cell->pt.x; - rc.right = rc.left + cell->nWidth; - } - if (para->nFlags & MEPF_ROWSTART) { - ME_Cell *cell = ¶->next_para->member.para.pCell->member.cell; - rc.right = c->rcView.left + cell->pt.x; - } else if (para->nFlags & MEPF_ROWEND) { - ME_Cell *cell = ¶->prev_para->member.para.pCell->member.cell; - rc.left = c->rcView.left + cell->pt.x + cell->nWidth; - } - ME_DrawParaDecoration(c, para, y, &bounds); - y += bounds.top; + assert(FALSE); break; case diStartRow: - /* we should have seen a diParagraph before */ - assert(para); y += height; rc.top = y; - if (para->nFlags & MEPF_ROWSTART) { - ME_Cell *cell = ¶->next_para->member.para.pCell->member.cell; - rc.bottom = y + cell->nHeight; - } else if (para->nFlags & MEPF_ROWEND) { - ME_Cell *cell = ¶->prev_para->member.para.pCell->member.cell; - rc.bottom = y + cell->nHeight; + if (para->nFlags & (MEPF_ROWSTART|MEPF_ROWEND)) { + rc.bottom = y + para->nHeight; } else { rc.bottom = y + p->member.row.nHeight; } @@ -991,9 +948,10 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) assert(para); run = &p->member.run; if (visible && me_debug) { - rc.left = c->rcView.left + run->pt.x; + RECT rc; + rc.left = c->pt.x + run->pt.x; rc.right = rc.left + run->nWidth; - rc.top = c->rcView.top + c->pt.y + run->pt.y; + rc.top = c->pt.y + para->pt.y + run->pt.y; rc.bottom = rc.bottom + height; TRACE("rc = (%d, %d, %d, %d)\n", rc.left, rc.top, rc.right, rc.bottom); if (run->nFlags & MERF_SKIPPED) @@ -1002,30 +960,27 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) FrameRect(c->hDC, &rc, GetSysColorBrush(COLOR_GRAYTEXT)); } if (visible) - ME_DrawRun(c, c->rcView.left + run->pt.x, - c->rcView.top + c->pt.y + run->pt.y + baseline, - p, ¶graph->member.para); + ME_DrawRun(c, c->pt.x + run->pt.x, + c->pt.y + para->pt.y + run->pt.y + baseline, p, para); if (me_debug) { /* I'm using %ls, hope wsprintfW is not going to use wrong (4-byte) WCHAR version */ const WCHAR wszRunDebug[] = {'[','%','d',':','%','x',']',' ','%','l','s',0}; WCHAR buf[2560]; POINT pt; - pt.x = run->pt.x; - pt.y = c->rcView.top + c->pt.y + run->pt.y; + pt.x = c->pt.x + run->pt.x; + pt.y = c->pt.y + para->pt.y + run->pt.y; wsprintfW(buf, wszRunDebug, no, p->member.run.nFlags, p->member.run.strText->szData); ME_DebugWrite(c->hDC, &pt, buf); } - /* c->pt.x += p->member.run.nWidth; */ break; case diCell: /* Clear any space at the bottom of the cell after the text. */ - if (para->nFlags & MEPF_ROWSTART) + if (para->nFlags & (MEPF_ROWSTART|MEPF_ROWEND)) break; y += height; - rc.top = y; - rc.bottom = c->rcView.top + p->member.cell.pt.y - + p->member.cell.nHeight - ME_GetYScrollPos(c->editor); + rc.top = c->pt.y + para->pt.y + para->nHeight; + rc.bottom = c->pt.y + p->member.cell.pt.y + p->member.cell.nHeight; if (RectVisible(c->hDC, &rc)) { FillRect(c->hDC, &rc, c->editor->hbrBackground); diff --git a/dlls/riched20/wrap.c b/dlls/riched20/wrap.c index 890c2bd8870..7eb844c733f 100644 --- a/dlls/riched20/wrap.c +++ b/dlls/riched20/wrap.c @@ -693,7 +693,8 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) c.pt.x = cell->pt.x + cell->nWidth; c.pt.y = cell->pt.y; cell->next_cell->member.cell.pt = c.pt; - c.pt.y += cell->yTextOffset; + if (!(item->member.para.next_para->member.para.nFlags & MEPF_ROWEND)) + c.pt.y += cell->yTextOffset; } else { -- 2.11.4.GIT