Paint only the damaged area instead of the whole widget. Reuse the rendering context to update the children. Scroll the children.

This commit is contained in:
pierre%netscape.com 1999-01-19 00:02:51 +00:00
Родитель 434b3ec6d6
Коммит 9b2c45c82a
2 изменённых файлов: 113 добавлений и 66 удалений

Просмотреть файл

@ -554,12 +554,14 @@ void nsWindow::StartDraw(nsIRenderingContext* aRenderingContext)
{
// make sure we have a rendering context
mTempRenderingContext = GetRenderingContext();
mTempRenderingContextMadeHere = PR_TRUE;
}
else
{
// if we already have a rendering context, save its state
NS_IF_ADDREF(aRenderingContext);
mTempRenderingContext = aRenderingContext;
mTempRenderingContextMadeHere = PR_FALSE;
mTempRenderingContext->PushState();
// set the environment to the current widget
@ -597,12 +599,15 @@ void nsWindow::StartDraw(nsIRenderingContext* aRenderingContext)
//-------------------------------------------------------------------------
void nsWindow::EndDraw()
{
if (! mDrawing)
if (! mDrawing)
return;
mDrawing = PR_FALSE;
PRBool clipEmpty;
mTempRenderingContext->PopState(clipEmpty);
if (mTempRenderingContextMadeHere)
{
PRBool clipEmpty;
mTempRenderingContext->PopState(clipEmpty);
}
NS_RELEASE(mTempRenderingContext);
}
@ -644,62 +649,21 @@ NS_IMETHODIMP nsWindow::Update()
::SectRgn(mWindowPtr->visRgn, updateRgn, updateRgn);
if (!::EmptyRgn(updateRgn))
{
nsIRenderingContext* renderingContext = GetRenderingContext(); // this sets the origin
nsIRenderingContext* renderingContext = GetRenderingContext();
if (renderingContext)
{
// initialize the paint event for that widget
// determine the rect to draw
nsRect rect;
#if 1
GetBounds(rect);
rect.x = rect.y = 0; // the origin is set on the topLeft corner of the widget
#else
//¥TODO: fix this: we don't want to always pass the entire rect
//GetBounds(rect);
//rect.x = rect.y = 0;
Rect macRect = (*updateRgn)->rgnBBox;
::OffsetRect(&macRect, -bounds.x, -bounds.y);
rect.x = macRect.left;
rect.y = macRect.top;
rect.width = macRect.right - macRect.left;
rect.height = macRect.bottom - macRect.top;
#endif
rect.SetRect(macRect.left, macRect.top, macRect.right - macRect.left, macRect.bottom - macRect.top);
// nsEvent
nsPaintEvent paintEvent;
paintEvent.eventStructType = NS_PAINT_EVENT;
paintEvent.message = NS_PAINT;
paintEvent.point.x = 0;
paintEvent.point.y = 0;
paintEvent.time = PR_IntervalNow();
// update the widget
UpdateWidget(rect, renderingContext);
// nsGUIEvent
paintEvent.widget = this;
paintEvent.nativeMsg = nsnull;
// nsPaintEvent
paintEvent.renderingContext = renderingContext;
paintEvent.rect = ▭
// draw the widget
StartDraw(renderingContext);
if (OnPaint(paintEvent))
DispatchWindowEvent(paintEvent);
EndDraw();
// recursively scan through its children to draw them too
nsIEnumerator* children = GetChildren();
if (children)
{
nsWindow* child;
children->First();
do
{
if (NS_SUCCEEDED(children->CurrentItem((nsISupports **)&child))) {
child->Update();
}
}
while (NS_SUCCEEDED(children->Next()));
delete children;
}
NS_RELEASE(renderingContext); // this restores the origin to (0, 0)
NS_RELEASE(renderingContext);
}
}
::DisposeRgn(updateRgn);
@ -707,6 +671,55 @@ NS_IMETHODIMP nsWindow::Update()
}
//-------------------------------------------------------------------------
//
//
//-------------------------------------------------------------------------
void nsWindow::UpdateWidget(nsRect& aRect, nsIRenderingContext* aContext)
{
// initialize the paint event
nsPaintEvent paintEvent;
paintEvent.eventStructType = NS_PAINT_EVENT; // nsEvent
paintEvent.message = NS_PAINT;
paintEvent.widget = this; // nsGUIEvent
paintEvent.nativeMsg = nsnull;
paintEvent.renderingContext = aContext; // nsPaintEvent
paintEvent.rect = &aRect;
// draw the widget
StartDraw(aContext);
if (OnPaint(paintEvent))
DispatchWindowEvent(paintEvent);
EndDraw();
// recursively draw the children
nsIEnumerator* children = GetChildren();
if (children)
{
nsWindow* child;
children->First();
do
{
if (NS_SUCCEEDED(children->CurrentItem((nsISupports **)&child)))
{
nsRect childBounds;
child->GetBounds(childBounds);
// redraw only the intersection of the child rect and the update rect
nsRect intersection;
if (intersection.IntersectRect(aRect, childBounds))
{
intersection.MoveBy(-childBounds.x, -childBounds.y);
child->UpdateWidget(intersection, aContext);
}
}
}
while (NS_SUCCEEDED(children->Next()));
delete children;
}
}
//-------------------------------------------------------------------------
//
// Scroll the bits of a window
@ -714,7 +727,44 @@ NS_IMETHODIMP nsWindow::Update()
//-------------------------------------------------------------------------
NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
{
Invalidate(PR_FALSE);
StartDraw();
// scroll the rect
Rect macRect;
nsRectToMacRect(*aClipRect, macRect);
RgnHandle updateRgn = ::NewRgn();
if (updateRgn == nil)
return NS_ERROR_OUT_OF_MEMORY;
::ClipRect(&macRect);
::ScrollRect(&macRect, aDx, aDy, updateRgn);
::InvalRgn(updateRgn);
::DisposeRgn(updateRgn);
// scroll the children
nsIEnumerator* children = GetChildren();
if (children)
{
nsWindow* child;
children->First();
do
{
if (NS_SUCCEEDED(children->CurrentItem((nsISupports **)&child))) {
nsRect bounds;
child->GetBounds(bounds);
bounds.x += aDx;
bounds.y += aDy;
child->SetBounds(bounds);
child->Scroll(aDx, aDy, &bounds);
}
}
while (NS_SUCCEEDED(children->Next()));
delete children;
}
EndDraw();
return NS_OK;
}

Просмотреть файл

@ -113,6 +113,7 @@ public:
virtual void EndDraw();
virtual PRBool OnPaint(nsPaintEvent &event);
NS_IMETHOD Update();
virtual void UpdateWidget(nsRect& aRect, nsIRenderingContext* aContext);
virtual void ConvertToDeviceCoordinates(nscoord &aX, nscoord &aY);
virtual void LocalToWindowCoordinate(nsPoint& aPoint);
@ -156,23 +157,19 @@ protected:
protected:
nsIWidget* mParent;
PRBool mVisible;
PRBool mEnabled;
PRInt32 mPreferredWidth;
PRInt32 mPreferredHeight;
nsIFontMetrics* mFontMetrics;
nsIMenuBar* mMenuBar;
RgnHandle mWindowRegion; // the region defining this window
WindowPtr mWindowPtr;
PRBool mDestroyCalled;
PRInt32 mPreferredWidth;
PRInt32 mPreferredHeight;
nsIFontMetrics* mFontMetrics;
nsIMenuBar* mMenuBar;
PRBool mDrawing;
nsIRenderingContext* mTempRenderingContext;
// MAC SPECIFIC MEMBERS
protected:
RgnHandle mWindowRegion; // the region defining this window
WindowPtr mWindowPtr;
PRBool mDrawing;
PRBool mDestroyCalled;
PRBool mTempRenderingContextMadeHere;
};
// =============================================================================