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 // make sure we have a rendering context
mTempRenderingContext = GetRenderingContext(); mTempRenderingContext = GetRenderingContext();
mTempRenderingContextMadeHere = PR_TRUE;
} }
else else
{ {
// if we already have a rendering context, save its state // if we already have a rendering context, save its state
NS_IF_ADDREF(aRenderingContext); NS_IF_ADDREF(aRenderingContext);
mTempRenderingContext = aRenderingContext; mTempRenderingContext = aRenderingContext;
mTempRenderingContextMadeHere = PR_FALSE;
mTempRenderingContext->PushState(); mTempRenderingContext->PushState();
// set the environment to the current widget // set the environment to the current widget
@ -597,12 +599,15 @@ void nsWindow::StartDraw(nsIRenderingContext* aRenderingContext)
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
void nsWindow::EndDraw() void nsWindow::EndDraw()
{ {
if (! mDrawing) if (! mDrawing)
return; return;
mDrawing = PR_FALSE; mDrawing = PR_FALSE;
PRBool clipEmpty; if (mTempRenderingContextMadeHere)
mTempRenderingContext->PopState(clipEmpty); {
PRBool clipEmpty;
mTempRenderingContext->PopState(clipEmpty);
}
NS_RELEASE(mTempRenderingContext); NS_RELEASE(mTempRenderingContext);
} }
@ -644,62 +649,21 @@ NS_IMETHODIMP nsWindow::Update()
::SectRgn(mWindowPtr->visRgn, updateRgn, updateRgn); ::SectRgn(mWindowPtr->visRgn, updateRgn, updateRgn);
if (!::EmptyRgn(updateRgn)) if (!::EmptyRgn(updateRgn))
{ {
nsIRenderingContext* renderingContext = GetRenderingContext(); // this sets the origin nsIRenderingContext* renderingContext = GetRenderingContext();
if (renderingContext) if (renderingContext)
{ {
// initialize the paint event for that widget // determine the rect to draw
nsRect rect; nsRect rect;
#if 1 //GetBounds(rect);
GetBounds(rect); //rect.x = rect.y = 0;
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
Rect macRect = (*updateRgn)->rgnBBox; Rect macRect = (*updateRgn)->rgnBBox;
::OffsetRect(&macRect, -bounds.x, -bounds.y); ::OffsetRect(&macRect, -bounds.x, -bounds.y);
rect.x = macRect.left; rect.SetRect(macRect.left, macRect.top, macRect.right - macRect.left, macRect.bottom - macRect.top);
rect.y = macRect.top;
rect.width = macRect.right - macRect.left;
rect.height = macRect.bottom - macRect.top;
#endif
// nsEvent // update the widget
nsPaintEvent paintEvent; UpdateWidget(rect, renderingContext);
paintEvent.eventStructType = NS_PAINT_EVENT;
paintEvent.message = NS_PAINT;
paintEvent.point.x = 0;
paintEvent.point.y = 0;
paintEvent.time = PR_IntervalNow();
// nsGUIEvent NS_RELEASE(renderingContext);
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)
} }
} }
::DisposeRgn(updateRgn); ::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 // Scroll the bits of a window
@ -714,7 +727,44 @@ NS_IMETHODIMP nsWindow::Update()
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect) 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; return NS_OK;
} }

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

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