Bug 317375. Reorganize frame painting and mouse event targeting around frame display lists. Some review from dbaron, lots of testing help from Martijn, Julien and others

This commit is contained in:
roc+%cs.cmu.edu 2006-01-26 02:29:17 +00:00
Родитель b6f702b221
Коммит 5451e97878
174 изменённых файлов: 8094 добавлений и 7747 удалений

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

@ -1296,6 +1296,7 @@ GK_ATOM(IBSplitSpecialPrevSibling, "IBSplitSpecialPrevSibling")// nsIFrame*
GK_ATOM(IBSplitSpecialSibling, "IBSplitSpecialSibling") // nsIFrame*
GK_ATOM(lineCursorProperty, "LineCursorProperty") // nsLineBox*
GK_ATOM(maxElementWidthProperty, "MaxElementWidthProperty") // nscoord*
GK_ATOM(outOfFlowDirtyRectProperty, "OutOfFlowDirtyRectProperty") // nsRect*
GK_ATOM(overflowAreaProperty, "OverflowArea") // nsRect*
GK_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame*
GK_ATOM(overflowLinesProperty, "OverflowLinesProperty") // list of nsLineBox*

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

@ -71,8 +71,8 @@
#include "nsIScriptSecurityManager.h"
#include "nsIDocShell.h"
#include "nsPresContext.h"
#include "nsIViewManager.h"
#include "nsIScrollableView.h"
#include "nsIPresShell.h"
#include "nsIDOMWindow.h"
#include "nsPIDOMWindow.h"
#include "cairo.h"
@ -1882,12 +1882,6 @@ nsCanvasRenderingContext2D::DrawWindow(nsIDOMWindow* aWindow, PRInt32 aX, PRInt3
if (!presContext)
return NS_ERROR_FAILURE;
// Dig down past the viewport scroll stuff
nsIViewManager* vm = presContext->GetViewManager();
nsIView* view;
vm->GetRootView(view);
NS_ASSERTION(view, "Must have root view!");
nscolor bgColor;
nsresult rv = mCSSParser->ParseColorString(PromiseFlatString(aBGColor),
nsnull, 0, PR_TRUE, &bgColor);
@ -1896,11 +1890,13 @@ nsCanvasRenderingContext2D::DrawWindow(nsIDOMWindow* aWindow, PRInt32 aX, PRInt3
float p2t = presContext->PixelsToTwips();
nsRect r(aX, aY, aW, aH);
r.ScaleRoundOut(p2t);
nsIPresShell* presShell = presContext->PresShell();
nsCOMPtr<nsIRenderingContext> blackCtx;
rv = vm->RenderOffscreen(view, r, PR_FALSE, PR_TRUE,
NS_ComposeColors(NS_RGB(0, 0, 0), bgColor),
getter_AddRefs(blackCtx));
rv = presShell->RenderOffscreen(r, PR_FALSE, PR_TRUE,
NS_ComposeColors(NS_RGB(0, 0, 0), bgColor),
getter_AddRefs(blackCtx));
NS_ENSURE_SUCCESS(rv, rv);
nsIDrawingSurface* blackSurface;
@ -1921,9 +1917,9 @@ nsCanvasRenderingContext2D::DrawWindow(nsIDOMWindow* aWindow, PRInt32 aX, PRInt3
// But we need to compose our given background color onto black/white
// to get the real background to use.
nsCOMPtr<nsIRenderingContext> whiteCtx;
rv = vm->RenderOffscreen(view, r, PR_FALSE, PR_TRUE,
NS_ComposeColors(NS_RGB(255, 255, 255), bgColor),
getter_AddRefs(whiteCtx));
rv = presShell->RenderOffscreen(r, PR_FALSE, PR_TRUE,
NS_ComposeColors(NS_RGB(255, 255, 255), bgColor),
getter_AddRefs(whiteCtx));
if (NS_SUCCEEDED(rv)) {
nsIDrawingSurface* whiteSurface;
whiteCtx->GetDrawingSurface(&whiteSurface);

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

@ -326,6 +326,13 @@ public:
* @param aY The vertical translation
*/
NS_IMETHOD Translate(nscoord aX, nscoord aY) = 0;
/**
* Set the translation compoennt of the current transformation matrix.
* Useful to set it to a known pixel value without incurring roundoff
* errors.
*/
NS_IMETHOD SetTranslation(nscoord aX, nscoord aY) = 0;
/**
* Add in a scale to the RenderingContext's transformation matrix

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

@ -95,6 +95,9 @@ struct NS_GFX nsRect {
void SetRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight) {
x = aX; y = aY; width = aWidth; height = aHeight;
}
void SetRect(nsPoint aPt, nsSize aSize) {
SetRect(aPt.x, aPt.y, aSize.width, aSize.height);
}
void MoveTo(nscoord aX, nscoord aY) {x = aX; y = aY;}
void MoveTo(const nsPoint& aPoint) {x = aPoint.x; y = aPoint.y;}
void MoveBy(nscoord aDx, nscoord aDy) {x += aDx; y += aDy;}

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

@ -224,6 +224,7 @@ public:
void Transform(float *aX, float *aY, float *aWidth, float *aHeight) const;
void TransformCoord(nscoord *aX, nscoord *aY, nscoord *aWidth, nscoord *aHeight) const;
void TransformNoXLateCoord(nscoord *aX, nscoord *aY, nscoord *aWidth, nscoord *aHeight) const;
/**
* Scale an array of X/Y coordinates by the X/Y scale factor in the

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

@ -100,6 +100,7 @@ public:
NS_IMETHOD PushTranslation(PushedTranslation* aState);
NS_IMETHOD PopTranslation(PushedTranslation* aState);
NS_IMETHOD SetTranslation(nscoord aX, nscoord aY);
/**
* Let the device context know whether we want text reordered with

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

@ -285,6 +285,16 @@ void nsTransform2D :: TransformCoord(nscoord *aX, nscoord *aY, nscoord *aWidth,
*aHeight = y2 - *aY;
}
void nsTransform2D :: TransformNoXLateCoord(nscoord *aX, nscoord *aY, nscoord *aWidth, nscoord *aHeight) const
{
nscoord x2 = *aX + *aWidth;
nscoord y2 = *aY + *aHeight;
TransformNoXLateCoord(aX, aY);
TransformNoXLateCoord(&x2, &y2);
*aWidth = x2 - *aX;
*aHeight = y2 - *aY;
}
void nsTransform2D :: AddTranslation(float ptX, float ptY)
{
if (type == MG_2DIDENTITY)

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

@ -184,6 +184,14 @@ NS_IMETHODIMP nsRenderingContextImpl::PopTranslation(PushedTranslation* aState)
return NS_OK;
}
NS_IMETHODIMP nsRenderingContextImpl::SetTranslation(nscoord aX, nscoord aY)
{
nsTransform2D *theTransform;
GetCurrentTransform(theTransform);
NS_ASSERTION(theTransform != nsnull, "The rendering context transform is null");
theTransform->SetTranslation(aX, aY);
}
PRBool nsRenderingContextImpl::RectFitsInside(const nsRect& aRect, PRInt32 aWidth, PRInt32 aHeight) const
{
if (aRect.width > aWidth)
@ -300,15 +308,13 @@ NS_IMETHODIMP nsRenderingContextImpl::DrawImage(imgIContainer *aImage, const nsR
mTranMatrix->TransformCoord(&dr.x, &dr.y, &dr.width, &dr.height);
nsRect sr = aSrcRect;
mTranMatrix->TransformCoord(&sr.x, &sr.y, &sr.width, &sr.height);
// We should NOT be transforming the source rect (which is based on the image
// origin) using the rendering context's translation!
mTranMatrix->TransformNoXLateCoord(&sr.x, &sr.y, &sr.width, &sr.height);
if (sr.IsEmpty() || dr.IsEmpty())
return NS_OK;
sr.x = aSrcRect.x;
sr.y = aSrcRect.y;
mTranMatrix->TransformNoXLateCoord(&sr.x, &sr.y);
nsCOMPtr<gfxIImageFrame> iframe;
aImage->GetCurrentFrame(getter_AddRefs(iframe));
if (!iframe) return NS_ERROR_FAILURE;

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

@ -229,6 +229,16 @@ nsThebesRenderingContext::PopTranslation(PushedTranslation* aState)
return NS_OK;
}
NS_IMETHODIMP
nsThebesRenderingContext::SetTranslation(nscoord aX, nscoord aY)
{
gfxMatrix mat = mThebes->CurrentMatrix();
gfxFloat a, b, c, d, tx, ty;
mat->ToValues(&a, &b, &c, &d, &tx, &ty);
gfxMatrix newMat(a, b, c, d, aX, aY);
mThebes->SetMatrix(&newMat);
}
NS_IMETHODIMP
nsThebesRenderingContext::GetHints(PRUint32& aResult)
{

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

@ -203,6 +203,7 @@ public:
NS_IMETHOD PushTranslation(PushedTranslation* aState);
NS_IMETHOD PopTranslation(PushedTranslation* aState);
NS_IMETHOD SetTranslation(nscoord aX, nscoord aY);
#ifdef MOZ_MATHML
NS_IMETHOD GetBoundingMetrics(const char* aString, PRUint32 aLength, nsBoundingMetrics& aBoundingMetrics);

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

@ -119,6 +119,7 @@ CPPSRCS = \
nsCaret.cpp \
nsChildIterator.cpp \
nsCounterManager.cpp \
nsDisplayList.cpp \
nsDocumentViewer.cpp \
nsFrameContentIterator.cpp \
nsFrameManager.cpp \

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

@ -990,7 +990,7 @@ const nscolor kBlackColor = NS_RGB(0,0,0);
dashRect.x = borderOutside.x;
}
temp = borderOutside.YMost();
temp = borderOutside.height;
temp1 = temp/dashRect.height;
currRect = dashRect;
@ -1001,16 +1001,17 @@ const nscolor kBlackColor = NS_RGB(0,0,0);
FillOrInvertRect(aContext, dashRect.x, borderOutside.y,dashRect.width, dashRect.height-adjust,isInvert);
FillOrInvertRect(aContext,dashRect.x,(borderOutside.YMost()-(dashRect.height-adjust)),dashRect.width, dashRect.height-adjust,isInvert);
currRect.y += (dashRect.height-adjust);
temp = temp-= (dashRect.height-adjust);
temp-= (dashRect.height-adjust);
} else {
adjust = (temp%dashRect.width)/2; // adjust a tad longer
// draw in the left and right
FillOrInvertRect(aContext, dashRect.x, borderOutside.y,dashRect.width, dashRect.height+adjust,isInvert);
FillOrInvertRect(aContext, dashRect.x,(borderOutside.YMost()-(dashRect.height+adjust)),dashRect.width, dashRect.height+adjust,isInvert);
currRect.y += (dashRect.height+adjust);
temp = temp-= (dashRect.height+adjust);
temp-= (dashRect.height+adjust);
}
temp += borderOutside.y;
if( temp > ywidth)
temp = ywidth;
@ -1021,7 +1022,7 @@ const nscolor kBlackColor = NS_RGB(0,0,0);
if((temp1%2)==1){
bSolid = PR_TRUE;
}
}
}
while(currRect.y<temp) {
//draw if necessary
@ -1056,7 +1057,7 @@ const nscolor kBlackColor = NS_RGB(0,0,0);
dashRect.y = borderOutside.y;
}
temp = borderOutside.XMost();
temp = borderOutside.width;
temp1 = temp/dashRect.width;
currRect = dashRect;
@ -1067,17 +1068,17 @@ const nscolor kBlackColor = NS_RGB(0,0,0);
FillOrInvertRect(aContext, borderOutside.x,dashRect.y,dashRect.width-adjust,dashRect.height,isInvert);
FillOrInvertRect(aContext, (borderOutside.XMost()-(dashRect.width-adjust)),dashRect.y,dashRect.width-adjust,dashRect.height,isInvert);
currRect.x += (dashRect.width-adjust);
temp = temp-= (dashRect.width-adjust);
temp-= (dashRect.width-adjust);
} else {
adjust = (temp%dashRect.width)/2;
// draw in the left and right
FillOrInvertRect(aContext, borderOutside.x,dashRect.y,dashRect.width+adjust,dashRect.height,isInvert);
FillOrInvertRect(aContext, (borderOutside.XMost()-(dashRect.width+adjust)),dashRect.y,dashRect.width+adjust,dashRect.height,isInvert);
currRect.x += (dashRect.width+adjust);
temp = temp-= (dashRect.width+adjust);
temp-= (dashRect.width+adjust);
}
temp += borderOutside.x;
if( temp > xwidth)
temp = xwidth;
@ -2131,7 +2132,7 @@ nscoord width, offset;
// get the offset for our outline
aOutlineStyle.GetOutlineOffset(offset);
nsRect outside(*overflowArea);
nsRect outside(*overflowArea + aBorderArea.TopLeft());
nsRect inside(outside);
if (width + offset >= 0) {
// the overflow area is exactly the outside edge of the outline
@ -2804,6 +2805,30 @@ nsCSSRendering::PaintBackground(nsPresContext* aPresContext,
aBorder, aPadding, aUsePrintSettings, aBGClipRect);
}
/**
* Return the largest 'v' such that v = aTileOffset + N*aTileSize, for some
* integer N, and v <= aDirtyStart.
*/
static nscoord
FindTileStart(nscoord aDirtyStart, nscoord aTileOffset, nscoord aTileSize)
{
// Find largest integer N such that aTileOffset + N*aTileSize <= aDirtyStart
PRInt32 n = NSToIntFloor((aDirtyStart*1.0f - aTileOffset)/aTileSize);
return aTileOffset + n*aTileSize;
}
/**
* Return the smallest 'v' such that v = aTileOffset + N*aTileSize, for some
* integer N, and v >= aDirtyEnd.
*/
static nscoord
FindTileEnd(nscoord aDirtyEnd, nscoord aTileOffset, nscoord aTileSize)
{
// Find smallest integer N such that aTileOffset + N*aTileSize >= aDirtyEnd
PRInt32 n = NSToIntCeil((aDirtyEnd*1.0f - aTileOffset)/aTileSize);
return aTileOffset + n*aTileSize;
}
void
nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@ -2833,8 +2858,14 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
if (displayData->mAppearance) {
nsITheme *theme = aPresContext->GetTheme();
if (theme && theme->ThemeSupportsWidget(aPresContext, aForFrame, displayData->mAppearance)) {
nsPoint offset = aBorderArea.TopLeft();
nsIRenderingContext::AutoPushTranslation
translate(&aRenderingContext, offset.x, offset.y);
nsRect dirty;
nsRect border = aBorderArea - offset;
dirty.IntersectRect(aDirtyRect - offset, border);
theme->DrawWidgetBackground(&aRenderingContext, aForFrame,
displayData->mAppearance, aBorderArea, aDirtyRect);
displayData->mAppearance, border, dirty);
return;
}
}
@ -3002,6 +3033,7 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
// When tiling, the anchor coordinate values will be negative offsets
// from the background-origin area.
// relative to the origin of aForFrame
nsPoint anchor;
if (NS_STYLE_BG_ATTACHMENT_FIXED == aColor.mBackgroundAttachment) {
// If it's a fixed background attachment, then the image is placed
@ -3033,15 +3065,12 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
viewportArea.Deflate(scrollbars);
}
// Get the anchor point
// Get the anchor point, relative to rootFrame
ComputeBackgroundAnchorPoint(aColor, viewportArea, viewportArea, tileWidth, tileHeight, anchor);
// Convert the anchor point to aForFrame's coordinate space
nsPoint offset(0, 0);
nsIView* view = aForFrame->GetClosestView(&offset);
anchor -= offset;
NS_ASSERTION(view, "expected a view");
anchor -= view->GetOffsetTo(viewportView);
// Convert the anchor point from viewport coordinates (relative to aRootFrame) to
// relative to aForFrame
anchor -= aForFrame->GetOffsetTo(rootFrame);
} else {
if (frameType == nsLayoutAtoms::canvasFrame) {
// If the frame is the canvas, the image is placed relative to
@ -3062,7 +3091,8 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
firstRootElementFrameArea.Deflate(borderStyle->GetBorder());
// Get the anchor point
ComputeBackgroundAnchorPoint(aColor, firstRootElementFrameArea, bgClipArea, tileWidth, tileHeight, anchor);
ComputeBackgroundAnchorPoint(aColor, firstRootElementFrameArea +
aBorderArea.TopLeft(), bgClipArea, tileWidth, tileHeight, anchor);
} else {
ComputeBackgroundAnchorPoint(aColor, bgOriginArea, bgClipArea, tileWidth, tileHeight, anchor);
}
@ -3071,8 +3101,11 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
// simply placed relative to the frame's background-clip area
ComputeBackgroundAnchorPoint(aColor, bgOriginArea, bgClipArea, tileWidth, tileHeight, anchor);
}
}
// For scrolling attachment, the anchor is within the 'background-clip'
anchor.x += bgClipArea.x - aBorderArea.x;
anchor.y += bgClipArea.y - aBorderArea.y;
}
#if (!defined(XP_UNIX) && !defined(XP_BEOS)) || defined(XP_MACOSX)
// Setup clipping so that rendering doesn't leak out of the computed
@ -3181,52 +3214,33 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
*/
// first do the horizontal case
nscoord x0, x1;
// For scrolling attachment, the anchor is within the 'background-clip'
// For fixed attachment, the anchor is within the bounds of the nearest
// scrolling ancestor (or the viewport)
x0 = (NS_STYLE_BG_ATTACHMENT_SCROLL == aColor.mBackgroundAttachment) ?
bgClipArea.x : 0;
// relative to aBorderArea.TopLeft()
nsRect tileRect(anchor, nsSize(tileWidth, tileHeight));
if (repeat & NS_STYLE_BG_REPEAT_X) {
// When tiling in the x direction, adjust the starting position of the
// tile to account for dirtyRect.x. When tiling in x, the anchor.x value
// will be a negative value used to adjust the starting coordinate.
x0 += anchor.x +
((dirtyRect.x - (bgClipArea.x + anchor.x)) / tileWidth) * tileWidth;
x1 = x0 + ((dirtyRect.x + dirtyRect.width - x0 + tileWidth - 1) / tileWidth) * tileWidth;
nscoord x0 = FindTileStart(dirtyRect.x - aBorderArea.x, anchor.x, tileWidth);
nscoord x1 = FindTileEnd(dirtyRect.XMost() - aBorderArea.x, anchor.x, tileWidth);
tileRect.x = x0;
tileRect.width = x1 - x0;
}
else {
x0 += anchor.x;
x1 = x0 + tileWidth;
}
// now do all that again with the vertical case
nscoord y0, y1;
// For scrolling attachment, the anchor is within the 'background-clip'
// For fixed attachment, the anchor is within the bounds of the nearest
// scrolling ancestor (or the viewport)
y0 = (NS_STYLE_BG_ATTACHMENT_SCROLL == aColor.mBackgroundAttachment) ?
bgClipArea.y : 0;
if (repeat & NS_STYLE_BG_REPEAT_Y) {
// When tiling in the y direction, adjust the starting position of the
// tile to account for dirtyRect.y. When tiling in y, the anchor.y value
// will be a negative value used to adjust the starting coordinate.
y0 += anchor.y +
((dirtyRect.y - (bgClipArea.y + anchor.y)) / tileHeight) * tileHeight;
y1 = y0 + ((dirtyRect.y + dirtyRect.height - y0 + tileHeight - 1) / tileHeight) * tileHeight;
}
else {
y0 += anchor.y;
y1 = y0 + tileHeight;
nscoord y0 = FindTileStart(dirtyRect.y - aBorderArea.y, anchor.y, tileHeight);
nscoord y1 = FindTileEnd(dirtyRect.YMost() - aBorderArea.y, anchor.y, tileHeight);
tileRect.y = y0;
tileRect.height = y1 - y0;
}
// Take the intersection again to paint only the required area
nsRect tileRect(x0, y0, (x1 - x0), (y1 - y0));
nsRect absTileRect = tileRect + aBorderArea.TopLeft();
nsRect drawRect;
if (drawRect.IntersectRect(tileRect, dirtyRect))
aRenderingContext.DrawTile(image, x0, y0, &drawRect);
if (drawRect.IntersectRect(absTileRect, dirtyRect)) {
aRenderingContext.DrawTile(image, absTileRect.x, absTileRect.y, &drawRect);
}
#if (!defined(XP_UNIX) && !defined(XP_BEOS)) || defined(XP_MACOSX)
// Restore clipping
@ -3815,11 +3829,13 @@ RoundedRect::Set(nscoord aLeft,nscoord aTop,PRInt32 aWidth,PRInt32 aHeight,PRIn
nscoord x,y,width,height;
int i;
// convert this rect to pixel boundaries
x = (aLeft/aNumTwipPerPix)*aNumTwipPerPix;
y = (aTop/aNumTwipPerPix)*aNumTwipPerPix;
width = (aWidth/aNumTwipPerPix)*aNumTwipPerPix;
height = (aHeight/aNumTwipPerPix)*aNumTwipPerPix;
// Convert this rect to pixel boundaries. Preserve the same pixel centers.
// It's important that this preserve the same drawn-pixels as gfx's
// rounding.
x = NSToCoordRound((float)aLeft/aNumTwipPerPix)*aNumTwipPerPix;
y = NSToCoordRound((float)aTop/aNumTwipPerPix)*aNumTwipPerPix;
width = (NSToCoordRound((float)aLeft + aWidth)/aNumTwipPerPix)*aNumTwipPerPix - x;
height = (NSToCoordRound((float)aTop + aHeight)/aNumTwipPerPix)*aNumTwipPerPix - y;
for(i=0;i<4;i++) {

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

@ -110,12 +110,13 @@ public:
* an element. The nsStyleBackground should first be initialized
* using the pres context. This applies the rules for propagating
* backgrounds between BODY, the root element, and the canvas.
* @return PR_TRUE if there is some meaningful background.
*/
static PRBool FindBackground(nsPresContext* aPresContext,
nsIFrame* aForFrame,
const nsStyleBackground** aBackground,
PRBool* aIsCanvas);
/**
* Find a non-transparent background, for various table-related and
* HR-related backwards-compatibility hacks. Be very hesitant if

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

@ -0,0 +1,723 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Novell code.
*
* The Initial Developer of the Novell Code is Novell Corporation.
* Portions created by Novell are Copyright (C) 2005 Novell. All Rights Reserved.
*
* Contributor(s):
* robert@ocallahan.org
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK *****
*/
#include "nsDisplayList.h"
#include "nsCSSRendering.h"
#include "nsISelectionController.h"
#include "nsIPresShell.h"
#include "nsRegion.h"
#include "nsIViewManager.h"
#include "nsIBlender.h"
#include "nsTransform2D.h"
nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
PRBool aIsForEvents, nsIFrame* aMovingFrame)
: mReferenceFrame(aReferenceFrame),
mMovingFrame(aMovingFrame),
mIgnoreScrollFrame(nsnull),
mEventDelivery(aIsForEvents),
mIsAtRootOfPseudoStackingContext(PR_FALSE) {
PL_InitArenaPool(&mPool, "displayListArena", 1024, sizeof(void*)-1);
nsPresContext* pc = aReferenceFrame->GetPresContext();
nsIPresShell *shell = pc->PresShell();
PRBool suppressed;
shell->IsPaintingSuppressed(&suppressed);
mIsBackgroundOnly = suppressed;
if (pc->IsRenderingOnlySelection()) {
nsCOMPtr<nsISelectionController> selcon(do_QueryInterface(shell));
if (selcon) {
selcon->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(mBoundingSelection));
}
}
}
nsDisplayListBuilder::~nsDisplayListBuilder() {
PL_FreeArenaPool(&mPool);
PL_FinishArenaPool(&mPool);
}
void*
nsDisplayListBuilder::Allocate(size_t aSize) {
void *tmp;
PL_ARENA_ALLOCATE(tmp, &mPool, aSize);
return tmp;
}
void nsDisplayListSet::MoveTo(const nsDisplayListSet& aDestination) const
{
aDestination.BorderBackground()->AppendToTop(BorderBackground());
aDestination.BlockBorderBackgrounds()->AppendToTop(BlockBorderBackgrounds());
aDestination.Floats()->AppendToTop(Floats());
aDestination.Content()->AppendToTop(Content());
aDestination.PositionedDescendants()->AppendToTop(PositionedDescendants());
aDestination.Outlines()->AppendToTop(Outlines());
}
// Suitable for leaf items only, overridden by nsDisplayWrapList
PRBool
nsDisplayItem::OptimizeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
nsRect bounds = GetBounds(aBuilder);
if (!aVisibleRegion->Intersects(bounds))
return PR_FALSE;
nsIFrame* f = GetUnderlyingFrame();
NS_ASSERTION(f, "GetUnderlyingFrame() must return non-null for leaf items");
if (aBuilder->HasMovingFrames() && aBuilder->IsMovingFrame(f)) {
// If this frame is in the moving subtree, and it doesn't
// require repainting just because it's moved, then just remove it now
// because it's not relevant.
if (!IsVaryingRelativeToFrame(aBuilder, aBuilder->GetRootMovingFrame()))
return PR_FALSE;
// keep it, but don't let it cover other display items (see nsLayoutUtils::
// ComputeRepaintRegionForCopy)
return PR_TRUE;
}
if (IsOpaque(aBuilder)) {
aVisibleRegion->SimpleSubtract(bounds);
}
return PR_TRUE;
}
void
nsDisplayList::FlattenTo(nsVoidArray* aElements) {
nsDisplayItem* item;
while ((item = RemoveBottom()) != nsnull) {
if (item->GetType() == nsDisplayItem::TYPE_WRAPLIST) {
item->GetList()->FlattenTo(aElements);
item->nsDisplayItem::~nsDisplayItem();
} else {
aElements->AppendElement(item);
}
}
}
void
nsDisplayList::OptimizeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
nsVoidArray elements;
FlattenTo(&elements);
for (PRInt32 i = elements.Count() - 1; i >= 0; --i) {
nsDisplayItem* item = NS_STATIC_CAST(nsDisplayItem*, elements.ElementAt(i));
nsDisplayItem* belowItem = i < 1 ? nsnull :
NS_STATIC_CAST(nsDisplayItem*, elements.ElementAt(i - 1));
if (belowItem && item->TryMerge(aBuilder, belowItem)) {
belowItem->nsDisplayItem::~nsDisplayItem();
elements.ReplaceElementAt(item, i - 1);
continue;
}
if (item->OptimizeVisibility(aBuilder, aVisibleRegion)) {
AppendToBottom(item);
} else {
item->nsDisplayItem::~nsDisplayItem();
}
}
}
void nsDisplayList::Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect) const {
for (nsDisplayItem* i = GetBottom(); i != nsnull; i = i->GetAbove()) {
i->Paint(aBuilder, aCtx, aDirtyRect);
}
}
PRUint32 nsDisplayList::Count() const {
PRUint32 count = 0;
for (nsDisplayItem* i = GetBottom(); i; i = i->GetAbove()) {
++count;
}
return count;
}
nsDisplayItem* nsDisplayList::RemoveBottom() {
nsDisplayItem* item = mSentinel.mAbove;
if (!item)
return nsnull;
mSentinel.mAbove = item->mAbove;
if (item == mTop) {
// must have been the only item
mTop = &mSentinel;
}
item->mAbove = nsnull;
return item;
}
void nsDisplayList::DeleteBottom() {
nsDisplayItem* item = RemoveBottom();
if (item) {
item->nsDisplayItem::~nsDisplayItem();
}
}
void nsDisplayList::DeleteAll() {
nsDisplayItem* item;
while ((item = RemoveBottom()) != nsnull) {
item->nsDisplayItem::~nsDisplayItem();
}
}
nsIFrame* nsDisplayList::HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt) const {
nsVoidArray elements;
nsDisplayItem* item;
for (item = GetBottom(); item; item = item->GetAbove()) {
elements.AppendElement(item);
}
for (PRInt32 i = elements.Count() - 1; i >= 0; --i) {
item = NS_STATIC_CAST(nsDisplayItem*, elements.ElementAt(i));
if (item->GetBounds(aBuilder).Contains(aPt)) {
nsIFrame* f = item->HitTest(aBuilder, aPt);
// Handle the XUL 'mousethrough' feature.
if (f) {
PRBool mouseThrough = PR_FALSE;
f->GetMouseThrough(mouseThrough);
if (!mouseThrough)
return f;
}
}
}
return nsnull;
}
typedef PRBool (* SortLEQ)(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
void* aClosure);
static void Sort(nsDisplayList* aList, PRInt32 aCount, SortLEQ aCmp, void* aClosure) {
if (aCount < 2)
return;
nsDisplayList list1;
nsDisplayList list2;
int i;
PRInt32 half = aCount/2;
PRBool sorted = PR_TRUE;
nsDisplayItem* prev = nsnull;
for (i = 0; i < aCount; ++i) {
nsDisplayItem* item = aList->RemoveBottom();
(i < half ? &list1 : &list2)->AppendToTop(item);
if (sorted && prev && !aCmp(prev, item, aClosure)) {
sorted = PR_FALSE;
}
prev = item;
}
if (sorted) {
aList->AppendToTop(&list1);
aList->AppendToTop(&list2);
return;
}
Sort(&list1, half, aCmp, aClosure);
Sort(&list2, aCount - half, aCmp, aClosure);
for (i = 0; i < aCount; ++i) {
if (list1.GetBottom() &&
(!list2.GetBottom() ||
aCmp(list1.GetBottom(), list2.GetBottom(), aClosure))) {
aList->AppendToTop(list1.RemoveBottom());
} else {
aList->AppendToTop(list2.RemoveBottom());
}
}
}
static PRBool IsContentLEQ(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
void* aClosure) {
// These GetUnderlyingFrame calls return non-null because we're only used
// in sorting
return nsLayoutUtils::CompareTreePosition(
aItem1->GetUnderlyingFrame()->GetContent(),
aItem2->GetUnderlyingFrame()->GetContent(),
NS_STATIC_CAST(nsIContent*, aClosure)) <= 0;
}
static PRBool IsZOrderLEQ(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
void* aClosure) {
// These GetUnderlyingFrame calls return non-null because we're only used
// in sorting
PRInt32 diff = nsLayoutUtils::GetZIndex(aItem1->GetUnderlyingFrame()) -
nsLayoutUtils::GetZIndex(aItem2->GetUnderlyingFrame());
if (diff == 0)
return IsContentLEQ(aItem1, aItem2, aClosure);
return diff < 0;
}
void nsDisplayList::ExplodeAnonymousChildLists(nsDisplayListBuilder* aBuilder) {
// See if there's anything to do
PRBool anyAnonymousItems = PR_FALSE;
nsDisplayItem* i;
for (i = GetBottom(); i != nsnull; i = i->GetAbove()) {
if (!i->GetUnderlyingFrame()) {
anyAnonymousItems = PR_TRUE;
break;
}
}
if (!anyAnonymousItems)
return;
nsDisplayList tmp;
while ((i = RemoveBottom()) != nsnull) {
if (i->GetUnderlyingFrame()) {
tmp.AppendToTop(i);
} else {
nsDisplayList* list = i->GetList();
NS_ASSERTION(list, "leaf items can't be anonymous");
list->ExplodeAnonymousChildLists(aBuilder);
nsDisplayItem* j;
while ((j = list->RemoveBottom()) != nsnull) {
tmp.AppendToTop(NS_STATIC_CAST(nsDisplayWrapList*, i)->
WrapWithClone(aBuilder, j));
}
i->nsDisplayItem::~nsDisplayItem();
}
}
AppendToTop(&tmp);
}
void nsDisplayList::SortByZOrder(nsDisplayListBuilder* aBuilder,
nsIContent* aCommonAncestor) {
ExplodeAnonymousChildLists(aBuilder);
Sort(this, Count(), IsZOrderLEQ, aCommonAncestor);
}
void nsDisplayList::SortByContentOrder(nsDisplayListBuilder* aBuilder,
nsIContent* aCommonAncestor) {
ExplodeAnonymousChildLists(aBuilder);
Sort(this, Count(), IsContentLEQ, aCommonAncestor);
}
static PRBool
NonZeroStyleCoord(const nsStyleCoord& aCoord) {
switch (aCoord.GetUnit()) {
case eStyleUnit_Percent:
return aCoord.GetPercentValue() > 0;
case eStyleUnit_Coord:
return aCoord.GetCoordValue() > 0;
case eStyleUnit_Null:
return PR_FALSE;
default:
return PR_TRUE;
}
}
static PRBool
HasNonZeroBorderRadius(const nsStyleBorder* aBorder) {
nsStyleCoord coord;
aBorder->mBorderRadius.GetTop(coord);
if (NonZeroStyleCoord(coord)) return PR_TRUE;
aBorder->mBorderRadius.GetRight(coord);
if (NonZeroStyleCoord(coord)) return PR_TRUE;
aBorder->mBorderRadius.GetBottom(coord);
if (NonZeroStyleCoord(coord)) return PR_TRUE;
aBorder->mBorderRadius.GetLeft(coord);
if (NonZeroStyleCoord(coord)) return PR_TRUE;
return PR_FALSE;
}
PRBool
nsDisplayBackground::IsOpaque(nsDisplayListBuilder* aBuilder) {
// theme background overrides any other background
if (mFrame->IsThemed())
return PR_FALSE;
PRBool isCanvas;
const nsStyleBackground* bg;
PRBool hasBG =
nsCSSRendering::FindBackground(mFrame->GetPresContext(), mFrame, &bg, &isCanvas);
if (!hasBG || (bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) ||
bg->mBackgroundClip != NS_STYLE_BG_CLIP_BORDER ||
HasNonZeroBorderRadius(mFrame->GetStyleBorder()) ||
NS_GET_A(bg->mBackgroundColor) < 255)
return PR_FALSE;
return PR_TRUE;
}
PRBool
nsDisplayBackground::IsUniform(nsDisplayListBuilder* aBuilder) {
// theme background overrides any other background
if (mFrame->IsThemed())
return PR_FALSE;
PRBool isCanvas;
const nsStyleBackground* bg;
PRBool hasBG =
nsCSSRendering::FindBackground(mFrame->GetPresContext(), mFrame, &bg, &isCanvas);
if (!hasBG)
return PR_TRUE;
if ((bg->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE) &&
!HasNonZeroBorderRadius(mFrame->GetStyleBorder()) &&
bg->mBackgroundClip == NS_STYLE_BG_CLIP_BORDER)
return PR_TRUE;
return PR_FALSE;
}
PRBool
nsDisplayBackground::IsVaryingRelativeToFrame(nsDisplayListBuilder* aBuilder,
nsIFrame* aAncestorFrame)
{
PRBool isCanvas;
const nsStyleBackground* bg;
PRBool hasBG =
nsCSSRendering::FindBackground(mFrame->GetPresContext(), mFrame, &bg, &isCanvas);
if (!hasBG)
return PR_FALSE;
if (!bg->HasFixedBackground())
return PR_FALSE;
// aAncestorFrame is an ancestor of this frame ... if it's in our document
// then we'll be moving relative to the viewport, so we will change our
// display. If it's in some ancestor document then we won't be moving
// relative to the viewport so we won't change our display.
for (nsIFrame* f = mFrame->GetParent(); f; f = f->GetParent()) {
if (f == aAncestorFrame)
return PR_TRUE;
}
return PR_FALSE;
}
void
nsDisplayBackground::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect) {
nsPoint offset = aBuilder->ToReferenceFrame(mFrame);
nsCSSRendering::PaintBackground(mFrame->GetPresContext(), *aCtx, mFrame,
aDirtyRect, nsRect(offset, mFrame->GetSize()),
*mFrame->GetStyleBorder(),
*mFrame->GetStylePadding(),
mFrame->HonorPrintBackgroundSettings());
}
nsRect
nsDisplayOutline::GetBounds(nsDisplayListBuilder* aBuilder) {
return mFrame->GetOverflowRect() + aBuilder->ToReferenceFrame(mFrame);
}
void
nsDisplayOutline::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect) {
// TODO join outlines together
nsPoint offset = aBuilder->ToReferenceFrame(mFrame);
nsCSSRendering::PaintOutline(mFrame->GetPresContext(), *aCtx, mFrame,
aDirtyRect, nsRect(offset, mFrame->GetSize()),
*mFrame->GetStyleBorder(),
*mFrame->GetStyleOutline(),
mFrame->GetStyleContext(), 0);
}
void
nsDisplayBorder::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect) {
nsPoint offset = aBuilder->ToReferenceFrame(mFrame);
nsCSSRendering::PaintBorder(mFrame->GetPresContext(), *aCtx, mFrame,
aDirtyRect, nsRect(offset, mFrame->GetSize()),
*mFrame->GetStyleBorder(),
mFrame->GetStyleContext(), mFrame->GetSkipSides());
}
nsDisplayWrapList::nsDisplayWrapList(nsIFrame* aFrame, nsDisplayList* aList)
: mFrame(aFrame) {
mList.AppendToTop(aList);
}
nsDisplayWrapList::nsDisplayWrapList(nsIFrame* aFrame, nsDisplayItem* aItem)
: mFrame(aFrame) {
mList.AppendToTop(aItem);
}
nsDisplayWrapList::~nsDisplayWrapList() {
mList.DeleteAll();
}
nsIFrame*
nsDisplayWrapList::HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt) {
return mList.HitTest(aBuilder, aPt);
}
nsRect
nsDisplayWrapList::GetBounds(nsDisplayListBuilder* aBuilder) {
nsRect bounds;
for (nsDisplayItem* i = mList.GetBottom(); i != nsnull; i = i->GetAbove()) {
bounds.UnionRect(bounds, i->GetBounds(aBuilder));
}
return bounds;
}
PRBool
nsDisplayWrapList::OptimizeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
mList.OptimizeVisibility(aBuilder, aVisibleRegion);
// If none of the items are visible, they will all have been deleted
return mList.GetTop() != nsnull;
}
PRBool
nsDisplayWrapList::IsOpaque(nsDisplayListBuilder* aBuilder) {
// We could try to do something but let's conservatively just return PR_FALSE.
// We reimplement OptimizeVisibility and that's what really matters
return PR_FALSE;
}
PRBool nsDisplayWrapList::IsUniform(nsDisplayListBuilder* aBuilder) {
// We could try to do something but let's conservatively just return PR_FALSE.
return PR_FALSE;
}
PRBool nsDisplayWrapList::IsVaryingRelativeToFrame(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame) {
for (nsDisplayItem* i = mList.GetBottom(); i != nsnull; i = i->GetAbove()) {
if (i->IsVaryingRelativeToFrame(aBuilder, aFrame))
return PR_TRUE;
}
return PR_FALSE;
}
void nsDisplayWrapList::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect) {
mList.Paint(aBuilder, aCtx, aDirtyRect);
}
static nsresult
WrapDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, nsDisplayWrapper* aWrapper) {
if (!aList->GetTop())
return NS_OK;
nsDisplayItem* item = aWrapper->WrapList(aBuilder, aFrame, aList);
if (!item)
return NS_ERROR_OUT_OF_MEMORY;
// aList was emptied
aList->AppendToTop(item);
return NS_OK;
}
static nsresult
WrapEachDisplayItem(nsDisplayListBuilder* aBuilder,
nsDisplayList* aList, nsDisplayWrapper* aWrapper) {
nsDisplayList newList;
nsDisplayItem* item;
while ((item = aList->RemoveBottom())) {
item = aWrapper->WrapItem(aBuilder, item);
if (!item)
return NS_ERROR_OUT_OF_MEMORY;
newList.AppendToTop(item);
}
// aList was emptied
aList->AppendToTop(&newList);
return NS_OK;
}
nsresult nsDisplayWrapper::WrapLists(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, const nsDisplayListSet& aIn, const nsDisplayListSet& aOut)
{
nsresult rv = WrapListsInPlace(aBuilder, aFrame, aIn);
NS_ENSURE_SUCCESS(rv, rv);
if (&aOut == &aIn)
return NS_OK;
aOut.BorderBackground()->AppendToTop(aIn.BorderBackground());
aOut.BlockBorderBackgrounds()->AppendToTop(aIn.BlockBorderBackgrounds());
aOut.Floats()->AppendToTop(aIn.Floats());
aOut.Content()->AppendToTop(aIn.Content());
aOut.PositionedDescendants()->AppendToTop(aIn.PositionedDescendants());
aOut.Outlines()->AppendToTop(aIn.Outlines());
return NS_OK;
}
nsresult nsDisplayWrapper::WrapListsInPlace(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, const nsDisplayListSet& aLists)
{
nsresult rv;
if (WrapBorderBackground()) {
// Our border-backgrounds are in-flow
rv = WrapDisplayList(aBuilder, aFrame, aLists.BorderBackground(), this);
NS_ENSURE_SUCCESS(rv, rv);
}
// Our block border-backgrounds are in-flow
rv = WrapDisplayList(aBuilder, aFrame, aLists.BlockBorderBackgrounds(), this);
NS_ENSURE_SUCCESS(rv, rv);
// The floats are not in flow
rv = WrapEachDisplayItem(aBuilder, aLists.Floats(), this);
NS_ENSURE_SUCCESS(rv, rv);
// Our child content is in flow
rv = WrapDisplayList(aBuilder, aFrame, aLists.Content(), this);
NS_ENSURE_SUCCESS(rv, rv);
// The positioned descendants may not be in-flow
rv = WrapEachDisplayItem(aBuilder, aLists.PositionedDescendants(), this);
NS_ENSURE_SUCCESS(rv, rv);
// The outlines may not be in-flow
return WrapEachDisplayItem(aBuilder, aLists.Outlines(), this);
}
nsDisplayOpacity::nsDisplayOpacity(nsIFrame* aFrame, nsDisplayList* aList)
: nsDisplayWrapList(aFrame, aList), mNeedAlpha(PR_TRUE) {
}
PRBool nsDisplayOpacity::IsOpaque(nsDisplayListBuilder* aBuilder) {
// We are never opaque, if our opacity was < 1 then we wouldn't have
// been created.
return PR_FALSE;
}
void nsDisplayOpacity::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
{
// XXX This way of handling 'opacity' creates exponential time blowup in the
// depth of nested translucent elements. This will be fixed when we move to
// cairo with support for real alpha channels in surfaces, so we don't have
// to do this white/black hack anymore.
nsIViewManager* vm = mFrame->GetPresContext()->GetViewManager();
nsRect bounds;
bounds.IntersectRect(GetBounds(aBuilder), aDirtyRect);
nsIViewManager::BlendingBuffers* buffers =
vm->CreateBlendingBuffers(aCtx, PR_FALSE, nsnull, mNeedAlpha, bounds);
if (!buffers) {
NS_WARNING("Could not create blending buffers for translucent painting; ignoring opacity");
nsDisplayWrapList::Paint(aBuilder, aCtx, aDirtyRect);
return;
}
// Paint onto black, and also onto white if necessary
nsDisplayWrapList::Paint(aBuilder, buffers->mBlackCX, bounds);
if (buffers->mWhiteCX) {
nsDisplayWrapList::Paint(aBuilder, buffers->mWhiteCX, bounds);
}
nsTransform2D* transform;
nsresult rv = aCtx->GetCurrentTransform(transform);
if (NS_FAILED(rv))
return;
nsRect damageRectInPixels = bounds;
transform->TransformCoord(&damageRectInPixels.x, &damageRectInPixels.y,
&damageRectInPixels.width, &damageRectInPixels.height);
// If blender creation failed then we would have not received a buffers object
nsIBlender* blender = vm->GetBlender();
blender->Blend(0, 0, damageRectInPixels.width, damageRectInPixels.height,
buffers->mBlackCX, aCtx,
damageRectInPixels.x, damageRectInPixels.y,
mFrame->GetStyleDisplay()->mOpacity, buffers->mWhiteCX,
NS_RGB(0, 0, 0), NS_RGB(255, 255, 255));
delete buffers;
}
PRBool nsDisplayOpacity::OptimizeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
// Our children are translucent so we should not allow them to subtract
// area from aVisibleRegion. We do need to find out what is visible under
// our children in the temporary compositing buffer, because if our children
// paint our entire bounds opaquely then we don't need an alpha channel in
// the temporary compositing buffer.
nsRegion visibleUnderChildren = *aVisibleRegion;
PRBool anyVisibleChildren =
nsDisplayWrapList::OptimizeVisibility(aBuilder, &visibleUnderChildren);
if (!anyVisibleChildren)
return PR_FALSE;
mNeedAlpha = visibleUnderChildren.Intersects(GetBounds(aBuilder));
return PR_TRUE;
}
PRBool nsDisplayOpacity::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
if (aItem->GetType() != TYPE_OPACITY)
return PR_FALSE;
// items for the same content element should be merged into a single
// compositing group
// aItem->GetUnderlyingFrame() returns non-null because it's nsDisplayOpacity
if (aItem->GetUnderlyingFrame()->GetContent() != mFrame->GetContent())
return PR_FALSE;
mList.AppendToBottom(&NS_STATIC_CAST(nsDisplayOpacity*, aItem)->mList);
return PR_TRUE;
}
nsDisplayClip::nsDisplayClip(nsIFrame* aFrame, nsDisplayItem* aItem,
const nsRect& aRect)
: nsDisplayWrapList(aFrame, aItem), mClip(aRect) {
}
nsDisplayClip::nsDisplayClip(nsIFrame* aFrame, nsDisplayList* aList,
const nsRect& aRect)
: nsDisplayWrapList(aFrame, aList), mClip(aRect) {
}
nsRect nsDisplayClip::GetBounds(nsDisplayListBuilder* aBuilder) {
nsRect r = nsDisplayWrapList::GetBounds(aBuilder);
r.IntersectRect(mClip, r);
return r;
}
void nsDisplayClip::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect) {
nsRect dirty;
dirty.IntersectRect(mClip, aDirtyRect);
aCtx->PushState();
aCtx->SetClipRect(dirty, nsClipCombine_kIntersect);
nsDisplayWrapList::Paint(aBuilder, aCtx, dirty);
aCtx->PopState();
}
PRBool nsDisplayClip::OptimizeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
nsRegion clipped;
clipped.And(*aVisibleRegion, mClip);
nsRegion rNew(clipped);
PRBool anyVisible = nsDisplayWrapList::OptimizeVisibility(aBuilder, &rNew);
nsRegion subtracted;
subtracted.Sub(clipped, rNew);
aVisibleRegion->SimpleSubtract(subtracted);
return anyVisible;
}
PRBool nsDisplayClip::TryMerge(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem) {
if (aItem->GetType() != TYPE_CLIP)
return PR_FALSE;
nsDisplayClip* other = NS_STATIC_CAST(nsDisplayClip*, aItem);
if (other->mClip != mClip)
return PR_FALSE;
mList.AppendToBottom(&other->mList);
return PR_TRUE;
}
nsDisplayWrapList* nsDisplayClip::WrapWithClone(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem) {
return new (aBuilder) nsDisplayClip(aItem->GetUnderlyingFrame(), aItem, mClip);
}

895
layout/base/nsDisplayList.h Normal file
Просмотреть файл

@ -0,0 +1,895 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Novell code.
*
* The Initial Developer of the Novell Code is Novell Corporation.
* Portions created by Novell are Copyright (C) 2005 Novell. All Rights Reserved.
*
* Contributor(s):
* robert@ocallahan.org
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK *****
*/
#ifndef NSDISPLAYLIST_H_
#define NSDISPLAYLIST_H_
#include "nsCOMPtr.h"
#include "nsIFrame.h"
#include "nsPoint.h"
#include "nsRect.h"
#include "nsISelection.h"
#include "plarena.h"
#include "nsLayoutUtils.h"
#include <stdlib.h>
class nsIPresShell;
class nsIContent;
class nsRegion;
class nsIRenderingContext;
class nsIDeviceContext;
/*
* An nsIFrame can have many different visual parts. For example an image frame
* can have a background, border, and outline, the image itself, and a
* translucent selection overlay. In general these parts can be drawn at
* discontiguous z-levels; see CSS2.1 appendix E:
* http://www.w3.org/TR/CSS21/zindex.html
*
* We construct a display list for a frame tree that contains one item
* for each visual part. The display list is itself a tree since some items
* are containers for other items; however, its structure does not match
* the structure of its source frame tree. The display list items are sorted
* by z-order. A display list can be used to paint the frames, to determine
* which frame is the target of a mouse event, and to determine what areas
* need to be repainted when scrolling. The display lists built for each task
* may be different for efficiency; in particular some frames need special
* display list items only for event handling, and do not create these items
* when the display list will be used for painting (the common case). For
* example, when painting we avoid creating nsDisplayBackground items for
* frames that don't display a visible background, but for event handling
* we need those backgrounds because they are not transparent to events.
*
* We could avoid constructing an explicit display list by traversing the
* frame tree multiple times in clever ways. However, reifying the display list
* reduces code complexity and reduces the number of times each frame must be
* traversed to one, which seems to be good for performance. It also means
* we can share code for painting, event handling and scroll analysis.
*
* Display lists are short-lived; content and frame trees cannot change
* between a display list being created and destroyed. Display lists should
* not be created during reflow because the frame tree may be in an
* inconsistent state (e.g., a frame's stored overflow-area may not include
* the bounds of all its children). However, it should be fine to create
* a display list while a reflow is pending, before it starts.
*
* A display list covers the "extended" frame tree; the display list for a frame
* tree containing FRAME/IFRAME elements can include frames from the subdocuments.
*/
#ifdef NS_DEBUG
#define NS_DISPLAY_DECL_NAME(n) virtual const char* Name() { return n; }
#else
#define NS_DISPLAY_DECL_NAME(n)
#endif
/**
* This manages a display list and is passed as a parameter to
* nsIFrame::BuildDisplayList.
* It contains the parameters that don't change from frame to frame and manages
* the display list memory using a PLArena. It also establishes the reference
* coordinate system for all display list items. Some of the parameters are
* available from the prescontext/presshell, but we copy them into the builder
* for faster/more convenient access.
*/
class nsDisplayListBuilder {
public:
/**
* @param aReferenceFrame the frame at the root of the subtree; its origin
* is the origin of the reference coordinate system for this display list
* @param aIsForEvents PR_TRUE if we're creating this list in order to
* determine which frame is under the mouse position
* @param aMovingFrame a frame whose subtree should be regarded as
* moving; moving frames are not allowed to clip or cover (during
* OptimizeVisibility) non-moving frames. E.g. when we're constructing
* a display list to see what should be repainted during a scroll
* operation, we specify the scrolled frame as the moving frame.
*/
nsDisplayListBuilder(nsIFrame* aReferenceFrame, PRBool aIsForEvents,
nsIFrame* aMovingFrame = nsnull);
~nsDisplayListBuilder();
/**
* @return PR_TRUE if the display is being built in order to determine which
* frame is under the mouse position.
*/
PRBool IsForEventDelivery() { return mEventDelivery; }
/**
* @return PR_TRUE if "painting is suppressed" during page load and we
* should paint only the background of the document.
*/
PRBool IsBackgroundOnly() { return mIsBackgroundOnly; }
/**
* @return PR_TRUE if the currently active BuildDisplayList call is being
* applied to a frame at the root of a pseudo stacking context. A psuedo
* stacking context is either a real stacking context or basically what
* CSS2.1 appendix E refers to with "treat the element as if it created
* a new stacking context
*/
PRBool IsAtRootOfPseudoStackingContext() { return mIsAtRootOfPseudoStackingContext; }
/**
* @return PR_TRUE if we are doing analysis of moving frames
*/
PRBool HasMovingFrames() { return mMovingFrame != nsnull; }
/**
* @return the frame that is being hypothetically moved
*/
nsIFrame* GetRootMovingFrame() { return mMovingFrame; }
/**
* @return PR_TRUE if aFrame is, or is a descendant of, the hypothetical
* moving frame
*/
PRBool IsMovingFrame(nsIFrame* aFrame) {
return aFrame == mMovingFrame || (mMovingFrame &&
nsLayoutUtils::IsProperAncestorFrameCrossDoc(mMovingFrame, aFrame, mReferenceFrame));
}
/**
* @return the selection that painting should be restricted to (or nsnull
* in the normal unrestricted case)
*/
nsISelection* GetBoundingSelection() { return mBoundingSelection; }
/**
* @return the root of the display list's frame (sub)tree, whose origin
* establishes the coordinate system for the display list
*/
nsIFrame* ReferenceFrame() { return mReferenceFrame; }
/**
* @return a point pt such that adding pt to a coordinate relative to aFrame
* makes it relative to ReferenceFrame(), i.e., returns
* aFrame->GetOffsetTo(ReferenceFrame()). It may be optimized to be faster
* than aFrame->GetOffsetTo(ReferenceFrame()) (but currently isn't).
*/
nsPoint ToReferenceFrame(nsIFrame* aFrame) {
return aFrame->GetOffsetTo(ReferenceFrame());
}
/**
* When building the display list, the scrollframe aFrame will be "ignored"
* for the purposes of clipping, and its scrollbars will be hidden. We use
* this to allow RenderOffscreen to render a whole document without beign
* clipped by the viewport or drawing the viewport scrollbars.
*/
void SetIgnoreScrollFrame(nsIFrame* aFrame) { mIgnoreScrollFrame = aFrame; }
/**
* Get the scrollframe to ignore, if any.
*/
nsIFrame* GetIgnoreScrollFrame() { return mIgnoreScrollFrame; }
/**
* Allocate memory in our arena. It will only be freed when this display list
* builder is destroyed. This memory holds nsDisplayItems. nsDisplayItem
* destructors are called as soon as the item is no longer used.
*/
void* Allocate(size_t aSize);
/**
* A helper class to temporarily set the value of
* mIsAtRootOfPseudoStackingContext.
*/
class AutoIsRootSetter;
friend class nsAutoIsRootSetter;
class AutoIsRootSetter {
public:
AutoIsRootSetter(nsDisplayListBuilder* aBuilder, PRBool aIsRoot)
: mBuilder(aBuilder), mOldValue(aBuilder->mIsAtRootOfPseudoStackingContext) {
aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot;
}
~AutoIsRootSetter() {
mBuilder->mIsAtRootOfPseudoStackingContext = mOldValue;
}
private:
nsDisplayListBuilder* mBuilder;
PRPackedBool mOldValue;
};
private:
nsIFrame* mReferenceFrame;
nsIFrame* mMovingFrame;
nsIFrame* mIgnoreScrollFrame;
PLArenaPool mPool;
nsCOMPtr<nsISelection> mBoundingSelection;
PRPackedBool mEventDelivery;
PRPackedBool mIsBackgroundOnly;
PRPackedBool mIsAtRootOfPseudoStackingContext;
};
class nsDisplayItem;
class nsDisplayList;
/**
* nsDisplayItems are put in singly-linked lists rooted in an nsDisplayList.
* nsDisplayItemLink holds the link. The lists are linked from lowest to
* highest in z-order.
*/
class nsDisplayItemLink {
protected:
nsDisplayItem* mAbove;
friend class nsDisplayList;
};
/**
* This is the unit of rendering and event testing. Each instance of this
* class represents an entity that can be drawn on the screen, e.g., a
* frame's CSS background, or a frame's text string.
*
* nsDisplayListItems can be containers --- i.e., they can perform hit testing
* and painting by recursively traversing a list of child items.
*
* These are arena-allocated during display list construction. A typical
* subclass would just have a frame pointer, so its object would be just three
* pointers (vtable, next-item, frame).
*
* Display items belong to a list at all times (except temporarily as they
* move from one list to another).
*/
class nsDisplayItem : public nsDisplayItemLink {
public:
virtual ~nsDisplayItem() {}
void* operator new(size_t aSize, nsDisplayListBuilder* aBuilder) {
return aBuilder->Allocate(aSize);
}
/**
* It's useful to be able to dynamically check the type of certain items.
* For items whose type never gets checked, TYPE_GENERIC will suffice.
*/
enum Type {
TYPE_GENERIC,
TYPE_OUTLINE,
TYPE_CLIP,
TYPE_OPACITY,
TYPE_WRAPLIST
};
/**
* Some consecutive items should be rendered together as a unit, e.g.,
* outlines for the same element. For this, we need a way for items to
* identify their type.
*/
virtual Type GetType() { return TYPE_GENERIC; }
/**
* This is called after we've constructed a display list for event handling.
* When this is called, we've already ensured that aPt is in the item's bounds.
*
* @return the frame that the point is considered over, or nsnull if
* this is not over any frame
*/
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt) { return nsnull; }
/**
* @return the frame that this display item is based on. This is used to sort
* items by z-index and content order and for some other uses. For some items
* that wrap item lists, this could return nsnull because there is no single
* underlying frame; for leaf items it will never return nsnull.
*/
virtual nsIFrame* GetUnderlyingFrame() = 0;
/**
* The default bounds is the frame border rect.
* @return a rectangle relative to aBuilder->ReferenceFrame() that
* contains the area drawn by this display item
*/
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
nsIFrame* f = GetUnderlyingFrame();
return nsRect(aBuilder->ToReferenceFrame(f), f->GetSize());
}
/**
* @return PR_TRUE if the item is definitely opaque --- i.e., paints
* every pixel within its bounds opaquely
*/
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder) { return PR_FALSE; }
/**
* @return PR_TRUE if the item is guaranteed to paint every pixel in its
* bounds with the same (possibly translucent) color
*/
virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder) { return PR_FALSE; }
/**
* @return PR_FALSE if the painting performed by the item is invariant
* when frame aFrame is moved relative to its parent (so it would be safe
* to update the display by just copying pixels from their old to new location)
*/
virtual PRBool IsVaryingRelativeToFrame(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame) { return PR_FALSE; }
/**
* Actually paint this item to some rendering context.
* @param aDirtyRect relative to aBuilder->ReferenceFrame()
*/
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect) {}
/**
* Only to be (re)implemented by items that contain child display lists.
* Do not reimplement for leaf items.
* The default implementation calls GetBounds() and IsOpaque().
* On entry, aVisibleRegion contains the region (relative to ReferenceFrame())
* which may be visible. If the display item opaquely covers an area, it
* can remove that area from aVisibleRegion before returning.
* @return PR_TRUE if the item is visible, PR_FALSE if no part of the item
* is visible
*/
virtual PRBool OptimizeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion);
/**
* Try to merge with the other item (which is below us in the display
* list). This gets used by nsDisplayClip to coalesce clipping operations
* (optimization), by nsDisplayOpacity to merge rendering for the same
* content element into a single opacity group (correctness), and will be
* used by nsDisplayOutline to merge multiple outlines for the same element
* (also for correctness).
* @return PR_TRUE if the merge was successful and the other item should be deleted
*/
virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
return PR_FALSE;
}
/**
* If this is a leaf item we return null, otherwise we return the wrapped
* list.
*/
virtual nsDisplayList* GetList() { return nsnull; }
#ifdef NS_DEBUG
/**
* For debugging and stuff
*/
virtual const char* Name() = 0;
#endif
nsDisplayItem* GetAbove() { return mAbove; }
protected:
friend class nsDisplayList;
nsDisplayItem() {
mAbove = nsnull;
}
static PRBool ComputeVisibilityFromBounds(nsIFrame* aFrame,
const nsRect& aRect, nsRegion& aCovered, PRBool aIsOpaque);
};
/**
* Manages a singly-linked list of display list items.
*
* mSentinel is the sentinel list value, the first value in the null-terminated
* linked list of items. mTop is the last item in the list (whose 'above'
* pointer is null). This class has no virtual methods. So list objects are just
* two pointers.
*
* Stepping upward through this list is very fast. Stepping downward is very
* slow so we don't support it. The methods that need to step downward
* (HitTest(), OptimizeVisibility()) internally build a temporary array of all
* the items while they do the downward traversal, so overall they're still
* linear time. We have optimized for efficient AppendToTop() of both
* items and lists, with minimal codesize. AppendToBottom() is efficient too.
*/
class nsDisplayList {
public:
/**
* Create an empty list.
*/
nsDisplayList() { mTop = &mSentinel; mSentinel.mAbove = nsnull; }
~nsDisplayList() {
if (mSentinel.mAbove) {
NS_WARNING("Nonempty list left over?");
}
DeleteAll();
}
/**
* Append an item to the top of the list. The item must not currently
* be in a list and cannot be null.
*/
void AppendToTop(nsDisplayItem* aItem) {
NS_ASSERTION(aItem, "No item to append!");
NS_ASSERTION(!aItem->mAbove, "Already in a list!");
mTop->mAbove = aItem;
mTop = aItem;
}
/**
* Append a new item to the top of the list. If the item is null we return
* NS_ERROR_OUT_OF_MEMORY. The intended usage is AppendNewToTop(new ...);
*/
nsresult AppendNewToTop(nsDisplayItem* aItem) {
if (!aItem)
return NS_ERROR_OUT_OF_MEMORY;
AppendToTop(aItem);
return NS_OK;
}
/**
* Append a new item to the bottom of the list. The item must be non-null
* and not already in a list.
*/
void AppendToBottom(nsDisplayItem* aItem) {
NS_ASSERTION(aItem, "No item to append!");
NS_ASSERTION(!aItem->mAbove, "Already in a list!");
aItem->mAbove = mSentinel.mAbove;
mSentinel.mAbove = aItem;
if (mTop == &mSentinel) {
mTop = aItem;
}
}
/**
* Removes all items from aList and appends them to the top of this list
*/
void AppendToTop(nsDisplayList* aList) {
if (aList->mSentinel.mAbove) {
mTop->mAbove = aList->mSentinel.mAbove;
mTop = aList->mTop;
aList->mTop = &aList->mSentinel;
aList->mSentinel.mAbove = nsnull;
}
}
/**
* Removes all items from aList and prepends them to the bottom of this list
*/
void AppendToBottom(nsDisplayList* aList) {
if (aList->mSentinel.mAbove) {
aList->mTop->mAbove = mSentinel.mAbove;
mTop = aList->mTop;
mSentinel.mAbove = aList->mSentinel.mAbove;
aList->mTop = &aList->mSentinel;
aList->mSentinel.mAbove = nsnull;
}
}
/**
* Remove an item from the bottom of the list and return it.
*/
nsDisplayItem* RemoveBottom();
/**
* Remove an item from the bottom of the list and call its destructor.
*/
void DeleteBottom();
/**
* Remove all items from the list and call their destructors.
*/
void DeleteAll();
/**
* @return the item at the top of the list, or null if the list is empty
*/
nsDisplayItem* GetTop() const {
return mTop != &mSentinel ? NS_STATIC_CAST(nsDisplayItem*, mTop) : nsnull;
}
/**
* @return the item at the bottom of the list, or null if the list is empty
*/
nsDisplayItem* GetBottom() const { return mSentinel.mAbove; }
PRBool IsEmpty() const { return mTop == &mSentinel; }
/**
* This is *linear time*!
* @return the number of items in the list
*/
PRUint32 Count() const;
/**
* Stable sort the list by the z-order of GetUnderlyingFrame() on
* each item. 'auto' is counted as zero. Content order is used as the
* secondary order.
* @param aCommonAncestor a common ancestor of all the content elements
* associated with the display items, for speeding up tree order
* checks, or nsnull if not known; it's only a hint, if it is not an
* ancestor of some elements, then we lose performance but not correctness
*/
void SortByZOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor);
/**
* Stable sort the list by the tree order of the content of
* GetUnderlyingFrame() on each item. z-index is ignored.
* @param aCommonAncestor a common ancestor of all the content elements
* associated with the display items, for speeding up tree order
* checks, or nsnull if not known; it's only a hint, if it is not an
* ancestor of some elements, then we lose performance but not correctness
*/
void SortByContentOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor);
/**
* Optimize the display list for visibility, removing any elements that
* are not visible. We put this logic here so it can be shared by top-level
* painting and also display items that maintain child lists.
*
* @param aVisibleRegion the area that is visible, relative to the
* reference frame; on return, this contains the area visible under the list
*/
void OptimizeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion);
/**
* Paint the list to the rendering context. We assume that (0,0) in aCtx
* corresponds to the origin of the reference frame. The rectangle in
* aDirtyRect is painted, which *must* be contained in the dirty rect
* used to construct the display list.
*/
void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect) const;
/**
* Find the topmost display item that returns a non-null frame, and return
* the frame.
*/
nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt) const;
private:
// Utility function used to massage the list during OptimizeVisibility.
void FlattenTo(nsVoidArray* aElements);
// Utility function used to massage the list during sorting, to rewrite
// any wrapper items with null GetUnderlyingFrame
void ExplodeAnonymousChildLists(nsDisplayListBuilder* aBuilder);
nsDisplayItemLink mSentinel;
nsDisplayItemLink* mTop;
};
/**
* This is passed as a parameter to nsIFrame::BuildDisplayList. That method
* will put any generated items onto the appropriate list given here. It's
* basically just a collection with one list for each separate stacking layer.
* The lists themselves are external to this object and thus can be shared
* with others. Some of the list pointers may even refer to the same list.
*/
struct nsDisplayListSet {
/**
* @return a list where one should place the border and/or background for
* this frame (everything from steps 1 and 2 of CSS 2.1 appendix E)
*/
nsDisplayList* BorderBackground() const { return mBorderBackground; }
/**
* @return a list where one should place the borders and/or backgrounds for
* block-level in-flow descendants (step 4 of CSS 2.1 appendix E)
*/
nsDisplayList* BlockBorderBackgrounds() const { return mBlockBorderBackgrounds; }
/**
* @return a list where one should place descendant floats (step 5 of
* CSS 2.1 appendix E)
*/
nsDisplayList* Floats() const { return mFloats; }
/**
* @return a list where one should place the (pseudo) stacking contexts
* for descendants of this frame (everything from steps 3, 7 and 8
* of CSS 2.1 appendix E)
*/
nsDisplayList* PositionedDescendants() const { return mPositioned; }
/**
* @return a list where one should place the outlines
* for this frame and its descendants (step 9 of CSS 2.1 appendix E)
*/
nsDisplayList* Outlines() const { return mOutlines; }
/**
* @return a list where one should place all other content
*/
nsDisplayList* Content() const { return mContent; }
nsDisplayListSet(nsDisplayList* aBorderBackground,
nsDisplayList* aBlockBorderBackgrounds,
nsDisplayList* aFloats,
nsDisplayList* aContent,
nsDisplayList* aPositionedDescendants,
nsDisplayList* aOutlines) :
mBorderBackground(aBorderBackground),
mBlockBorderBackgrounds(aBlockBorderBackgrounds),
mFloats(aFloats),
mContent(aContent),
mPositioned(aPositionedDescendants),
mOutlines(aOutlines) {
}
/**
* A copy constructor that lets the caller override the BorderBackground
* list.
*/
nsDisplayListSet(const nsDisplayListSet& aLists,
nsDisplayList* aBorderBackground) :
mBorderBackground(aBorderBackground),
mBlockBorderBackgrounds(aLists.BlockBorderBackgrounds()),
mFloats(aLists.Floats()),
mContent(aLists.Content()),
mPositioned(aLists.PositionedDescendants()),
mOutlines(aLists.Outlines()) {
}
/**
* Move all display items in our lists to top of the corresponding lists in the
* destination.
*/
void MoveTo(const nsDisplayListSet& aDestination) const;
protected:
nsDisplayList* mBorderBackground;
nsDisplayList* mBlockBorderBackgrounds;
nsDisplayList* mFloats;
nsDisplayList* mContent;
nsDisplayList* mPositioned;
nsDisplayList* mOutlines;
};
/**
* A specialization of nsDisplayListSet where the lists are actually internal
* to the object, and all distinct.
*/
struct nsDisplayListCollection : public nsDisplayListSet {
nsDisplayListCollection() :
nsDisplayListSet(&mLists[0], &mLists[1], &mLists[2], &mLists[3], &mLists[4],
&mLists[5]) {}
nsDisplayListCollection(nsDisplayList* aBorderBackground) :
nsDisplayListSet(aBorderBackground, &mLists[1], &mLists[2], &mLists[3], &mLists[4],
&mLists[5]) {}
/**
* Sort all lists by content order.
*/
void SortAllByContentOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor) {
for (PRInt32 i = 0; i < 6; ++i) {
mLists[i].SortByContentOrder(aBuilder, aCommonAncestor);
}
}
private:
nsDisplayList mLists[6];
};
/**
* Use this class to implement not-very-frequently-used display items
* that are not opaque, do not receive events, and are bounded by a frame's
* border-rect.
*
* This should not be used for display items which are created frequently,
* because each item is one or two pointers bigger than an item from a
* custom display item class could be, and fractionally slower. However it does
* save code size. We use this for infrequently-used item types.
*/
class nsDisplayGeneric : public nsDisplayItem {
public:
typedef void (* PaintCallback)(nsIFrame* aFrame, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aFramePt);
nsDisplayGeneric(nsIFrame* aFrame, PaintCallback aPaint, const char* aName)
: mFrame(aFrame), mPaint(aPaint)
#ifdef DEBUG
, mName(aName)
#endif
{}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect) {
mPaint(mFrame, aCtx, aDirtyRect, aBuilder->ToReferenceFrame(mFrame));
}
NS_DISPLAY_DECL_NAME(mName)
protected:
nsIFrame* mFrame;
PaintCallback mPaint;
#ifdef DEBUG
const char* mName;
#endif
};
/**
* The standard display item to paint the CSS borders of a frame.
*/
class nsDisplayBorder : public nsDisplayItem {
public:
nsDisplayBorder(nsIFrame* aFrame) : mFrame(aFrame) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("Border")
private:
nsIFrame* mFrame;
};
/**
* The standard display item to paint the CSS background of a frame.
*/
class nsDisplayBackground : public nsDisplayItem {
public:
nsDisplayBackground(nsIFrame* aFrame) : mFrame(aFrame) {}
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt) { return mFrame; }
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
virtual PRBool IsVaryingRelativeToFrame(nsDisplayListBuilder* aBuilder,
nsIFrame* aAncestorFrame);
virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("Background")
private:
nsIFrame* mFrame;
};
/**
* The standard display item to paint the CSS outline of a frame.
*/
class nsDisplayOutline : public nsDisplayItem {
public:
nsDisplayOutline(nsIFrame* aFrame) : mFrame(aFrame) {}
virtual Type GetType() { return TYPE_OUTLINE; }
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("Outline")
private:
nsIFrame* mFrame;
};
/**
* A class that lets you receive events within the frame bounds but never paints.
*/
class nsDisplayEventReceiver : public nsDisplayItem {
public:
nsDisplayEventReceiver(nsIFrame* aFrame) : mFrame(aFrame) {}
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt) { return mFrame; }
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
NS_DISPLAY_DECL_NAME("EventReceiver")
private:
nsIFrame* mFrame;
};
/**
* A class that lets you wrap a display list as a display item.
*
* GetUnderlyingFrame() is troublesome for wrapped lists because if the wrapped
* list has many items, it's not clear which one has the 'underlying frame'.
* Thus we force the creator to specify what the underlying frame is. The
* underlying frame should be the root of a stacking context, because sorting
* a list containing this item will not get at the children.
*
* In some cases (e.g., clipping) we want to wrap a list but we don't have a
* particular underlying frame that is a stacking context root. In that case
* we allow the frame to be nsnull. Callers to GetUnderlyingFrame must
* detect and handle this case.
*/
class nsDisplayWrapList : public nsDisplayItem {
public:
/**
* Takes all the items from aList and puts them in our list.
*/
nsDisplayWrapList(nsIFrame* aFrame, nsDisplayList* aList);
nsDisplayWrapList(nsIFrame* aFrame, nsDisplayItem* aItem);
virtual ~nsDisplayWrapList();
virtual Type GetType() { return TYPE_WRAPLIST; }
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt);
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder);
virtual PRBool IsVaryingRelativeToFrame(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
virtual PRBool OptimizeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion);
virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
NS_WARNING("This list should already have been flattened!!!");
return PR_FALSE;
}
NS_DISPLAY_DECL_NAME("WrapList")
virtual nsDisplayList* GetList() { return &mList; }
/**
* This creates a copy of this item, but wrapping aItem instead of
* our existing list. Only gets called if this item returned nsnull
* for GetUnderlyingFrame(). aItem is guaranteed to return non-null from
* GetUnderlyingFrame().
*/
virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem) {
NS_NOTREACHED("We never returned nsnull for GetUnderlyingFrame!");
return nsnull;
}
protected:
nsDisplayList mList;
nsIFrame* mFrame;
};
/**
* We call WrapDisplayList on the in-flow lists: BorderBackground(),
* BlockBorderBackgrounds() and Content().
* We call WrapDisplayItem on each item of Outlines(), PositionedDescendants(),
* and Floats(). This is done to support special wrapping processing for frames
* that may not be in-flow descendants of the current frame.
*/
class nsDisplayWrapper {
public:
virtual PRBool WrapBorderBackground() { return PR_TRUE; }
virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList) = 0;
virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem) = 0;
nsresult WrapLists(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsDisplayListSet& aIn, const nsDisplayListSet& aOut);
nsresult WrapListsInPlace(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsDisplayListSet& aLists);
};
/**
* The standard display item to paint a stacking context with translucency
* set by the stacking context root frame's 'opacity' style.
*/
class nsDisplayOpacity : public nsDisplayWrapList {
public:
nsDisplayOpacity(nsIFrame* aFrame, nsDisplayList* aList);
virtual Type GetType() { return TYPE_OPACITY; }
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
virtual PRBool OptimizeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion);
virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
NS_DISPLAY_DECL_NAME("Opacity")
private:
/**
* We set this to PR_FALSE if we can prove that our children cover our bounds
* completely and opaquely, therefore no alpha channel is required in the
* intermediate surface.
*/
PRPackedBool mNeedAlpha;
};
/**
* nsDisplayClip can clip a list of items, but we take a single item
* initially and then later merge other items into it when we merge
* adjacent matching nsDisplayClips
*/
class nsDisplayClip : public nsDisplayWrapList {
public:
nsDisplayClip(nsIFrame* aFrame, nsDisplayItem* aItem, const nsRect& aRect);
nsDisplayClip(nsIFrame* aFrame, nsDisplayList* aList, const nsRect& aRect);
virtual Type GetType() { return TYPE_CLIP; }
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
virtual PRBool OptimizeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion);
virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
NS_DISPLAY_DECL_NAME("Clip")
nsRect GetClipRect() { return mClip; }
virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem);
private:
nsRect mClip;
};
#endif /*NSDISPLAYLIST_H_*/

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

@ -894,10 +894,9 @@ DocumentViewerImpl::DumpContentToPPM(const char* aFileName)
status = "EMPTY";
} else {
nsCOMPtr<nsIRenderingContext> context;
nsresult rv = mViewManager->RenderOffscreen(view, r,
PR_FALSE, PR_TRUE,
NS_RGB(255, 255, 255),
getter_AddRefs(context));
nsresult rv = mPresShell->RenderOffscreen(r, PR_FALSE, PR_TRUE,
NS_RGB(255, 255, 255),
getter_AddRefs(context));
if (NS_FAILED(rv)) {
status = "FAILEDRENDER";

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

@ -53,6 +53,8 @@
#include "nsISupports.h"
#include "nsCoord.h"
#include "nsRect.h"
#include "nsColor.h"
#include "nsEvent.h"
#include "nsReflowType.h"
#include "nsCompatibility.h"
@ -707,6 +709,29 @@ public:
{
mForwardingContainer = aContainer;
}
/**
* Dump window contents into a new offscreen rendering context.
* @param aRect is the region to capture into the offscreen buffer, in the
* root frame's coordinate system (if aIgnoreViewportScrolling is false)
* or in the root scrolled frame's coordinate system
* (if aIgnoreViewportScrolling is true)
* @param aUntrusted set to PR_TRUE if the contents may be passed to malicious
* agents. E.g. we might choose not to paint the contents of sensitive widgets
* such as the file name in a file upload widget, and we might choose not
* to paint themes.
* @param aIgnoreViewportScrolling ignore clipping/scrolling/scrollbar painting
* due to scrolling in the viewport
* @param aBackgroundColor a background color to render onto
* @param aRenderedContext gets set to a rendering context whose offscreen
* buffer can be locked to get the data. The buffer's size will be aRect's size.
* In all cases the caller must clean it up by calling
* cx->DestroyDrawingSurface(cx->GetDrawingSurface()).
*/
NS_IMETHOD RenderOffscreen(nsRect aRect, PRBool aUntrusted,
PRBool aIgnoreViewportScrolling,
nscolor aBackgroundColor,
nsIRenderingContext** aRenderedContext) = 0;
protected:
// IMPORTANT: The ownership implicit in the following member variables

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

@ -37,7 +37,9 @@
#include "nsILayoutDebugger.h"
#include "nsIFrame.h"
#include "nsIFrameDebug.h"
#include "nsDisplayList.h"
#include <stdio.h>
#ifdef NS_DEBUG
class nsLayoutDebugger : public nsILayoutDebugger {
@ -141,4 +143,50 @@ nsLayoutDebugger::GetStyleSize(nsIPresShell* aPresentation,
*aSizeInBytesResult = 0;
return NS_ERROR_FAILURE;
}
static void
PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList,
PRInt32 aIndent, FILE* aOutput)
{
for (nsDisplayItem* i = aList.GetBottom(); i != nsnull; i = i->GetAbove()) {
for (PRInt32 j = 0; j < aIndent; ++j) {
fputc(' ', aOutput);
}
nsIFrame* f = i->GetUnderlyingFrame();
nsIFrameDebug* fDebug = nsnull;
if (f) {
CallQueryInterface(f, &fDebug);
}
nsAutoString fName;
if (fDebug) {
fDebug->GetFrameName(fName);
}
nsRect rect = i->GetBounds(aBuilder);
switch (i->GetType()) {
case nsDisplayItem::TYPE_CLIP: {
nsDisplayClip* c = NS_STATIC_CAST(nsDisplayClip*, i);
rect = c->GetClipRect();
break;
}
default:
break;
}
fprintf(aOutput, "%s %p(%s) (%d,%d,%d,%d)%s%s\n", i->Name(),
(void*)f, NS_ConvertUTF16toUTF8(fName).get(),
rect.x, rect.y, rect.width, rect.height,
i->IsOpaque(aBuilder) ? " opaque" : "",
i->IsUniform(aBuilder) ? " uniform" : "");
nsDisplayList* list = i->GetList();
if (list) {
PrintDisplayListTo(aBuilder, *list, aIndent + 4, aOutput);
}
}
}
void
nsIFrameDebug::PrintDisplayList(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList)
{
PrintDisplayListTo(aBuilder, aList, 0, stderr);
}
#endif

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

@ -52,6 +52,8 @@
#include "nsIPrivateDOMEvent.h"
#include "nsIDOMEvent.h"
#include "nsGUIEvent.h"
#include "nsDisplayList.h"
#include "nsRegion.h"
/**
* A namespace class for static layout utilities.
@ -208,6 +210,46 @@ nsLayoutUtils::IsGeneratedContentFor(nsIContent* aContent,
return aFrame->GetStyleContext()->GetPseudoType() == aPseudoElement;
}
// static
nsIFrame*
nsLayoutUtils::GetCrossDocParentFrame(nsIFrame* aFrame)
{
nsIFrame* p = aFrame->GetParent();
if (p)
return p;
nsIView* v = aFrame->GetView();
if (!v)
return nsnull;
v = v->GetParent(); // anonymous inner view
if (!v)
return nsnull;
v = v->GetParent(); // subdocumentframe's view
if (!v)
return nsnull;
return NS_STATIC_CAST(nsIFrame*, v->GetClientData());
}
// static
PRBool
nsLayoutUtils::IsProperAncestorFrameCrossDoc(nsIFrame* aAncestorFrame, nsIFrame* aFrame,
nsIFrame* aCommonAncestor)
{
if (aFrame == aCommonAncestor)
return PR_FALSE;
nsIFrame* parentFrame = GetCrossDocParentFrame(aFrame);
while (parentFrame != aCommonAncestor) {
if (parentFrame == aAncestorFrame)
return PR_TRUE;
parentFrame = GetCrossDocParentFrame(parentFrame);
}
return PR_FALSE;
}
// static
PRBool
nsLayoutUtils::IsProperAncestorFrame(nsIFrame* aAncestorFrame, nsIFrame* aFrame,
@ -540,6 +582,202 @@ nsLayoutUtils::IsInitialContainingBlock(nsIFrame* aFrame)
aFrame->GetPresContext()->PresShell()->FrameConstructor()->GetInitialContainingBlock();
}
#ifdef DEBUG
#include <stdio.h>
static PRBool gDumpPaintList = 0;
static PRBool gDumpEventList = 0;
#endif
nsIFrame*
nsLayoutUtils::GetFrameForPoint(nsIFrame* aFrame, nsPoint aPt)
{
nsDisplayListBuilder builder(aFrame, PR_TRUE);
nsDisplayList list;
nsresult rv =
aFrame->BuildDisplayListForStackingContext(&builder, nsRect(aPt, nsSize(1, 1)), &list);
NS_ENSURE_SUCCESS(rv, nsnull);
#ifdef DEBUG
if (gDumpEventList) {
fprintf(stderr, "Event handling --- (%d,%d):\n", aPt.x, aPt.y);
nsIFrameDebug::PrintDisplayList(&builder, list);
}
#endif
nsIFrame* result = list.HitTest(&builder, aPt);
list.DeleteAll();
return result;
}
nsresult
nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFrame,
const nsRegion& aDirtyRegion)
{
nsDisplayListBuilder builder(aFrame, PR_FALSE);
nsDisplayList list;
nsRect dirtyRect = aDirtyRegion.GetBounds();
nsresult rv =
aFrame->BuildDisplayListForStackingContext(&builder, dirtyRect, &list);
NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG
if (gDumpPaintList) {
fprintf(stderr, "Painting --- before optimization (dirty %d,%d,%d,%d):\n",
dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
nsIFrameDebug::PrintDisplayList(&builder, list);
}
#endif
nsRegion visibleRegion = aDirtyRegion;
list.OptimizeVisibility(&builder, &visibleRegion);
#ifdef DEBUG
if (gDumpPaintList) {
fprintf(stderr, "Painting --- after optimization:\n");
nsIFrameDebug::PrintDisplayList(&builder, list);
}
#endif
list.Paint(&builder, aRenderingContext, aDirtyRegion.GetBounds());
// Flush the list so we don't trigger the IsEmpty-on-destruction assertion
list.DeleteAll();
return NS_OK;
}
static void
AddItemsToRegion(nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
const nsRect& aRect, const nsRect& aClipRect, nsPoint aDelta,
nsRegion* aRegion)
{
for (nsDisplayItem* item = aList->GetBottom(); item; item = item->GetAbove()) {
nsDisplayList* sublist = item->GetList();
if (sublist) {
if (item->GetType() == nsDisplayItem::TYPE_CLIP) {
nsRect clip;
clip.IntersectRect(aClipRect, NS_STATIC_CAST(nsDisplayClip*, item)->GetClipRect());
AddItemsToRegion(aBuilder, sublist, aRect, clip, aDelta, aRegion);
} else {
// opacity, or a generic sublist
AddItemsToRegion(aBuilder, sublist, aRect, aClipRect, aDelta, aRegion);
}
} else {
// Items left in the list are either IsVaryingRelativeToFrame
// or !IsMovingFrame (i.e., not in the moving subtree)
nsRect r;
if (r.IntersectRect(aClipRect, item->GetBounds(aBuilder))) {
PRBool inMovingSubtree = PR_FALSE;
if (item->IsVaryingRelativeToFrame(aBuilder, aBuilder->GetRootMovingFrame())) {
nsIFrame* f = item->GetUnderlyingFrame();
NS_ASSERTION(f, "Must have an underlying frame for leaf item");
inMovingSubtree = aBuilder->IsMovingFrame(f);
nsRect damageRect;
if (damageRect.IntersectRect(aRect + aDelta, r)) {
aRegion->Or(*aRegion, damageRect);
}
}
if (!inMovingSubtree) {
// if it's uniform and it includes both the old and new areas, then
// we don't need to paint it
if (!(r.Contains(aRect) && r.Contains(aRect + aDelta) &&
item->IsVaryingRelativeToFrame(aBuilder, aBuilder->GetRootMovingFrame()))) {
// area where a non-moving element is visible must be repainted
nsRect damageRect;
if (damageRect.IntersectRect(aRect + aDelta, r)) {
aRegion->Or(*aRegion, damageRect);
}
// we may have bitblitted an area that was painted by a non-moving
// element. This bitblitted data is invalid and was copied to
// "r + aDelta".
if (damageRect.IntersectRect(aRect + aDelta, r + aDelta)) {
aRegion->Or(*aRegion, damageRect);
}
}
}
}
}
}
}
nsresult
nsLayoutUtils::ComputeRepaintRegionForCopy(nsIFrame* aRootFrame,
nsIFrame* aMovingFrame,
nsPoint aDelta,
const nsRect& aCopyRect,
nsRegion* aRepaintRegion)
{
// Build the 'after' display list over the whole area of interest.
// Frames under aMovingFrame will not be allowed to affect (clip or cover)
// non-moving frame display items ... then we can be sure the non-moving
// frame display items we get are the same ones we would have gotten if
// we had constructed the 'before' display list.
// (We have to build the 'after' display list because the frame/view
// hierarchy has already been updated for the move.)
nsRect rect;
rect.UnionRect(aCopyRect, aCopyRect + aDelta);
nsDisplayListBuilder builder(aRootFrame, PR_FALSE, aMovingFrame);
nsDisplayList list;
nsresult rv =
aRootFrame->BuildDisplayListForStackingContext(&builder, rect, &list);
NS_ENSURE_SUCCESS(rv, rv);
// Optimize for visibility, but frames under aMovingFrame will not be
// considered opaque, so they don't cover non-moving frames.
nsRegion visibleRegion(aCopyRect);
visibleRegion.Or(visibleRegion, aCopyRect + aDelta);
list.OptimizeVisibility(&builder, &visibleRegion);
aRepaintRegion->SetEmpty();
// Any visible non-moving display items get added to the repaint region
// a) at their current location and b) offset by -aPt (their position in
// the 'before' display list) (unless they're uniform and we can exclude them).
// Also, any visible position-varying display items get added to the
// repaint region. All these areas are confined to aCopyRect+aDelta.
// We could do more work here: e.g., do another optimize-visibility pass
// with the moving items taken into account, either on the before-list
// or the after-list, or even both if we cloned the display lists ... but
// it's probably not worth it.
AddItemsToRegion(&builder, &list, aCopyRect, rect, aDelta, aRepaintRegion);
// Flush the list so we don't trigger the IsEmpty-on-destruction assertion
list.DeleteAll();
return NS_OK;
}
nsresult
nsLayoutUtils::CreateOffscreenContext(nsIDeviceContext* deviceContext, nsIDrawingSurface* surface,
const nsRect& aRect, nsIRenderingContext** aResult)
{
nsresult rv;
nsIRenderingContext *context = nsnull;
rv = deviceContext->CreateRenderingContext(surface, context);
NS_ENSURE_SUCCESS(rv, rv);
// always initialize clipping, linux won't draw images otherwise.
nsRect clip(0, 0, aRect.width, aRect.height);
context->SetClipRect(clip, nsClipCombine_kReplace);
context->Translate(-aRect.x, -aRect.y);
*aResult = context;
return NS_OK;
}
PRInt32
nsLayoutUtils::GetZIndex(nsIFrame* aFrame) {
if (!aFrame->GetStyleDisplay()->IsPositioned())
return 0;
const nsStylePosition* position =
aFrame->GetStylePosition();
if (position->mZIndex.GetUnit() == eStyleUnit_Integer)
return position->mZIndex.GetIntValue();
// sort the auto and 0 elements together
return 0;
}
/**
* Uses a binary search for find where the cursor falls in the line of text
* It also keeps track of the part of the string that has already been measured
@ -614,4 +852,3 @@ nsLayoutUtils::ScrollIntoView(nsIFormControlFrame* aFormFrame)
}
}
}

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

@ -46,6 +46,7 @@ class nsIAtom;
class nsIScrollableView;
class nsIScrollableFrame;
class nsIDOMEvent;
class nsRegion;
#include "prtypes.h"
#include "nsStyleContext.h"
@ -155,6 +156,13 @@ public:
*/
static nsIView* FindSiblingViewFor(nsIView* aParentView, nsIFrame* aFrame);
/**
* Get the parent of aFrame. If aFrame is the root frame for a document,
* and the document has a parent document in the same view hierarchy, then
* we try to return the subdocumentframe in the parent document.
*/
static nsIFrame* GetCrossDocParentFrame(nsIFrame* aFrame);
/**
* IsProperAncestorFrame checks whether aAncestorFrame is an ancestor
* of aFrame and not equal to aFrame.
@ -165,6 +173,12 @@ public:
static PRBool IsProperAncestorFrame(nsIFrame* aAncestorFrame, nsIFrame* aFrame,
nsIFrame* aCommonAncestor = nsnull);
/**
* Like IsProperAncestorFrame, but looks across document boundaries.
*/
static PRBool IsProperAncestorFrameCrossDoc(nsIFrame* aAncestorFrame, nsIFrame* aFrame,
nsIFrame* aCommonAncestor = nsnull);
/**
* GetFrameFor returns the root frame for a view
* @param aView is the view to return the root frame for
@ -300,6 +314,74 @@ public:
nsIWidget* aWidget, nsIntPoint aPt,
nsIView* aView);
/**
* Given aFrame, the root frame of a stacking context, find its descendant
* frame under the point aPt that receives a mouse event at that location,
* or nsnull if there is no such frame.
* @param aPt the point, relative to the frame origin
*/
static nsIFrame* GetFrameForPoint(nsIFrame* aFrame, nsPoint aPt);
/**
* Given aFrame, the root frame of a stacking context, paint it and its
* descendants to aRenderingContext.
* @param aRenderingContext a rendering context translated so that (0,0)
* is the origin of aFrame
* @param aDirtyRegion the region that must be painted, in the coordinates
* of aFrame
*/
static nsresult PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFrame,
const nsRegion& aDirtyRegion);
/**
* @param aRootFrame the root frame of the tree to be displayed
* @param aMovingFrame a frame that has moved
* @param aPt the amount by which aMovingFrame has moved and the rect will
* be copied
* @param aCopyRect a rectangle that will be copied, relative to aRootFrame
* @param aRepaintRegion a subregion of aCopyRect+aDelta that must be repainted
* after doing the bitblt
*
* Ideally this function would actually have the rect-to-copy as an output
* rather than an input, but for now, scroll bitblitting is limited to
* the whole of a single widget, so we cannot choose the rect.
*
* This function assumes that the caller will do a bitblt copy of aCopyRect
* to aCopyRect+aPt. It computes a region that must be repainted in order
* for the resulting rendering to be correct.
*
* The region consists of:
* a) any visible background-attachment:fixed areas in the after-move display
* list
* b) any visible areas of the before-move display list corresponding to
* frames that will not move (translated by aDelta)
* c) any visible areas of the after-move display list corresponding to
* frames that did not move
* d) except that if the same display list element is visible in b) and c)
* for a frame that did not move and paints a uniform color within its
* bounds, then the intersection of its old and new bounds can be excluded
* when it is processed by b) and c).
*
* We may return a larger region if computing the above region precisely is
* too expensive.
*/
static nsresult ComputeRepaintRegionForCopy(nsIFrame* aRootFrame,
nsIFrame* aMovingFrame,
nsPoint aDelta,
const nsRect& aCopyRect,
nsRegion* aRepaintRegion);
static nsresult CreateOffscreenContext(nsIDeviceContext* deviceContext,
nsIDrawingSurface* surface,
const nsRect& aRect,
nsIRenderingContext** aResult);
/**
* Compute the used z-index of aFrame; returns zero for elements to which
* z-index does not apply, and for z-index:auto
*/
static PRInt32 GetZIndex(nsIFrame* aFrame);
/**
* Uses a binary search for find where the cursor falls in the line of text
* It also keeps track of the part of the string that has already been measured

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

@ -1349,14 +1349,4 @@ nsPresContext::CountReflows(const char * aName,
mShell->CountReflows(aName, aType, aFrame);
}
}
void
nsPresContext::PaintCount(const char * aName,
nsIRenderingContext* aRenderingContext,
nsIFrame * aFrame, PRUint32 aColor)
{
if (mShell) {
mShell->PaintCount(aName, aRenderingContext, this, aFrame, aColor);
}
}
#endif

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

@ -615,9 +615,6 @@ public:
#ifdef MOZ_REFLOW_PERF
NS_HIDDEN_(void) CountReflows(const char * aName,
PRUint32 aType, nsIFrame * aFrame);
NS_HIDDEN_(void) PaintCount(const char * aName,
nsIRenderingContext* aRendingContext,
nsIFrame * aFrame, PRUint32 aColor);
#endif
/**
@ -765,18 +762,4 @@ protected:
#define DO_GLOBAL_REFLOW_COUNT(_name, _type)
#endif // MOZ_REFLOW_PERF
#if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)
#define DO_GLOBAL_REFLOW_COUNT_DSP(_name, _rend) \
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { \
aPresContext->PaintCount((_name), (_rend), (nsIFrame*)this, 0); \
}
#define DO_GLOBAL_REFLOW_COUNT_DSP_J(_name, _rend, _just) \
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { \
aPresContext->PaintCount((_name), (_rend), (nsIFrame*)this, (_just)); \
}
#else
#define DO_GLOBAL_REFLOW_COUNT_DSP(_name, _rend)
#define DO_GLOBAL_REFLOW_COUNT_DSP_J(_name, _rend, _just)
#endif // MOZ_REFLOW_PERF_DSP
#endif /* nsPresContext_h___ */

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

@ -140,6 +140,8 @@
#include "prenv.h"
#include "nsIAttribute.h"
#include "nsIGlobalHistory2.h"
#include "nsDisplayList.h"
#include "nsRegion.h"
#ifdef MOZ_REFLOW_PERF_DSP
#include "nsIRenderingContext.h"
@ -1153,6 +1155,11 @@ public:
virtual nsresult ReconstructFrames(void);
virtual void Freeze();
virtual void Thaw();
NS_IMETHOD RenderOffscreen(nsRect aRect, PRBool aUntrusted,
PRBool aIgnoreViewportScrolling,
nscolor aBackgroundColor,
nsIRenderingContext** aRenderedContext);
#ifdef IBMBIDI
NS_IMETHOD SetCaretBidiLevel(PRUint8 aLevel);
@ -1164,13 +1171,16 @@ public:
//nsIViewObserver interface
NS_IMETHOD Paint(nsIView *aView,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
nsIRenderingContext* aRenderingContext,
const nsRegion& aDirtyRegion);
NS_IMETHOD ComputeRepaintRegionForCopy(nsIView* aRootView,
nsIView* aMovingView,
nsPoint aDelta,
const nsRect& aCopyRect,
nsRegion* aRepaintRegion);
NS_IMETHOD HandleEvent(nsIView* aView,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus,
PRBool aForceHandle,
PRBool& aHandled);
nsEventStatus* aEventStatus);
NS_IMETHOD HandleDOMEventWithTarget(nsIContent* aTargetContent,
nsEvent* aEvent,
nsEventStatus* aStatus);
@ -1315,6 +1325,7 @@ protected:
nsresult CloneStyleSet(nsStyleSet* aSet, nsStyleSet** aResult);
PRBool VerifyIncrementalReflow();
PRBool mInVerifyReflow;
void ShowEventTargetDebug();
#endif
/**
@ -1409,8 +1420,8 @@ private:
PRBool InZombieDocument(nsIContent *aContent);
nsresult RetargetEventToParent(nsIView *aView, nsGUIEvent* aEvent,
nsEventStatus* aEventStatus, PRBool aForceHandle,
PRBool& aHandled, nsIContent *aZombieFocusedContent);
nsEventStatus* aEventStatus,
nsIContent *aZombieFocusedContent);
void FreeDynamicStack();
@ -1419,6 +1430,10 @@ private:
void PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent);
void PopCurrentEventInfo();
nsresult HandleEventInternal(nsEvent* aEvent, nsIView* aView, PRUint32 aFlags, nsEventStatus *aStatus);
nsresult HandlePositionedEvent(nsIView* aView,
nsIFrame* aTargetFrame,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus);
//help funcs for resize events
void CreateResizeEventTimer();
@ -5378,77 +5393,100 @@ PresShell::BidiStyleChangeReflow()
//nsIViewObserver
// Return TRUE if any clipping is to be done.
static PRBool ComputeClipRect(nsIFrame* aFrame, nsRect& aResult) {
const nsStyleDisplay* display = aFrame->GetStyleDisplay();
// 'clip' only applies to absolutely positioned elements, and is
// relative to the element's border edge. 'clip' applies to the entire
// element: border, padding, and content areas, and even scrollbars if
// there are any.
if (display->IsAbsolutelyPositioned() && (display->mClipFlags & NS_STYLE_CLIP_RECT)) {
nsSize size = aFrame->GetSize();
// Start with the 'auto' values and then factor in user specified values
nsRect clipRect(0, 0, size.width, size.height);
if (display->mClipFlags & NS_STYLE_CLIP_RECT) {
if (0 == (NS_STYLE_CLIP_TOP_AUTO & display->mClipFlags)) {
clipRect.y = display->mClip.y;
}
if (0 == (NS_STYLE_CLIP_LEFT_AUTO & display->mClipFlags)) {
clipRect.x = display->mClip.x;
}
if (0 == (NS_STYLE_CLIP_RIGHT_AUTO & display->mClipFlags)) {
clipRect.width = display->mClip.width;
}
if (0 == (NS_STYLE_CLIP_BOTTOM_AUTO & display->mClipFlags)) {
clipRect.height = display->mClip.height;
}
}
aResult = clipRect;
return PR_TRUE;
}
return PR_FALSE;
}
// If the element is absolutely positioned and has a specified clip rect
// then it pushes the current rendering context and sets the clip rect.
// Returns PR_TRUE if the clip rect is set and PR_FALSE otherwise
static PRBool
SetClipRect(nsIRenderingContext& aRenderingContext, nsIFrame* aFrame)
NS_IMETHODIMP
PresShell::ComputeRepaintRegionForCopy(nsIView* aRootView,
nsIView* aMovingView,
nsPoint aDelta,
const nsRect& aCopyRect,
nsRegion* aRepaintRegion)
{
nsRect clipRect;
if (ComputeClipRect(aFrame, clipRect)) {
// Set updated clip-rect into the rendering context
aRenderingContext.PushState();
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect);
return PR_TRUE;
}
return PR_FALSE;
}
static PRBool
InClipRect(nsIFrame* aFrame, const nsPoint& aEventPoint)
{
nsRect clipRect;
if (ComputeClipRect(aFrame, clipRect)) {
return clipRect.Contains(aEventPoint);
} else {
return PR_TRUE;
}
return nsLayoutUtils::ComputeRepaintRegionForCopy(
NS_STATIC_CAST(nsIFrame*, aRootView->GetClientData()),
NS_STATIC_CAST(nsIFrame*, aMovingView->GetClientData()),
aDelta, aCopyRect, aRepaintRegion);
}
NS_IMETHODIMP
PresShell::Paint(nsIView *aView,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect)
PresShell::RenderOffscreen(nsRect aRect, PRBool aUntrusted,
PRBool aIgnoreViewportScrolling,
nscolor aBackgroundColor,
nsIRenderingContext** aRenderedContext)
{
nsIView* rootView;
mViewManager->GetRootView(rootView);
NS_ASSERTION(rootView, "No root view?");
nsIWidget* rootWidget = rootView->GetWidget();
NS_ASSERTION(rootWidget, "No root widget?");
*aRenderedContext = nsnull;
NS_ASSERTION(!aUntrusted, "We don't support untrusted yet");
if (aUntrusted)
return NS_ERROR_NOT_IMPLEMENTED;
nsCOMPtr<nsIRenderingContext> tmpContext;
mPresContext->DeviceContext()->CreateRenderingContext(rootWidget,
*getter_AddRefs(tmpContext));
if (!tmpContext)
return NS_ERROR_FAILURE;
nsRect bounds(nsPoint(0, 0), aRect.Size());
bounds.ScaleRoundOut(mPresContext->TwipsToPixels());
nsIDrawingSurface* surface;
nsresult rv
= tmpContext->CreateDrawingSurface(bounds, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS,
surface);
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
nsCOMPtr<nsIRenderingContext> localcx;
rv = nsLayoutUtils::CreateOffscreenContext(mPresContext->DeviceContext(),
surface, aRect, getter_AddRefs(localcx));
if (NS_FAILED(rv)) {
tmpContext->DestroyDrawingSurface(surface);
return NS_ERROR_FAILURE;
}
// clipping and translation is set by CreateOffscreenContext
localcx->SetColor(aBackgroundColor);
localcx->FillRect(aRect);
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
if (!rootFrame) {
localcx.swap(*aRenderedContext);
return NS_OK;
}
nsDisplayListBuilder builder(rootFrame, PR_FALSE);
nsDisplayList list;
nsIScrollableView* scrollingView = nsnull;
mViewManager->GetRootScrollableView(&scrollingView);
nsRect r = aRect;
if (aIgnoreViewportScrolling && scrollingView) {
nscoord x, y;
scrollingView->GetScrollPosition(x, y);
localcx->Translate(x, y);
r.MoveBy(-x, -y);
builder.SetIgnoreScrollFrame(GetRootScrollFrame(rootFrame));
}
rv = rootFrame->BuildDisplayListForStackingContext(&builder, r, &list);
NS_ENSURE_SUCCESS(rv, rv);
nsRegion region(r);
list.OptimizeVisibility(&builder, &region);
list.Paint(&builder, localcx, r);
// Flush the list so we don't trigger the IsEmpty-on-destruction assertion
list.DeleteAll();
localcx.swap(*aRenderedContext);
return NS_OK;
}
NS_IMETHODIMP
PresShell::Paint(nsIView* aView,
nsIRenderingContext* aRenderingContext,
const nsRegion& aDirtyRegion)
{
nsIFrame* frame;
nsresult rv = NS_OK;
@ -5467,31 +5505,19 @@ PresShell::Paint(nsIView *aView,
if (mCaret)
mCaret->EraseCaret();
// If the frame is absolutely positioned, then the 'clip' property
// applies
PRBool setClipRect = SetClipRect(aRenderingContext, frame);
rv = frame->Paint(mPresContext, aRenderingContext, aDirtyRect,
NS_FRAME_PAINT_LAYER_BACKGROUND);
rv = frame->Paint(mPresContext, aRenderingContext, aDirtyRect,
NS_FRAME_PAINT_LAYER_FLOATS);
rv = frame->Paint(mPresContext, aRenderingContext, aDirtyRect,
NS_FRAME_PAINT_LAYER_FOREGROUND);
if (setClipRect)
aRenderingContext.PopState();
nsLayoutUtils::PaintFrame(aRenderingContext, frame, aDirtyRegion);
#ifdef NS_DEBUG
// Draw a border around the frame
if (nsIFrameDebug::GetShowFrameBorders()) {
nsRect r = frame->GetRect();
aRenderingContext.SetColor(NS_RGB(0,0,255));
aRenderingContext.DrawRect(0, 0, r.width, r.height);
aRenderingContext->SetColor(NS_RGB(0,0,255));
aRenderingContext->DrawRect(0, 0, r.width, r.height);
}
// Draw a border around the current event target
if ((nsIFrameDebug::GetShowEventTargetFrameBorder()) && (aView == mCurrentTargetView)) {
aRenderingContext.SetColor(NS_RGB(128,0,128));
aRenderingContext.DrawRect(mCurrentTargetRect.x, mCurrentTargetRect.y, mCurrentTargetRect.width, mCurrentTargetRect.height);
aRenderingContext->SetColor(NS_RGB(128,0,128));
aRenderingContext->DrawRect(mCurrentTargetRect.x, mCurrentTargetRect.y, mCurrentTargetRect.width, mCurrentTargetRect.height);
}
#endif
}
@ -5579,8 +5605,6 @@ PRBool PresShell::InZombieDocument(nsIContent *aContent)
nsresult PresShell::RetargetEventToParent(nsIView *aView,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus,
PRBool aForceHandle,
PRBool& aHandled,
nsIContent* aZombieFocusedContent)
{
// Send this events straight up to the parent pres shell.
@ -5645,20 +5669,15 @@ nsresult PresShell::RetargetEventToParent(nsIView *aView,
PopCurrentEventInfo();
return parentViewObserver->HandleEvent(aView, aEvent,
aEventStatus,
aForceHandle,
aHandled);
aEventStatus);
}
NS_IMETHODIMP
PresShell::HandleEvent(nsIView *aView,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus,
PRBool aForceHandle,
PRBool& aHandled)
nsEventStatus* aEventStatus)
{
NS_ASSERTION(aView, "null view");
aHandled = PR_TRUE;
if (mIsDestroying || mIsReflowing || mChangeNestCount) {
return NS_OK;
@ -5689,7 +5708,6 @@ PresShell::HandleEvent(nsIView *aView,
nsIView *view;
vm->GetRootView(view);
if (view == aView) {
aHandled = PR_TRUE;
*aEventStatus = nsEventStatus_eConsumeDoDefault;
mPresContext->SysColorChanged();
return NS_OK;
@ -5697,13 +5715,42 @@ PresShell::HandleEvent(nsIView *aView,
}
return NS_OK;
}
nsIFrame* frame = NS_STATIC_CAST(nsIFrame*, aView->GetClientData());
PRBool dispatchUsingCoordinates =
!NS_IS_KEY_EVENT(aEvent) && !NS_IS_IME_EVENT(aEvent) &&
aEvent->message != NS_CONTEXTMENU_KEY && !NS_IS_FOCUS_EVENT(aEvent);
nsIFrame* targetFrame;
if (frame && dispatchUsingCoordinates) {
nsPoint eventPoint
= nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, frame);
targetFrame = nsLayoutUtils::GetFrameForPoint(frame, eventPoint);
if (targetFrame) {
PresShell* shell =
NS_STATIC_CAST(PresShell*, targetFrame->GetPresContext()->PresShell());
if (shell != this) {
// handle the event in the correct shell.
nsIView* subshellRootView;
shell->GetViewManager()->GetRootView(subshellRootView);
// We pass the subshell's root view as the view to start from. This is
// the only correct alternative; if the event was captured then it
// must have been captured by us or some ancestor shell and we
// now ask the subshell to dispatch it normally.
return shell->HandlePositionedEvent(subshellRootView, targetFrame,
aEvent, aEventStatus);
}
}
if (!targetFrame) {
targetFrame = frame;
}
return HandlePositionedEvent(aView, targetFrame, aEvent, aEventStatus);
}
// if this event has no frame, we need to retarget it at a parent
// view that has a frame.
if (!frame &&
((NS_IS_KEY_EVENT(aEvent) || NS_IS_IME_EVENT(aEvent)))) {
if (!frame && (NS_IS_KEY_EVENT(aEvent) || NS_IS_IME_EVENT(aEvent))) {
nsIView* targetView = aView;
while (targetView && !targetView->GetClientData()) {
targetView = targetView->GetParent();
@ -5721,17 +5768,14 @@ PresShell::HandleEvent(nsIView *aView,
PushCurrentEventInfo(nsnull, nsnull);
// key and IME events go to the focused frame
nsCOMPtr<nsIEventStateManager> manager;
if ((NS_IS_KEY_EVENT(aEvent) || NS_IS_IME_EVENT(aEvent) ||
aEvent->message == NS_CONTEXTMENU_KEY)) {
nsIEventStateManager *esm = mPresContext->EventStateManager();
nsIEventStateManager *esm = mPresContext->EventStateManager();
if (NS_IS_KEY_EVENT(aEvent) || NS_IS_IME_EVENT(aEvent) ||
aEvent->message == NS_CONTEXTMENU_KEY) {
esm->GetFocusedFrame(&mCurrentEventFrame);
if (mCurrentEventFrame) {
esm->GetFocusedContent(getter_AddRefs(mCurrentEventContent));
}
else {
} else {
#if defined(MOZ_X11) || defined(XP_WIN)
#if defined(MOZ_X11)
if (NS_IS_IME_EVENT(aEvent)) {
@ -5776,118 +5820,22 @@ PresShell::HandleEvent(nsIView *aView,
mCurrentEventFrame = nsnull; // XXXldb Isn't it already?
}
if (mCurrentEventContent && InZombieDocument(mCurrentEventContent)) {
return RetargetEventToParent(aView, aEvent, aEventStatus, aForceHandle,
aHandled, mCurrentEventContent);
return RetargetEventToParent(aView, aEvent, aEventStatus,
mCurrentEventContent);
}
}
else if (!InClipRect(frame,
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, frame))) {
// we only check for the clip rect on this frame ... all frames with clip
// have views so any viewless children of this frame cannot have clip.
// Furthermore if the event is not in the clip for this frame, then none
// of the children can get it either.
if (aForceHandle) {
mCurrentEventFrame = frame;
}
else {
mCurrentEventFrame = nsnull;
}
aHandled = PR_FALSE;
rv = NS_OK;
} else {
rv = NS_OK;
nsPoint eventPoint;
eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, frame);
mCurrentEventFrame = frame->GetFrameForPoint(eventPoint,
NS_FRAME_PAINT_LAYER_FOREGROUND);
if (!mCurrentEventFrame) {
mCurrentEventFrame = frame->GetFrameForPoint(eventPoint,
NS_FRAME_PAINT_LAYER_FLOATS);
if (!mCurrentEventFrame) {
mCurrentEventFrame = frame->GetFrameForPoint(eventPoint,
NS_FRAME_PAINT_LAYER_BACKGROUND);
if (!mCurrentEventFrame) {
if (aForceHandle) {
mCurrentEventFrame = frame;
}
else {
mCurrentEventFrame = nsnull;
}
aHandled = PR_FALSE;
}
}
}
if (mCurrentEventFrame) {
nsCOMPtr<nsIContent> targetElement;
mCurrentEventFrame->GetContentForEvent(mPresContext, aEvent,
getter_AddRefs(targetElement));
// If there is no content for this frame, target it anyway. Some
// frames can be targeted but do not have content, particularly
// windows with scrolling off.
if (targetElement) {
// Bug 103055, bug 185889: mouse events apply to *elements*, not all
// nodes. Thus we get the nearest element parent here.
// XXX we leave the frame the same even if we find an element
// parent, so that the text frame will receive the event (selection
// and friends are the ones who care about that anyway)
//
// We use weak pointers because during this tight loop, the node
// will *not* go away. And this happens on every mousemove.
while (targetElement &&
!targetElement->IsContentOfType(nsIContent::eELEMENT)) {
targetElement = targetElement->GetParent();
}
// If we found an element, target it. Otherwise, target *nothing*.
if (!targetElement) {
mCurrentEventContent = nsnull;
mCurrentEventFrame = nsnull;
} else if (targetElement != mCurrentEventContent) {
mCurrentEventContent = targetElement;
}
}
}
mCurrentEventFrame = frame;
}
if (GetCurrentEventFrame()) {
rv = HandleEventInternal(aEvent, aView,
NS_EVENT_FLAG_INIT, aEventStatus);
}
#ifdef NS_DEBUG
if ((nsIFrameDebug::GetShowEventTargetFrameBorder()) &&
(GetCurrentEventFrame())) {
nsIView *oldView = mCurrentTargetView;
nsPoint offset(0,0);
nsRect oldTargetRect(mCurrentTargetRect);
mCurrentTargetRect = mCurrentEventFrame->GetRect();
mCurrentTargetView = mCurrentEventFrame->GetView();
if (!mCurrentTargetView ) {
mCurrentEventFrame->GetOffsetFromView(offset, &mCurrentTargetView);
}
if (mCurrentTargetView) {
mCurrentTargetRect.x = offset.x;
mCurrentTargetRect.y = offset.y;
// use aView or mCurrentTargetView??
if ((mCurrentTargetRect != oldTargetRect) ||
(mCurrentTargetView != oldView)) {
nsIViewManager* vm = GetViewManager();
if (vm) {
vm->UpdateView(mCurrentTargetView,mCurrentTargetRect,0);
if (oldView)
vm->UpdateView(oldView,oldTargetRect,0);
}
}
}
}
ShowEventTargetDebug();
#endif
PopCurrentEventInfo();
}
else {
} else {
// Focus events need to be dispatched even if no frame was found, since
// we don't want the focus controller to be out of sync.
@ -5899,16 +5847,103 @@ PresShell::HandleEvent(nsIView *aView,
else if (NS_IS_KEY_EVENT(aEvent)) {
// Keypress events in new blank tabs should not be completely thrown away.
// Retarget them -- the parent chrome shell might make use of them.
return RetargetEventToParent(aView, aEvent, aEventStatus, aForceHandle,
aHandled, mCurrentEventContent);
return RetargetEventToParent(aView, aEvent, aEventStatus,
mCurrentEventContent);
}
aHandled = PR_FALSE;
}
return rv;
}
#ifdef NS_DEBUG
void
PresShell::ShowEventTargetDebug()
{
if ((nsIFrameDebug::GetShowEventTargetFrameBorder()) &&
(GetCurrentEventFrame())) {
nsIView *oldView = mCurrentTargetView;
nsPoint offset(0,0);
nsRect oldTargetRect(mCurrentTargetRect);
mCurrentTargetRect = mCurrentEventFrame->GetRect();
mCurrentTargetView = mCurrentEventFrame->GetView();
if (!mCurrentTargetView ) {
mCurrentEventFrame->GetOffsetFromView(offset, &mCurrentTargetView);
}
if (mCurrentTargetView) {
mCurrentTargetRect.x = offset.x;
mCurrentTargetRect.y = offset.y;
// use aView or mCurrentTargetView??
if ((mCurrentTargetRect != oldTargetRect) ||
(mCurrentTargetView != oldView)) {
nsIViewManager* vm = GetViewManager();
if (vm) {
vm->UpdateView(mCurrentTargetView,mCurrentTargetRect,0);
if (oldView)
vm->UpdateView(oldView,oldTargetRect,0);
}
}
}
}
}
#endif
nsresult
PresShell::HandlePositionedEvent(nsIView* aView,
nsIFrame* aTargetFrame,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
{
nsresult rv = NS_OK;
PushCurrentEventInfo(nsnull, nsnull);
mCurrentEventFrame = aTargetFrame;
if (mCurrentEventFrame) {
nsCOMPtr<nsIContent> targetElement;
mCurrentEventFrame->GetContentForEvent(mPresContext, aEvent,
getter_AddRefs(targetElement));
// If there is no content for this frame, target it anyway. Some
// frames can be targeted but do not have content, particularly
// windows with scrolling off.
if (targetElement) {
// Bug 103055, bug 185889: mouse events apply to *elements*, not all
// nodes. Thus we get the nearest element parent here.
// XXX we leave the frame the same even if we find an element
// parent, so that the text frame will receive the event (selection
// and friends are the ones who care about that anyway)
//
// We use weak pointers because during this tight loop, the node
// will *not* go away. And this happens on every mousemove.
while (targetElement &&
!targetElement->IsContentOfType(nsIContent::eELEMENT)) {
targetElement = targetElement->GetParent();
}
// If we found an element, target it. Otherwise, target *nothing*.
if (!targetElement) {
mCurrentEventContent = nsnull;
mCurrentEventFrame = nsnull;
} else if (targetElement != mCurrentEventContent) {
mCurrentEventContent = targetElement;
}
}
}
if (GetCurrentEventFrame()) {
rv = HandleEventInternal(aEvent, aView,
NS_EVENT_FLAG_INIT, aEventStatus);
}
#ifdef NS_DEBUG
ShowEventTargetDebug();
#endif
PopCurrentEventInfo();
return rv;
}
NS_IMETHODIMP
PresShell::HandleEventWithTarget(nsEvent* aEvent, nsIFrame* aFrame, nsIContent* aContent, PRUint32 aFlags, nsEventStatus* aStatus)
{

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

@ -44,6 +44,7 @@
#include "nsCSSPseudoElements.h"
#include "nsINameSpaceManager.h"
#include "nsStyleSet.h"
#include "nsDisplayList.h"
#define ACTIVE "active"
#define HOVER "hover"
@ -92,19 +93,66 @@ nsButtonFrameRenderer::isDisabled()
nsHTMLAtoms::disabled);
}
void
nsButtonFrameRenderer::PaintButton (nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
const nsRect& aRect)
class nsDisplayButtonBorderBackground : public nsDisplayItem {
public:
nsDisplayButtonBorderBackground(nsButtonFrameRenderer* aRenderer) : mBFR(aRenderer) {}
virtual nsIFrame* GetUnderlyingFrame() { return mBFR->GetFrame(); }
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt) {
return mBFR->GetFrame();
}
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("ButtonBorderBackground")
private:
nsButtonFrameRenderer* mBFR;
};
class nsDisplayButtonForeground : public nsDisplayItem {
public:
nsDisplayButtonForeground(nsButtonFrameRenderer* aRenderer) : mBFR(aRenderer) {}
virtual nsIFrame* GetUnderlyingFrame() { return mBFR->GetFrame(); }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("ButtonForeground")
private:
nsButtonFrameRenderer* mBFR;
};
void nsDisplayButtonBorderBackground::Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect)
{
//printf("painted width='%d' height='%d'\n",aRect.width, aRect.height);
nsIFrame* f = mBFR->GetFrame();
NS_ASSERTION(f, "No frame?");
nsPresContext* pc = f->GetPresContext();
nsRect r = nsRect(aBuilder->ToReferenceFrame(f), f->GetSize());
// draw the border and background inside the focus and outline borders
PaintBorderAndBackground(aPresContext, aRenderingContext, aDirtyRect, aRect);
mBFR->PaintBorderAndBackground(pc, *aCtx, aDirtyRect, r);
}
void nsDisplayButtonForeground::Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect)
{
nsIFrame* f = mBFR->GetFrame();
NS_ASSERTION(f, "No frame?");
nsPresContext* pc = f->GetPresContext();
nsRect r = nsRect(aBuilder->ToReferenceFrame(f), f->GetSize());
// draw the focus and outline borders
PaintOutlineAndFocusBorders(aPresContext, aRenderingContext, aDirtyRect, aRect);
mBFR->PaintOutlineAndFocusBorders(pc, *aCtx, aDirtyRect, r);
}
nsresult
nsButtonFrameRenderer::DisplayButton(nsDisplayListBuilder* aBuilder,
nsDisplayList* aBackground,
nsDisplayList* aForeground)
{
nsresult rv = aBackground->AppendNewToTop(new (aBuilder)
nsDisplayButtonBorderBackground(this));
NS_ENSURE_SUCCESS(rv, rv);
return aForeground->AppendNewToTop(new (aBuilder)
nsDisplayButtonForeground(this));
}
void

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

@ -57,23 +57,22 @@ class nsStyleChangeList;
class nsButtonFrameRenderer {
public:
nsButtonFrameRenderer();
virtual ~nsButtonFrameRenderer();
nsButtonFrameRenderer();
virtual ~nsButtonFrameRenderer();
/**
* Create display list items for the button
*/
nsresult DisplayButton(nsDisplayListBuilder* aBuilder,
nsDisplayList* aBackground, nsDisplayList* aForeground);
// These three functions all assume a "background" layer within the
// button, which is itself in the foreground layer.
virtual void PaintButton(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
const nsRect& aRect);
virtual void PaintOutlineAndFocusBorders(nsPresContext* aPresContext,
void PaintOutlineAndFocusBorders(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
const nsRect& aRect);
virtual void PaintBorderAndBackground(nsPresContext* aPresContext,
void PaintBorderAndBackground(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
const nsRect& aRect);
@ -114,8 +113,6 @@ private:
nsRefPtr<nsStyleContext> mOuterFocusStyle;
nsFrame* mFrame;
nsRect mOutlineRect;
};

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

@ -86,6 +86,7 @@
#include "nsStyleSet.h"
#include "nsNodeInfoManager.h"
#include "nsContentCreatorFunctions.h"
#include "nsDisplayList.h"
#ifdef MOZ_XUL
#include "nsIXULDocument.h" // Temporary fix for Bug 36558
@ -1535,30 +1536,6 @@ nsComboboxControlFrame::Reflow(nsPresContext* aPresContext,
//--------------------------------------------------------------
nsIFrame*
nsComboboxControlFrame::GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer)
{
// The button is getting the hover events so...
// None of the children frames of the combobox get
// the events. (like the button frame), that way
// all event based style rules affect the combobox
// and not the any of the child frames. (The inability
// of the parent to be in the :hover state at the same
// time as its children is really a bug (#5693 / #33736)
// in the implementation of :hover.)
// It would be theoretically more elegant to check the
// children when not disabled, and then use event
// capturing. It would correctly handle situations (obscure!!)
// where the children were visible but the parent was not.
// Now the functionality of the OPTIONs depends on the SELECT
// being visible. Oh well...
return nsFrame::GetFrameForPoint(aPoint, aWhichLayer);
}
//--------------------------------------------------------------
#ifdef NS_DEBUG
@ -2115,14 +2092,6 @@ nsComboboxControlFrame::GetAdditionalChildListName(PRInt32 aIndex) const
return nsnull;
}
PRIntn
nsComboboxControlFrame::GetSkipSides() const
{
// Don't skip any sides during border rendering
return 0;
}
//----------------------------------------------------------------------
//nsIRollupListener
//----------------------------------------------------------------------
@ -2155,79 +2124,98 @@ nsComboboxControlFrame::UpdateRecentIndex(PRInt32 aIndex)
return index;
}
NS_METHOD
nsComboboxControlFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
class nsDisplayComboboxFocus : public nsDisplayItem {
public:
nsDisplayComboboxFocus(nsComboboxControlFrame* aFrame) : mFrame(aFrame) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("ComboboxFocus")
private:
nsComboboxControlFrame* mFrame;
};
void nsDisplayComboboxFocus::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
{
mFrame->PaintFocus(*aCtx, aBuilder->ToReferenceFrame(mFrame));
}
NS_IMETHODIMP
nsComboboxControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
PRBool isVisible;
if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) {
return NS_OK;
}
#ifdef NOISY
printf("%p paint layer %d at (%d, %d, %d, %d)\n", this, aWhichLayer,
printf("%p paint at (%d, %d, %d, %d)\n", this,
aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
#endif
// We paint everything in the foreground so that the form control's
// parents cannot paint over it in other passes (bug 95826).
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
nsAreaFrame::Paint(aPresContext, aRenderingContext, aDirtyRect,
NS_FRAME_PAINT_LAYER_BACKGROUND);
nsAreaFrame::Paint(aPresContext, aRenderingContext, aDirtyRect,
NS_FRAME_PAINT_LAYER_FLOATS);
nsAreaFrame::Paint(aPresContext, aRenderingContext, aDirtyRect,
NS_FRAME_PAINT_LAYER_FOREGROUND);
// nsITheme should take care of drawing the focus border, but currently does so only on Mac.
// If all of the nsITheme implementations are fixed to draw the focus border correctly,
// this #ifdef should be replaced with a -moz-appearance / ThemeSupportsWidget() check.
if (!ToolkitHasNativePopup() && mDisplayFrame) {
aRenderingContext.PushState();
nsRect clipRect = mDisplayFrame->GetRect();
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect);
PaintChild(aPresContext, aRenderingContext, aDirtyRect,
mDisplayFrame, NS_FRAME_PAINT_LAYER_BACKGROUND);
PaintChild(aPresContext, aRenderingContext, aDirtyRect,
mDisplayFrame, NS_FRAME_PAINT_LAYER_FOREGROUND);
/////////////////////
// draw focus
// XXX This is only temporary
// Only paint the focus if we're visible
if (GetStyleVisibility()->IsVisible()) {
if (!nsFormControlHelper::GetDisabled(mContent) && mFocused == this) {
aRenderingContext.SetLineStyle(nsLineStyle_kDotted);
aRenderingContext.SetColor(0);
} else {
aRenderingContext.SetColor(GetStyleBackground()->mBackgroundColor);
aRenderingContext.SetLineStyle(nsLineStyle_kSolid);
}
//aRenderingContext.DrawRect(clipRect);
float p2t = aPresContext->PixelsToTwips();
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
clipRect.width -= onePixel;
clipRect.height -= onePixel;
aRenderingContext.DrawLine(clipRect.x, clipRect.y,
clipRect.x+clipRect.width, clipRect.y);
aRenderingContext.DrawLine(clipRect.x+clipRect.width, clipRect.y,
clipRect.x+clipRect.width, clipRect.y+clipRect.height);
aRenderingContext.DrawLine(clipRect.x+clipRect.width, clipRect.y+clipRect.height,
clipRect.x, clipRect.y+clipRect.height);
aRenderingContext.DrawLine(clipRect.x, clipRect.y+clipRect.height,
clipRect.x, clipRect.y);
aRenderingContext.DrawLine(clipRect.x, clipRect.y+clipRect.height,
clipRect.x, clipRect.y);
}
/////////////////////
aRenderingContext.PopState();
}
if (aBuilder->IsForEventDelivery()) {
// Don't allow children to receive events.
// REVIEW: following old GetFrameForPoint
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
} else {
// REVIEW: Our in-flow child frames are inline-level so they will paint in our
// content list, so we don't need to mess with layers.
nsresult rv = nsAreaFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
NS_ENSURE_SUCCESS(rv, rv);
}
// Call to the base class to draw selection borders when appropriate
return nsFrame::Paint(aPresContext,aRenderingContext,aDirtyRect,aWhichLayer);
// nsITheme should take care of drawing the focus border, but currently does so only on Mac.
// If all of the nsITheme implementations are fixed to draw the focus border correctly,
// this #ifdef should be replaced with a -moz-appearance / ThemeSupportsWidget() check.
if (!ToolkitHasNativePopup() && mDisplayFrame &&
IsVisibleForPainting(aBuilder)) {
// REVIEW: We used to paint mDisplayFrame *again* here, with clipping,
// but that makes no sense.
nsresult rv = aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayComboboxFocus(this));
NS_ENSURE_SUCCESS(rv, rv);
}
return DisplaySelectionOverlay(aBuilder, aLists);
}
void nsComboboxControlFrame::PaintFocus(nsIRenderingContext& aRenderingContext,
nsPoint aPt) {
aRenderingContext.PushState();
nsRect clipRect = mDisplayFrame->GetRect() + aPt;
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect);
// REVIEW: Why does the old code paint mDisplayFrame again? We've
// already painted it in the children above. So clipping it here won't do
// us much good.
/////////////////////
// draw focus
// XXX This is only temporary
if (!nsFormControlHelper::GetDisabled(mContent) && mFocused == this) {
aRenderingContext.SetLineStyle(nsLineStyle_kDotted);
aRenderingContext.SetColor(0);
} else {
aRenderingContext.SetColor(GetStyleBackground()->mBackgroundColor);
aRenderingContext.SetLineStyle(nsLineStyle_kSolid);
}
//aRenderingContext.DrawRect(clipRect);
float p2t = GetPresContext()->PixelsToTwips();
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
clipRect.width -= onePixel;
clipRect.height -= onePixel;
aRenderingContext.DrawLine(clipRect.x, clipRect.y,
clipRect.x+clipRect.width, clipRect.y);
aRenderingContext.DrawLine(clipRect.x+clipRect.width, clipRect.y,
clipRect.x+clipRect.width, clipRect.y+clipRect.height);
aRenderingContext.DrawLine(clipRect.x+clipRect.width, clipRect.y+clipRect.height,
clipRect.x, clipRect.y+clipRect.height);
aRenderingContext.DrawLine(clipRect.x, clipRect.y+clipRect.height,
clipRect.x, clipRect.y);
aRenderingContext.DrawLine(clipRect.x, clipRect.y+clipRect.height,
clipRect.x, clipRect.y);
aRenderingContext.PopState();
}
//----------------------------------------------------------------------

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

@ -123,11 +123,12 @@ public:
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus);
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
void PaintFocus(nsIRenderingContext& aRenderingContext, nsPoint aPt);
#ifdef NS_DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const;
#endif
@ -138,9 +139,6 @@ public:
nsIFrame* aChildList);
virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer);
virtual nsIFrame* GetContentInsertionFrame();
// nsIFormControlFrame
@ -202,9 +200,6 @@ protected:
nsHTMLReflowMetrics& aDesiredSize);
#endif
// nsHTMLContainerFrame
virtual PRIntn GetSkipSides() const;
// Utilities
nsresult ReflowComboChildFrame(nsIFrame* aFrame,
nsPresContext* aPresContext,

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

@ -61,6 +61,7 @@
#include "nsIAccessibilityService.h"
#endif
#include "nsIServiceManager.h"
#include "nsDisplayList.h"
class nsLegendFrame;
@ -78,13 +79,12 @@ public:
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
virtual PRBool CanPaintBackground();
void PaintBorderBackground(nsIRenderingContext& aRenderingContext,
nsPoint aPt, const nsRect& aDirtyRect);
NS_IMETHOD AppendFrames(nsIAtom* aListName,
nsIFrame* aFrameList);
@ -94,9 +94,6 @@ public:
NS_IMETHOD RemoveFrame(nsIAtom* aListName,
nsIFrame* aOldFrame);
virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer);
virtual nsIAtom* GetType() const;
virtual PRBool IsContainingBlock() const;
@ -166,118 +163,146 @@ nsFieldSetFrame::SetInitialChildList(nsPresContext* aPresContext,
return nsHTMLContainerFrame::SetInitialChildList(aPresContext, nsnull, aChildList);
}
// this is identical to nsHTMLContainerFrame::Paint except for the background and border.
NS_IMETHODIMP
nsFieldSetFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
class nsDisplayFieldSetBorderBackground : public nsDisplayItem {
public:
nsDisplayFieldSetBorderBackground(nsFieldSetFrame* aFrame) : mFrame(aFrame) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("FieldSetBorderBackground")
private:
nsFieldSetFrame* mFrame;
};
nsIFrame* nsDisplayFieldSetBorderBackground::HitTest(nsDisplayListBuilder* aBuilder,
nsPoint aPt)
{
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
// Paint our background and border
PRBool isVisible;
if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) &&
isVisible && mRect.width && mRect.height) {
PRIntn skipSides = GetSkipSides();
const nsStyleBorder* borderStyle = GetStyleBorder();
const nsStylePadding* paddingStyle = GetStylePadding();
nscoord topBorder = borderStyle->GetBorderWidth(NS_SIDE_TOP);
nscoord yoff = 0;
// if the border is smaller than the legend. Move the border down
// to be centered on the legend.
if (topBorder < mLegendRect.height)
yoff = (mLegendRect.height - topBorder)/2;
nsRect rect(0, yoff, mRect.width, mRect.height - yoff);
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *borderStyle,
*paddingStyle, PR_TRUE);
if (mLegendFrame) {
// Use the rect of the legend frame, not mLegendRect, so we draw our
// border under the legend's left and right margins.
const nsRect & legendRect = mLegendFrame->GetRect();
// we should probably use PaintBorderEdges to do this but for now just use clipping
// to achieve the same effect.
// draw left side
nsRect clipRect(rect);
clipRect.width = legendRect.x - rect.x;
clipRect.height = topBorder;
aRenderingContext.PushState();
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *borderStyle, mStyleContext, skipSides);
aRenderingContext.PopState();
// draw right side
clipRect = rect;
clipRect.x = legendRect.x + legendRect.width;
clipRect.width -= (legendRect.x + legendRect.width);
clipRect.height = topBorder;
aRenderingContext.PushState();
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *borderStyle, mStyleContext, skipSides);
aRenderingContext.PopState();
// draw bottom
clipRect = rect;
clipRect.y += topBorder;
clipRect.height = mRect.height - (yoff + topBorder);
aRenderingContext.PushState();
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *borderStyle, mStyleContext, skipSides);
aRenderingContext.PopState();
} else {
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect,
nsRect(0,0,mRect.width, mRect.height),
*borderStyle, mStyleContext, skipSides);
}
}
}
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
#ifdef DEBUG
if ((NS_FRAME_PAINT_LAYER_DEBUG == aWhichLayer) && GetShowFrameBorders()) {
if (HasView()) {
aRenderingContext.SetColor(NS_RGB(0,0,255));
}
else {
aRenderingContext.SetColor(NS_RGB(255,0,0));
}
aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height);
}
#endif
DO_GLOBAL_REFLOW_COUNT_DSP("nsFieldSetFrame", &aRenderingContext);
return NS_OK;
// aPt is guaranteed to be in this item's bounds. We do the hit test based on the
// frame bounds even though our background doesn't cover the whole frame.
// It's not clear whether this is correct.
return mFrame;
}
PRBool
nsFieldSetFrame::CanPaintBackground()
void
nsDisplayFieldSetBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
{
// If we have a legend, we won't be painting our background across our whole
// rect. So return false here, since we'll usually have a legend.
return PR_FALSE;
mFrame->PaintBorderBackground(*aCtx, aBuilder->ToReferenceFrame(mFrame),
aDirtyRect);
}
NS_IMETHODIMP
nsFieldSetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) {
// Paint our background and border in a special way.
// REVIEW: We don't really need to check frame emptiness here; if it's empty,
// the background/border display item won't do anything, and if it isn't empty,
// we need to paint the outline
if (IsVisibleForPainting(aBuilder)) {
// don't bother checking to see if we really have a border or background.
// we usually will have a border.
nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayFieldSetBorderBackground(this));
NS_ENSURE_SUCCESS(rv, rv);
rv = DisplayOutlineUnconditional(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
}
if (mLegendFrame) {
nsDisplayListSet set(aLists, aLists.Content());
nsresult rv = BuildDisplayListForChild(aBuilder, mLegendFrame, aDirtyRect, set);
NS_ENSURE_SUCCESS(rv, rv);
}
if (!mContentFrame)
return NS_OK;
// Allow mContentFrame's background to go onto our BorderBackground() list,
// this is OK since it won't have a real background except for event
// handling.
return BuildDisplayListForChild(aBuilder, mContentFrame, aDirtyRect, aLists);
// REVIEW: debug borders are always painted by nsFrame::BuildDisplayListForChild
// (or by the PresShell for the top level painted frame)
}
void
nsFieldSetFrame::PaintBorderBackground(nsIRenderingContext& aRenderingContext,
nsPoint aPt, const nsRect& aDirtyRect)
{
PRIntn skipSides = GetSkipSides();
const nsStyleBorder* borderStyle = GetStyleBorder();
const nsStylePadding* paddingStyle = GetStylePadding();
nscoord topBorder = borderStyle->GetBorderWidth(NS_SIDE_TOP);
nscoord yoff = 0;
nsPresContext* presContext = GetPresContext();
// if the border is smaller than the legend. Move the border down
// to be centered on the legend.
if (topBorder < mLegendRect.height)
yoff = (mLegendRect.height - topBorder)/2;
nsRect rect(aPt.x, aPt.y + yoff, mRect.width, mRect.height - yoff);
nsCSSRendering::PaintBackground(presContext, aRenderingContext, this,
aDirtyRect, rect, *borderStyle,
*paddingStyle, PR_TRUE);
if (mLegendFrame) {
// Use the rect of the legend frame, not mLegendRect, so we draw our
// border under the legend's left and right margins.
nsRect legendRect = mLegendFrame->GetRect() + aPt;
// we should probably use PaintBorderEdges to do this but for now just use clipping
// to achieve the same effect.
// draw left side
nsRect clipRect(rect);
clipRect.width = legendRect.x - rect.x;
clipRect.height = topBorder;
aRenderingContext.PushState();
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect);
nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
aDirtyRect, rect, *borderStyle, mStyleContext, skipSides);
aRenderingContext.PopState();
// draw right side
clipRect = rect;
clipRect.x = legendRect.XMost();
clipRect.width = rect.XMost() - legendRect.XMost();
clipRect.height = topBorder;
aRenderingContext.PushState();
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect);
nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
aDirtyRect, rect, *borderStyle, mStyleContext, skipSides);
aRenderingContext.PopState();
// draw bottom
clipRect = rect;
clipRect.y += topBorder;
clipRect.height = mRect.height - (yoff + topBorder);
aRenderingContext.PushState();
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect);
nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
aDirtyRect, rect, *borderStyle, mStyleContext, skipSides);
aRenderingContext.PopState();
} else {
nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
aDirtyRect,
nsRect(aPt, mRect.Size()),
*borderStyle, mStyleContext, skipSides);
}
}
NS_IMETHODIMP
@ -625,15 +650,6 @@ nsFieldSetFrame::RemoveFrame(nsIAtom* aListName,
return mContentFrame->RemoveFrame(aListName, aOldFrame);
}
nsIFrame*
nsFieldSetFrame::GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer)
{
// this should act like a block, so we need to override
return GetFrameForPointUsing(aPoint, nsnull, aWhichLayer,
aWhichLayer == NS_FRAME_PAINT_LAYER_BACKGROUND);
}
#ifdef ACCESSIBILITY
NS_IMETHODIMP nsFieldSetFrame::GetAccessible(nsIAccessible** aAccessible)
{

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

@ -37,7 +37,6 @@
#include "nsFileControlFrame.h"
#include "nsIContent.h"
#include "prtypes.h"
#include "nsIAtom.h"
@ -71,6 +70,7 @@
#include "nsNodeInfoManager.h"
#include "nsContentCreatorFunctions.h"
#include "nsContentUtils.h"
#include "nsDisplayList.h"
#define SYNC_TEXT 0x1
#define SYNC_BUTTON 0x2
@ -552,23 +552,6 @@ nsFileControlFrame::IsLeaf() const
return PR_TRUE;
}
nsIFrame*
nsFileControlFrame::GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer)
{
#ifndef DEBUG_NEWFRAME
nsRect thisRect(nsPoint(0,0), GetSize());
if (nsFormControlHelper::GetDisabled(mContent) && thisRect.Contains(aPoint)) {
if (GetStyleVisibility()->IsVisible()) {
return this;
}
} else {
return nsAreaFrame::GetFrameForPoint(aPoint, aWhichLayer);
}
#endif
return nsnull;
}
#ifdef NS_DEBUG
NS_IMETHODIMP
nsFileControlFrame::GetFrameName(nsAString& aResult) const
@ -609,23 +592,27 @@ nsFileControlFrame::GetFormProperty(nsIAtom* aName, nsAString& aValue) const
return NS_OK;
}
NS_METHOD
nsFileControlFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
NS_IMETHODIMP
nsFileControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
PRBool isVisible;
if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) {
return NS_OK;
}
nsresult rv = nsAreaFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
if (NS_FAILED(rv)) return rv;
nsresult rv = nsAreaFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
if (NS_FAILED(rv))
return rv;
return nsFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
}
// Disabled file controls don't pass mouse events to their children, so we
// put an invisible item in the display list above the children
// just to catch events
// REVIEW: I'm not sure why we do this, but that's what nsFileControlFrame::
// GetFrameForPoint was doing
if (nsFormControlHelper::GetDisabled(mContent) &&
IsVisibleForPainting(aBuilder)) {
nsDisplayItem* item = new (aBuilder) nsDisplayEventReceiver(this);
if (!item)
return NS_ERROR_OUT_OF_MEMORY;
aLists.Content()->AppendToTop(item);
}
return DisplaySelectionOverlay(aBuilder, aLists);
}

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

@ -68,11 +68,10 @@ public:
return nsAreaFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
}
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
// nsIFormControlFrame
@ -93,8 +92,6 @@ public:
NS_IMETHOD GetFrameName(nsAString& aResult) const;
#endif
virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);

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

@ -382,73 +382,10 @@ nsFormControlFrame::SetClickPoint(nscoord aX, nscoord aY)
mLastClickPoint.y = aY;
}
// XXX it would be cool if form element used our rendering sw, then
// they could be blended, and bordered, and so on...
NS_METHOD
nsFormControlFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
{
PRBool isVisible;
if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) {
return NS_OK;
}
nsresult rv = NS_OK;
if (aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND) {
rv = nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect,
NS_FRAME_PAINT_LAYER_BACKGROUND);
if (NS_FAILED(rv))
return rv;
// draw selection borders when appropriate
rv = nsFrame::Paint(aPresContext, aRenderingContext, aDirtyRect,
NS_FRAME_PAINT_LAYER_BACKGROUND);
if (NS_FAILED(rv))
return rv;
rv = nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect,
NS_FRAME_PAINT_LAYER_FLOATS);
if (NS_FAILED(rv))
return rv;
// draw selection borders when appropriate
rv = nsFrame::Paint(aPresContext, aRenderingContext, aDirtyRect,
NS_FRAME_PAINT_LAYER_FLOATS);
if (NS_FAILED(rv))
return rv;
rv = nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect,
NS_FRAME_PAINT_LAYER_FOREGROUND);
if (NS_FAILED(rv))
return rv;
// draw selection borders when appropriate
rv = nsFrame::Paint(aPresContext, aRenderingContext, aDirtyRect,
NS_FRAME_PAINT_LAYER_FOREGROUND);
}
return rv;
}
nsIFrame*
nsFormControlFrame::GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer)
{
nsIFrame* frame = nsnull;
if (aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND) {
frame = nsLeafFrame::GetFrameForPoint(aPoint,
NS_FRAME_PAINT_LAYER_FOREGROUND);
if (frame)
return frame;
frame = nsLeafFrame::GetFrameForPoint(aPoint,
NS_FRAME_PAINT_LAYER_FLOATS);
if (frame)
return frame;
frame = nsLeafFrame::GetFrameForPoint(aPoint,
NS_FRAME_PAINT_LAYER_BACKGROUND);
}
return frame;
}
// REVIEW: All nsFormControlFrame does different with painting is to put
// its standard decorations entirely in the "foreground" layer. But our only
// two subclasses are radio buttons and checkboxes, which are normally inline
// elements, so this will happen anyway.
void
nsFormControlFrame::GetDesiredSize(nsPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,

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

@ -104,19 +104,6 @@ public:
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus);
/**
* Draw this frame within the context of a presentation context and rendering context
* @see nsIFrame::Paint
*/
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD SetInitialChildList(nsPresContext* aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList);

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

@ -54,7 +54,7 @@
#include "nsIDOMHTMLInputElement.h"
#include "nsITheme.h"
#include "imgIRequest.h"
#include "nsDisplayList.h"
//------------------------------------------------------------
nsIFrame*
@ -161,97 +161,110 @@ nsGfxCheckboxControlFrame::OnChecked(nsPresContext* aPresContext,
return aChecked;
}
static void PaintCheckMarkFromStyle(nsIFrame* aFrame,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect, nsPoint aPt) {
NS_STATIC_CAST(nsGfxCheckboxControlFrame*, aFrame)
->PaintCheckBoxFromStyle(*aCtx, aPt, aDirtyRect);
}
class nsDisplayCheckMark : public nsDisplayItem {
public:
nsDisplayCheckMark(nsGfxCheckboxControlFrame* aFrame) : mFrame(aFrame) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
virtual const char* Name() { return "CheckMark"; }
private:
nsGfxCheckboxControlFrame* mFrame;
};
void
nsDisplayCheckMark::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect) {
mFrame->PaintCheckBox(*aCtx, aBuilder->ToReferenceFrame(mFrame),
aDirtyRect);
}
//------------------------------------------------------------
void
nsGfxCheckboxControlFrame::PaintCheckBox(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
nsGfxCheckboxControlFrame::PaintCheckBox(nsIRenderingContext& aRenderingContext,
nsPoint aPt,
const nsRect& aDirtyRect)
{
const nsStyleDisplay* disp = GetStyleDisplay();
if (disp->mAppearance) {
nsITheme *theme = aPresContext->GetTheme();
if (theme && theme->ThemeSupportsWidget(aPresContext, this, disp->mAppearance))
return; // No need to paint the checkbox. The theme will do it.
}
// Get current checked state through content model.
if (!GetCheckboxState())
return; // we're not checked, nothing to paint.
// REVIEW: moved the mAppearance test out so we avoid constructing
// a display item if it's not needed
aRenderingContext.PushState();
nsMargin borderPadding(0,0,0,0);
CalcBorderPadding(borderPadding);
nsRect checkRect(0,0, mRect.width, mRect.height);
nsRect checkRect(aPt, mRect.Size());
checkRect.Deflate(borderPadding);
const nsStyleColor* color = GetStyleColor();
aRenderingContext.SetColor(color->mColor);
nsFormControlHelper::PaintCheckMark(aRenderingContext,
aPresContext->ScaledPixelsToTwips(),
GetPresContext()->ScaledPixelsToTwips(),
checkRect);
aRenderingContext.PopState();
}
//------------------------------------------------------------
NS_METHOD
nsGfxCheckboxControlFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
NS_IMETHODIMP
nsGfxCheckboxControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
PRBool isVisible;
if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) {
return NS_OK;
nsresult rv = nsFormControlFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
NS_ENSURE_SUCCESS(rv, rv);
// Get current checked state through content model.
if (!GetCheckboxState() || !IsVisibleForPainting(aBuilder))
return NS_OK; // we're not checked or not visible, nothing to paint.
if (IsThemed())
return NS_OK; // No need to paint the checkmark. The theme will do it.
// Paint the checkmark
// REVIEW: this used to check !mCheckButtonFaceStyle, but that's clearly
// wrong ... look at the blame diff, it was reversed by accident
if (mCheckButtonFaceStyle) {
const nsStyleBackground* myColor = mCheckButtonFaceStyle->GetStyleBackground();
// REVIEW: I'm not sure if this is really sane. We should at least be also
// checking for other properties too. But this is what we had.
if (myColor->mBackgroundImage)
return aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayGeneric(this, PaintCheckMarkFromStyle, "CheckMarkFromStyle"));
}
// Paint the background
nsresult rv = nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
PRBool doDefaultPainting = PR_TRUE;
// Paint the checkmark
const nsStyleBorder* myBorder = mCheckButtonFaceStyle->GetStyleBorder();
if (!mCheckButtonFaceStyle && GetCheckboxState()) {
const nsStyleBackground* myColor = mCheckButtonFaceStyle->GetStyleBackground();
return aLists.Content()->AppendNewToTop(new (aBuilder) nsDisplayCheckMark(this));
// REVIEW: I'm not really sure why we were painting the outline again
// here ... the superclass call at the top should have painted it already.
// Just a bug I guess.
}
if (myColor->mBackgroundImage) {
const nsStylePadding* myPadding = mCheckButtonFaceStyle->GetStylePadding();
const nsStylePosition* myPosition = mCheckButtonFaceStyle->GetStylePosition();
void
nsGfxCheckboxControlFrame::PaintCheckBoxFromStyle(
nsIRenderingContext& aRenderingContext, nsPoint aPt, const nsRect& aDirtyRect) {
const nsStylePadding* myPadding = mCheckButtonFaceStyle->GetStylePadding();
const nsStylePosition* myPosition = mCheckButtonFaceStyle->GetStylePosition();
const nsStyleBorder* myBorder = mCheckButtonFaceStyle->GetStyleBorder();
nscoord width = myPosition->mWidth.GetCoordValue();
nscoord height = myPosition->mHeight.GetCoordValue();
// Position the button centered within the radio control's rectangle.
nscoord x = (mRect.width - width) / 2;
nscoord y = (mRect.height - height) / 2;
nsRect rect(x, y, width, height);
nscoord width = myPosition->mWidth.GetCoordValue();
nscoord height = myPosition->mHeight.GetCoordValue();
// Position the button centered within the radio control's rectangle.
nscoord x = (mRect.width - width) / 2;
nscoord y = (mRect.height - height) / 2;
nsRect rect(aPt.x + x, aPt.y + y, width, height);
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *myBorder, *myPadding,
PR_FALSE);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *myBorder, mCheckButtonFaceStyle, 0);
doDefaultPainting = PR_FALSE;
}
}
nsRect rect(0, 0, mRect.width, mRect.height);
const nsStyleOutline* myOutline = GetStyleOutline();
nsCSSRendering::PaintOutline(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *myBorder, *myOutline,
mStyleContext, 0);
if (doDefaultPainting) {
PaintCheckBox(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
}
}
return rv;
nsCSSRendering::PaintBackground(GetPresContext(), aRenderingContext, this,
aDirtyRect, rect, *myBorder, *myPadding,
PR_FALSE);
nsCSSRendering::PaintBorder(GetPresContext(), aRenderingContext, this,
aDirtyRect, rect, *myBorder, mCheckButtonFaceStyle, 0);
}
//------------------------------------------------------------

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

@ -65,11 +65,9 @@ public:
}
#endif
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
#ifdef ACCESSIBILITY
NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
@ -93,17 +91,16 @@ public:
nsReflowStatus& aStatus);
#endif
void PaintCheckBox(nsIRenderingContext& aRenderingContext,
nsPoint aPt, const nsRect& aDirtyRect);
void PaintCheckBoxFromStyle(nsIRenderingContext& aRenderingContext,
nsPoint aPt, const nsRect& aDirtyRect);
protected:
PRBool GetCheckboxState();
protected:
virtual void PaintCheckBox(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
//GFX-rendered state variables
PRBool mInClickEvent;
nsStyleContext* mCheckButtonFaceStyle;

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

@ -52,6 +52,7 @@
#include "nsIServiceManager.h"
#include "nsIDOMNode.h"
#include "nsITheme.h"
#include "nsDisplayList.h"
nsIFrame*
NS_NewGfxRadioControlFrame(nsIPresShell* aPresShell)
@ -155,77 +156,82 @@ nsGfxRadioControlFrame::HandleEvent(nsPresContext* aPresContext,
//--------------------------------------------------------------
void
nsGfxRadioControlFrame::PaintRadioButton(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect)
nsGfxRadioControlFrame::PaintRadioButtonFromStyle(
nsIRenderingContext& aRenderingContext, nsPoint aPt, const nsRect& aDirtyRect)
{
const nsStyleDisplay* disp = GetStyleDisplay();
if (disp->mAppearance) {
nsITheme *theme = aPresContext->GetTheme();
if (theme && theme->ThemeSupportsWidget(aPresContext, this, disp->mAppearance))
return; // No need to paint the radio button. The theme will do it.
}
PRBool checked = PR_TRUE;
GetCurrentCheckState(&checked); // Get check state from the content model
const nsStyleBorder* myBorder = mRadioButtonFaceStyle->GetStyleBorder();
if (checked) {
// Paint the button for the radio button using CSS background rendering code
if (nsnull != mRadioButtonFaceStyle) {
const nsStyleBackground* myColor = mRadioButtonFaceStyle->GetStyleBackground();
const nsStyleColor* color = mRadioButtonFaceStyle->GetStyleColor();
const nsStylePadding* myPadding = mRadioButtonFaceStyle->GetStylePadding();
const nsStylePosition* myPosition = mRadioButtonFaceStyle->GetStylePosition();
// Paint the button for the radio button using CSS background rendering code
const nsStyleBackground* myColor = mRadioButtonFaceStyle->GetStyleBackground();
const nsStyleColor* color = mRadioButtonFaceStyle->GetStyleColor();
const nsStylePadding* myPadding = mRadioButtonFaceStyle->GetStylePadding();
const nsStylePosition* myPosition = mRadioButtonFaceStyle->GetStylePosition();
nscoord width = myPosition->mWidth.GetCoordValue();
nscoord height = myPosition->mHeight.GetCoordValue();
// Position the button centered within the radio control's rectangle.
nscoord x = (mRect.width - width) / 2;
nscoord y = (mRect.height - height) / 2;
nsRect rect(x, y, width, height);
nscoord width = myPosition->mWidth.GetCoordValue();
nscoord height = myPosition->mHeight.GetCoordValue();
// Position the button centered within the radio control's rectangle.
nscoord x = (mRect.width - width) / 2;
nscoord y = (mRect.height - height) / 2;
nsRect rect = nsRect(x, y, width, height) + aPt;
// So we will use PaintBackgroundWithSC to paint the dot,
// but it uses the mBackgroundColor for painting and we need to use the mColor
// so create a temporary style color struct and set it up appropriately
// XXXldb It would make more sense to use
// |aRenderingContext.FillEllipse| here, but on at least GTK that
// doesn't draw a round enough circle.
nsStyleBackground tmpColor = *myColor;
tmpColor.mBackgroundColor = color->mColor;
nsCSSRendering::PaintBackgroundWithSC(aPresContext, aRenderingContext,
this, aDirtyRect, rect,
tmpColor, *myBorder, *myPadding, PR_FALSE);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *myBorder, mRadioButtonFaceStyle, 0);
}
}
// So we will use PaintBackgroundWithSC to paint the dot,
// but it uses the mBackgroundColor for painting and we need to use the mColor
// so create a temporary style color struct and set it up appropriately
// XXXldb It would make more sense to use
// |aRenderingContext.FillEllipse| here, but on at least GTK that
// doesn't draw a round enough circle.
nsStyleBackground tmpColor = *myColor;
tmpColor.mBackgroundColor = color->mColor;
nsPresContext* pc = GetPresContext();
nsCSSRendering::PaintBackgroundWithSC(pc, aRenderingContext,
this, aDirtyRect, rect,
tmpColor, *myBorder, *myPadding, PR_FALSE);
nsCSSRendering::PaintBorder(pc, aRenderingContext, this,
aDirtyRect, rect, *myBorder, mRadioButtonFaceStyle, 0);
}
class nsDisplayRadioButtonFromStyle : public nsDisplayItem {
public:
nsDisplayRadioButtonFromStyle(nsGfxRadioControlFrame* aFrame) : mFrame(aFrame) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
virtual const char* Name() { return "RadioButton"; }
private:
nsGfxRadioControlFrame* mFrame;
};
void
nsDisplayRadioButtonFromStyle::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect) {
mFrame->PaintRadioButtonFromStyle(*aCtx, aBuilder->ToReferenceFrame(mFrame),
aDirtyRect);
}
//--------------------------------------------------------------
NS_METHOD
nsGfxRadioControlFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
NS_IMETHODIMP
nsGfxRadioControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
PRBool isVisible;
if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) {
nsresult rv = nsFormControlFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
NS_ENSURE_SUCCESS(rv, rv);
if (!IsVisibleForPainting(aBuilder))
return NS_OK;
}
// Paint the background
nsresult rv = nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
if (IsThemed())
return NS_OK; // No need to paint the radio button. The theme will do it.
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
PaintRadioButton(aPresContext, aRenderingContext, aDirtyRect);
}
nsRect rect(0, 0, mRect.width, mRect.height);
const nsStyleOutline* myOutline = GetStyleOutline();
const nsStyleBorder* myBorder = GetStyleBorder();
nsCSSRendering::PaintOutline(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *myBorder, *myOutline,
mStyleContext, 0);
return rv;
if (!mRadioButtonFaceStyle)
return NS_OK;
PRBool checked = PR_TRUE;
GetCurrentCheckState(&checked); // Get check state from the content model
if (!checked)
return NS_OK;
return aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayRadioButtonFromStyle(this));
}
@ -242,21 +248,4 @@ nsGfxRadioControlFrame::OnChecked(nsPresContext* aPresContext,
//----------------------------------------------------------------------
// Extra Debug Helper Methods
//----------------------------------------------------------------------
#ifdef DEBUG_rodsXXX
NS_IMETHODIMP
nsGfxRadioControlFrame::Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
DO_GLOBAL_REFLOW_COUNT("nsGfxRadioControlFrame", aReflowState.reason);
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
nsresult rv = nsNativeFormControlFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
COMPARE_QUIRK_SIZE("nsGfxRadioControlFrame", 12, 11)
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
return rv;
}
#endif

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

@ -75,21 +75,13 @@ public:
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus);
//
// XXX: The following paint methods are TEMPORARY. It is being used to get printing working
// under windows. Later it may be used to GFX-render the controls to the display.
// Expect this code to repackaged and moved to a new location in the future.
//
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
virtual void PaintRadioButton(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
void PaintRadioButtonFromStyle(nsIRenderingContext& aRenderingContext, nsPoint aPt,
const nsRect& aDirtyRect);
///XXX: End o the temporary methods
#ifdef DEBUG_rodsXXX

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

@ -70,6 +70,7 @@
#ifdef ACCESSIBILITY
#include "nsIAccessibilityService.h"
#endif
#include "nsDisplayList.h"
nsIFrame*
NS_NewHTMLButtonControlFrame(nsIPresShell* aPresShell)
@ -196,41 +197,27 @@ nsHTMLButtonControlFrame::HandleEvent(nsPresContext* aPresContext,
}
nsIFrame*
nsHTMLButtonControlFrame::GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer)
{
nsRect thisRect(nsPoint(0,0), GetSize());
if (aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND &&
thisRect.Contains(aPoint) && GetStyleVisibility()->IsVisible()) {
return this;
}
return nsnull;
}
NS_IMETHODIMP
nsHTMLButtonControlFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
nsHTMLButtonControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
PRBool isVisible;
if (aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND ||
(NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible)) {
return NS_OK;
nsDisplayList onTop;
if (IsVisibleForPainting(aBuilder)) {
nsresult rv = mRenderer.DisplayButton(aBuilder, aLists.BorderBackground(), &onTop);
NS_ENSURE_SUCCESS(rv, rv);
}
nsDisplayListCollection set;
nsresult rv =
BuildDisplayListForChild(aBuilder, mFrames.FirstChild(), aDirtyRect, set,
DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT);
NS_ENSURE_SUCCESS(rv, rv);
// That should put the display items in set.Content()
// Put the foreground outline and focus rects on top of the children
set.Content()->AppendToTop(&onTop);
nsRect rect(0, 0, mRect.width, mRect.height);
mRenderer.PaintButton(aPresContext, aRenderingContext, aDirtyRect, rect);
#if 0 // old way
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, NS_FRAME_PAINT_LAYER_BACKGROUND);
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, NS_FRAME_PAINT_LAYER_FLOATS);
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, NS_FRAME_PAINT_LAYER_FOREGROUND);
#else // temporary
// XXX This is temporary
// clips to its size minus the border
// but the real problem is the FirstChild (the AreaFrame)
@ -240,28 +227,17 @@ nsHTMLButtonControlFrame::Paint(nsPresContext* aPresContext,
nsMargin border;
border.SizeTo(0, 0, 0, 0);
borderStyle->CalcBorderFor(this, border);
nsRect rect(aBuilder->ToReferenceFrame(this), GetSize());
rect.Deflate(border);
aRenderingContext.PushState();
aRenderingContext.SetClipRect(rect, nsClipCombine_kIntersect);
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, NS_FRAME_PAINT_LAYER_BACKGROUND);
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, NS_FRAME_PAINT_LAYER_FLOATS);
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, NS_FRAME_PAINT_LAYER_FOREGROUND);
aRenderingContext.PopState();
#endif
// Paint outline
const nsStyleOutline* outlineStyle = GetStyleOutline();
nsCSSRendering::PaintOutline(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *borderStyle, *outlineStyle,
mStyleContext, 0);
rv = OverflowClip(aBuilder, set, aLists, rect);
NS_ENSURE_SUCCESS(rv, rv);
rv = DisplayOutline(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
// to draw border when selected in editor
return nsFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
return DisplaySelectionOverlay(aBuilder, aLists);
}

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

@ -68,11 +68,9 @@ public:
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
@ -85,9 +83,6 @@ public:
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus);
virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD Init(nsPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,

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

@ -103,19 +103,8 @@ nsIsIndexFrame::~nsIsIndexFrame()
}
}
NS_IMETHODIMP
nsIsIndexFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
{
PRBool isVisible;
if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) {
return NS_OK;
}
return nsAreaFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
}
// REVIEW: We don't need to override BuildDisplayList, nsAreaFrame will honour
// our visibility setting
NS_IMETHODIMP
nsIsIndexFrame::UpdatePromptLabel()

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

@ -60,12 +60,6 @@ public:
nsIsIndexFrame();
virtual ~nsIsIndexFrame();
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
// XXX Hack so we can squirrel away the pres context pointer for the KeyPress method
NS_IMETHOD Init(nsPresContext* aPresContext,
nsIContent* aContent,

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

@ -107,21 +107,8 @@ nsLegendFrame::Reflow(nsPresContext* aPresContext,
return nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
}
NS_IMETHODIMP
nsLegendFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
{
PRBool isVisible;
if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) {
return NS_OK;
}
return nsAreaFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
}
// REVIEW: We don't need to override BuildDisplayList, nsAreaFrame will honour
// our visibility setting
PRInt32 nsLegendFrame::GetAlign()
{
PRInt32 intValue = NS_STYLE_TEXT_ALIGN_LEFT;

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

@ -64,12 +64,6 @@ public:
NS_IMETHOD Destroy(nsPresContext *aPresContext);
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
virtual nsIAtom* GetType() const;
#ifdef NS_DEBUG

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

@ -93,6 +93,7 @@
#include "nsIDOMMouseMotionListener.h"
#include "nsIDOMKeyListener.h"
#include "nsLayoutUtils.h"
#include "nsDisplayList.h"
// Constants
const nscoord kMaxDropDownRows = 20; // This matches the setting for 4.x browsers
@ -342,73 +343,35 @@ nsListControlFrame::Destroy(nsPresContext *aPresContext)
}
NS_IMETHODIMP
nsListControlFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
nsListControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
if (!GetStyleVisibility()->IsVisible()) {
return PR_FALSE;
}
// We allow visibility:hidden <select>s to contain visible options.
// Don't allow painting of list controls when painting is suppressed.
PRBool paintingSuppressed = PR_FALSE;
aPresContext->PresShell()->IsPaintingSuppressed(&paintingSuppressed);
if (paintingSuppressed)
// XXX why do we need this here? we should never reach this. Maybe
// because these can have widgets? Hmm
if (aBuilder->IsBackgroundOnly())
return NS_OK;
// Start by assuming we are visible and need to be painted
PRBool isVisible = PR_TRUE;
if (aPresContext->IsPaginated()) {
if (aPresContext->IsRenderingOnlySelection()) {
// Check the quick way first
PRBool isSelected = (mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
// if we aren't selected in the mState we could be a container
// so check to see if we are in the selection range
if (!isSelected) {
nsCOMPtr<nsISelectionController> selcon;
selcon = do_QueryInterface(aPresContext->PresShell());
if (selcon) {
nsCOMPtr<nsISelection> selection;
selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mContent));
selection->ContainsNode(node, PR_TRUE, &isVisible);
} else {
isVisible = PR_FALSE;
}
}
}
}
if (isVisible) {
if (aWhichLayer == NS_FRAME_PAINT_LAYER_BACKGROUND) {
const nsStyleDisplay* displayData = GetStyleDisplay();
if (displayData->mAppearance) {
nsITheme *theme = aPresContext->GetTheme();
nsRect rect(0, 0, mRect.width, mRect.height);
if (theme && theme->ThemeSupportsWidget(aPresContext, this, displayData->mAppearance))
theme->DrawWidgetBackground(&aRenderingContext, this,
displayData->mAppearance, rect, aDirtyRect);
}
}
return nsHTMLScrollFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
}
DO_GLOBAL_REFLOW_COUNT_DSP("nsListControlFrame", &aRenderingContext);
return NS_OK;
// REVIEW: The selection visibility code that used to be here is what
// we already do by default.
// REVIEW: There was code here to paint the theme background. But as far
// as I can tell, we'd just paint the theme background twice because
// it was redundant with nsCSSRendering::PaintBackground
return nsHTMLScrollFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
}
/* Note: this is called by the SelectsAreaFrame, which is the same
as the frame returned by GetOptionsContainer. It's the frame which is
scrolled by us. */
void nsListControlFrame::PaintFocus(nsIRenderingContext& aRC, nsFramePaintLayer aWhichLayer)
/**
* This is called by the SelectsAreaFrame, which is the same
* as the frame returned by GetOptionsContainer. It's the frame which is
* scrolled by us.
* @param aPt the offset of this frame, relative to the rendering reference
* frame
*/
void nsListControlFrame::PaintFocus(nsIRenderingContext& aRC, nsPoint aPt)
{
if (NS_FRAME_PAINT_LAYER_FOREGROUND != aWhichLayer) return;
if (mFocused != this) return;
// The mEndSelectionIndex is what is currently being selected
@ -494,14 +457,15 @@ void nsListControlFrame::PaintFocus(nsIRenderingContext& aRC, nsFramePaintLayer
if (childframe) {
// get the child rect
fRect = childframe->GetRect();
// get it into the coordinates of containerFrame
fRect.MoveBy(childframe->GetParent()->GetOffsetTo(containerFrame));
// get it into the our coordinates
fRect.MoveBy(childframe->GetParent()->GetOffsetTo(this));
} else {
fRect.x = fRect.y = 0;
fRect.width = mRect.width;
fRect.height = CalcFallbackRowHeight(0);
fRect.MoveBy(containerFrame->GetOffsetTo(this));
}
fRect += aPt;
PRBool lastItemIsSelected = PR_FALSE;
if (focusedIndex != kNothingSelected) {
@ -2547,9 +2511,8 @@ nsresult
nsListControlFrame::GetIndexFromDOMEvent(nsIDOMEvent* aMouseEvent,
PRInt32& aCurIndex)
{
if (IgnoreMouseEventForSelection(aMouseEvent)) {
if (IgnoreMouseEventForSelection(aMouseEvent))
return NS_ERROR_FAILURE;
}
nsIView* view = GetScrolledFrame()->GetView();
nsIViewManager* viewMan = view->GetViewManager();

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

@ -109,11 +109,9 @@ public:
nsDidReflowStatus aStatus);
NS_IMETHOD Destroy(nsPresContext *aPresContext);
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
virtual nsIFrame* GetContentInsertionFrame();
@ -192,7 +190,8 @@ public:
// Helper
void SetPassId(PRInt16 aId) { mPassId = aId; }
void PaintFocus(nsIRenderingContext& aRC, nsFramePaintLayer aWhichLayer);
PRBool IsFocused() { return this == mFocused; }
void PaintFocus(nsIRenderingContext& aRC, nsPoint aPt);
#ifdef ACCESSIBILITY
void FireMenuItemActiveEvent(); // Inform assistive tech what got focused
@ -289,7 +288,7 @@ protected:
nsSize mCachedAvailableSize;
static nsListControlFrame * mFocused;
#ifdef DO_REFLOW_COUNTER
PRInt32 mReflowId;
#endif

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

@ -40,6 +40,7 @@
#include "nsIDOMHTMLOptionElement.h"
#include "nsIContent.h"
#include "nsListControlFrame.h"
#include "nsDisplayList.h"
nsIFrame*
NS_NewSelectsAreaFrame(nsIPresShell* aShell, PRUint32 aFlags)
@ -97,52 +98,116 @@ nsSelectsAreaFrame::IsOptionElementFrame(nsIFrame *aFrame)
return PR_FALSE;
}
//---------------------------------------------------------
nsIFrame*
nsSelectsAreaFrame::GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer)
/**
* This wrapper class lets us redirect mouse hits from the child frame of
* an option element to the element's own frame.
* REVIEW: This is what nsSelectsAreaFrame::GetFrameForPoint used to do
*/
class nsDisplayOptionEventGrabber : public nsDisplayWrapList {
public:
nsDisplayOptionEventGrabber(nsIFrame* aFrame, nsDisplayItem* aItem)
: nsDisplayWrapList(aFrame, aItem) {}
nsDisplayOptionEventGrabber(nsIFrame* aFrame, nsDisplayList* aList)
: nsDisplayWrapList(aFrame, aList) {}
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt);
NS_DISPLAY_DECL_NAME("OptionEventGrabber")
virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem);
};
nsIFrame* nsDisplayOptionEventGrabber::HitTest(nsDisplayListBuilder* aBuilder,
nsPoint aPt)
{
nsRect thisRect(nsPoint(0,0), GetSize());
PRBool inThisFrame = thisRect.Contains(aPoint);
if (!((mState & NS_FRAME_OUTSIDE_CHILDREN) || inThisFrame)) {
return nsnull;
}
nsIFrame* frame = nsAreaFrame::GetFrameForPoint(aPoint, aWhichLayer);
nsIFrame* frame = mList.HitTest(aBuilder, aPt);
if (frame) {
nsIFrame* selectedFrame = frame;
while (selectedFrame && !IsOptionElementFrame(selectedFrame)) {
while (selectedFrame &&
!nsSelectsAreaFrame::IsOptionElementFrame(selectedFrame)) {
selectedFrame = selectedFrame->GetParent();
}
if (selectedFrame) {
return selectedFrame;
}
// else, keep the original result as *aFrame, which could be this frame
// else, keep the original result, which could be this frame
}
return frame;
}
NS_IMETHODIMP
nsSelectsAreaFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
nsDisplayWrapList* nsDisplayOptionEventGrabber::WrapWithClone(
nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
return new (aBuilder) nsDisplayOptionEventGrabber(aItem->GetUnderlyingFrame(), aItem);
}
class nsOptionEventGrabberWrapper : public nsDisplayWrapper
{
nsAreaFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, aFlags);
nsIFrame* frame = this;
while (frame) {
frame = frame->GetParent();
if (frame->GetType() == nsLayoutAtoms::listControlFrame) {
nsListControlFrame* listFrame = NS_STATIC_CAST(nsListControlFrame*, frame);
listFrame->PaintFocus(aRenderingContext, aWhichLayer);
return NS_OK;
}
public:
nsOptionEventGrabberWrapper() {}
virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList) {
// We can't specify the underlying frame here. We need this list to be
// exploded if sorted.
return new (aBuilder) nsDisplayOptionEventGrabber(nsnull, aList);
}
virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem) {
return new (aBuilder) nsDisplayOptionEventGrabber(aItem->GetUnderlyingFrame(), aItem);
}
};
static nsListControlFrame* GetEnclosingListFrame(nsIFrame* aSelectsAreaFrame)
{
nsIFrame* frame = aSelectsAreaFrame->GetParent();
while (frame) {
if (frame->GetType() == nsLayoutAtoms::listControlFrame)
return NS_STATIC_CAST(nsListControlFrame*, frame);
frame = frame->GetParent();
}
return nsnull;
}
static void PaintListFocus(nsIFrame* aFrame,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect, nsPoint aPt)
{
nsListControlFrame* listFrame = GetEnclosingListFrame(aFrame);
// listFrame must be non-null or we wouldn't get called.
listFrame->PaintFocus(*aCtx, aPt - aFrame->GetOffsetTo(listFrame));
}
NS_IMETHODIMP
nsSelectsAreaFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
if (!aBuilder->IsForEventDelivery())
return BuildDisplayListInternal(aBuilder, aDirtyRect, aLists);
nsDisplayListCollection set;
nsresult rv = BuildDisplayListInternal(aBuilder, aDirtyRect, set);
NS_ENSURE_SUCCESS(rv, rv);
nsOptionEventGrabberWrapper wrapper;
return wrapper.WrapLists(aBuilder, this, set, aLists);
}
nsresult
nsSelectsAreaFrame::BuildDisplayListInternal(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
nsresult rv = nsAreaFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
NS_ENSURE_SUCCESS(rv, rv);
nsListControlFrame* listFrame = GetEnclosingListFrame(this);
if (listFrame && listFrame->IsFocused()) {
// we can't just associate the display item with the list frame,
// because then the list's scrollframe won't clip it (the scrollframe
// only clips contained descendants).
return aLists.Outlines()->AppendNewToTop(new (aBuilder)
nsDisplayGeneric(this, PaintListFocus, "ListFocus"));
}
return NS_OK;
}

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

@ -54,18 +54,16 @@ public:
// nsISupports
//NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
protected:
PRBool IsOptionElement(nsIContent* aContent);
PRBool IsOptionElementFrame(nsIFrame *aFrame);
nsresult BuildDisplayListInternal(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
static PRBool IsOptionElement(nsIContent* aContent);
static PRBool IsOptionElementFrame(nsIFrame *aFrame);
};
#endif /* nsSelectsAreaFrame_h___ */

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

@ -2111,49 +2111,6 @@ nsTextControlFrame::Reflow(nsPresContext* aPresContext,
return rv;
}
NS_IMETHODIMP
nsTextControlFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
{
PRBool isVisible;
if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) {
return NS_OK;
}
nsresult rv = NS_OK;
if (aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND) {
rv = nsStackFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, NS_FRAME_PAINT_LAYER_BACKGROUND);
if (NS_FAILED(rv)) return rv;
rv = nsStackFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, NS_FRAME_PAINT_LAYER_FLOATS);
if (NS_FAILED(rv)) return rv;
rv = nsStackFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, NS_FRAME_PAINT_LAYER_FOREGROUND);
}
DO_GLOBAL_REFLOW_COUNT_DSP("nsTextControlFrame", &aRenderingContext);
return rv;
}
nsIFrame*
nsTextControlFrame::GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer)
{
nsIFrame* frame = nsnull;
if (aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND) {
frame = nsStackFrame::GetFrameForPoint(aPoint,
NS_FRAME_PAINT_LAYER_FOREGROUND);
if (frame)
return frame;
frame = nsStackFrame::GetFrameForPoint(aPoint,
NS_FRAME_PAINT_LAYER_FLOATS);
if (frame)
return frame;
frame = nsStackFrame::GetFrameForPoint(aPoint,
NS_FRAME_PAINT_LAYER_BACKGROUND);
}
return frame;
}
NS_IMETHODIMP
nsTextControlFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize)
{

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

@ -83,15 +83,6 @@ public:
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
NS_IMETHOD GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);

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

@ -68,6 +68,7 @@ public:
nsresult FirstChild(const nsIFrame* aDelegatingFrame,
nsIAtom* aListName,
nsIFrame** aFirstChild) const;
nsIFrame* GetFirstChild() { return mAbsoluteFrames.FirstChild(); }
nsresult SetInitialChildList(nsIFrame* aDelegatingFrame,
nsPresContext* aPresContext,

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

@ -54,13 +54,7 @@
class BRFrame : public nsFrame {
public:
// nsIFrame
#ifdef NS_DEBUG
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
#endif
// REVIEW: Removed debug-only Paint() method rather than porting it
NS_IMETHOD GetPositionHelper(const nsPoint& aPoint,
nsIContent ** aNewContent,
PRInt32& aContentOffset,
@ -69,12 +63,12 @@ public:
NS_IMETHOD PeekOffset(nsPresContext* aPresContext,
nsPeekOffsetStruct *aPos);
// nsIHTMLReflow
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
virtual nsIAtom* GetType() const;
protected:
virtual ~BRFrame();
};
@ -89,25 +83,6 @@ BRFrame::~BRFrame()
{
}
#ifdef NS_DEBUG
NS_IMETHODIMP
BRFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
{
if ((NS_FRAME_PAINT_LAYER_DEBUG == aWhichLayer) && GetShowFrameBorders()) {
float p2t;
p2t = aPresContext->PixelsToTwips();
nscoord five = NSIntPixelsToTwips(5, p2t);
aRenderingContext.SetColor(NS_RGB(0, 255, 255));
aRenderingContext.FillRect(0, 0, five, five*2);
}
return NS_OK;
}
#endif
NS_IMETHODIMP
BRFrame::Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aMetrics,

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

@ -81,6 +81,7 @@
#endif
#include "nsLayoutUtils.h"
#include "nsBoxLayoutState.h"
#include "nsDisplayList.h"
#ifdef IBMBIDI
#include "nsBidiPresUtils.h"
@ -6134,218 +6135,71 @@ static void ComputeCombinedArea(nsLineList& aLines,
}
#endif
NS_IMETHODIMP
nsBlockFrame::IsVisibleForPainting(nsPresContext * aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aCheckVis,
PRBool* aIsVisible)
PRBool
nsBlockFrame::IsVisibleInSelection(nsISelection* aSelection)
{
// first check to see if we are visible
if (aCheckVis) {
if (!GetStyleVisibility()->IsVisible()) {
*aIsVisible = PR_FALSE;
return NS_OK;
}
}
nsCOMPtr<nsIDOMHTMLHtmlElement> html(do_QueryInterface(mContent));
nsCOMPtr<nsIDOMHTMLBodyElement> body(do_QueryInterface(mContent));
if (html || body)
return PR_TRUE;
// Start by assuming we are visible and need to be painted
*aIsVisible = PR_TRUE;
// NOTE: GetSelectionforVisCheck checks the pagination to make sure we are printing
// In otherwords, the selection will ALWAYS be null if we are not printing, meaning
// the visibility will be TRUE in that case
nsCOMPtr<nsISelection> selection;
nsresult rv = GetSelectionForVisCheck(aPresContext, getter_AddRefs(selection));
if (NS_SUCCEEDED(rv) && selection) {
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mContent));
nsCOMPtr<nsIDOMHTMLHtmlElement> html(do_QueryInterface(mContent));
nsCOMPtr<nsIDOMHTMLBodyElement> body(do_QueryInterface(mContent));
if (!html && !body) {
rv = selection->ContainsNode(node, PR_TRUE, aIsVisible);
}
}
return rv;
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mContent));
PRBool visible;
nsresult rv = aSelection->ContainsNode(node, PR_TRUE, &visible);
return NS_SUCCEEDED(rv) && visible;
}
/* virtual */ void
nsBlockFrame::PaintTextDecorationLines(nsIRenderingContext& aRenderingContext,
nscolor aColor,
nscoord aOffset,
nscoord aAscent,
nscoord aSize)
nsBlockFrame::PaintTextDecorationLine(nsIRenderingContext& aRenderingContext,
nsPoint aPt,
nsLineBox* aLine,
nscolor aColor,
nscoord aOffset,
nscoord aAscent,
nscoord aSize)
{
aRenderingContext.SetColor(aColor);
for (nsLineList::iterator line = begin_lines(), line_start = line,
line_end = end_lines();
line != line_end; ++line) {
if (!line->IsBlock()) {
nscoord start = line->mBounds.x;
nscoord width = line->mBounds.width;
NS_ASSERTION(!aLine->IsBlock(), "Why did we ask for decorations on a block?");
if (line == line_start) {
// Adjust for the text-indent. See similar code in
// nsLineLayout::BeginLineReflow.
nscoord indent = 0;
const nsStyleText* styleText = GetStyleText();
nsStyleUnit unit = styleText->mTextIndent.GetUnit();
if (eStyleUnit_Coord == unit) {
indent = styleText->mTextIndent.GetCoordValue();
} else if (eStyleUnit_Percent == unit) {
// It's a percentage of the containing block width.
nsIFrame* containingBlock =
nsHTMLReflowState::GetContainingBlockFor(this);
NS_ASSERTION(containingBlock, "Must have containing block!");
indent = nscoord(styleText->mTextIndent.GetPercentValue() *
containingBlock->GetRect().width);
}
nscoord start = aLine->mBounds.x;
nscoord width = aLine->mBounds.width;
// Adjust the start position and the width of the decoration by the
// value of the indent. Note that indent can be negative; that's OK.
// It'll just increase the width (which can also happen to be
// negative!).
start += indent;
width -= indent;
}
if (aLine == begin_lines().get()) {
// Adjust for the text-indent. See similar code in
// nsLineLayout::BeginLineReflow.
nscoord indent = 0;
const nsStyleText* styleText = GetStyleText();
nsStyleUnit unit = styleText->mTextIndent.GetUnit();
if (eStyleUnit_Coord == unit) {
indent = styleText->mTextIndent.GetCoordValue();
} else if (eStyleUnit_Percent == unit) {
// It's a percentage of the containing block width.
nsIFrame* containingBlock =
nsHTMLReflowState::GetContainingBlockFor(this);
NS_ASSERTION(containingBlock, "Must have containing block!");
indent = nscoord(styleText->mTextIndent.GetPercentValue() *
containingBlock->GetRect().width);
}
// Adjust the start position and the width of the decoration by the
// value of the indent. Note that indent can be negative; that's OK.
// It'll just increase the width (which can also happen to be
// negative!).
start += indent;
width -= indent;
}
// Only paint if we have a positive width
if (width > 0) {
aRenderingContext.FillRect(start,
line->mBounds.y + line->GetAscent() - aOffset,
width, aSize);
}
}
}
}
NS_IMETHODIMP
nsBlockFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
{
if (NS_FRAME_IS_UNFLOWABLE & mState) {
return NS_OK;
}
#ifdef DEBUG
if (gNoisyDamageRepair) {
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
PRInt32 depth = GetDepth();
nsRect ca;
::ComputeCombinedArea(mLines, mRect.width, mRect.height, ca);
nsFrame::IndentBy(stdout, depth);
ListTag(stdout);
printf(": bounds=%d,%d,%d,%d dirty=%d,%d,%d,%d ca=%d,%d,%d,%d\n",
mRect.x, mRect.y, mRect.width, mRect.height,
aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height,
ca.x, ca.y, ca.width, ca.height);
}
}
#endif
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
PaintSelf(aPresContext, aRenderingContext, aDirtyRect);
}
PRBool paintingSuppressed = PR_FALSE;
aPresContext->PresShell()->IsPaintingSuppressed(&paintingSuppressed);
if (paintingSuppressed)
return NS_OK;
const nsStyleDisplay* disp = GetStyleDisplay();
// If overflow is hidden then set the clip rect so that children don't
// leak out of us. Note that because overflow'-clip' only applies to
// the content area we do this after painting the border and background
if (NS_STYLE_OVERFLOW_CLIP == disp->mOverflowX) {
aRenderingContext.PushState();
SetOverflowClipRect(aRenderingContext);
}
// Child elements have the opportunity to override the visibility
// property and display even if the parent is hidden
if (NS_FRAME_PAINT_LAYER_FLOATS == aWhichLayer) {
PaintFloats(aPresContext, aRenderingContext, aDirtyRect);
}
PaintDecorationsAndChildren(aPresContext, aRenderingContext,
aDirtyRect, aWhichLayer, PR_TRUE);
if (NS_STYLE_OVERFLOW_CLIP == disp->mOverflowX)
aRenderingContext.PopState();
#if 0
if ((NS_FRAME_PAINT_LAYER_DEBUG == aWhichLayer) && GetShowFrameBorders()) {
// Render the bands in the spacemanager
nsSpaceManager* sm = mSpaceManager;
if (nsnull != sm) {
nsBlockBandData band;
band.Init(sm, nsSize(mRect.width, mRect.height));
nscoord y = 0;
while (y < mRect.height) {
nsRect availArea;
band.GetAvailableSpace(y, PR_FALSE, availArea);
// Render a box and a diagonal line through the band
aRenderingContext.SetColor(NS_RGB(0,255,0));
aRenderingContext.DrawRect(0, availArea.y,
mRect.width, availArea.height);
aRenderingContext.DrawLine(0, availArea.y,
mRect.width, availArea.YMost());
// Render boxes and opposite diagonal lines around the
// unavailable parts of the band.
PRInt32 i;
for (i = 0; i < band.GetTrapezoidCount(); i++) {
const nsBandTrapezoid* trapezoid = band.GetTrapezoid(i);
if (nsBandTrapezoid::Available != trapezoid->mState) {
nsRect r = trapezoid->GetRect();
if (nsBandTrapezoid::OccupiedMultiple == trapezoid->mState) {
aRenderingContext.SetColor(NS_RGB(0,255,128));
}
else {
aRenderingContext.SetColor(NS_RGB(128,255,0));
}
aRenderingContext.DrawRect(r);
aRenderingContext.DrawLine(r.x, r.YMost(), r.XMost(), r.y);
}
}
y = availArea.YMost();
}
}
}
#endif
return NS_OK;
}
void
nsBlockFrame::PaintFloats(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect)
{
for (nsIFrame* floatFrame = mFloats.FirstChild();
floatFrame;
floatFrame = floatFrame->GetNextSibling()) {
PaintChild(aPresContext, aRenderingContext, aDirtyRect,
floatFrame, NS_FRAME_PAINT_LAYER_BACKGROUND);
PaintChild(aPresContext, aRenderingContext, aDirtyRect,
floatFrame, NS_FRAME_PAINT_LAYER_FLOATS);
PaintChild(aPresContext, aRenderingContext, aDirtyRect,
floatFrame, NS_FRAME_PAINT_LAYER_FOREGROUND);
// Only paint if we have a positive width
if (width > 0) {
aRenderingContext.FillRect(start + aPt.x,
aLine->mBounds.y + aLine->GetAscent() - aOffset + aPt.y,
width, aSize);
}
}
#ifdef DEBUG
static void DebugOutputDrawLine(nsFramePaintLayer aWhichLayer, PRInt32 aDepth,
nsLineBox* aLine, PRBool aDrawn) {
if (nsBlockFrame::gNoisyDamageRepair &&
(NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer)) {
static void DebugOutputDrawLine(PRInt32 aDepth, nsLineBox* aLine, PRBool aDrawn) {
if (nsBlockFrame::gNoisyDamageRepair) {
nsFrame::IndentBy(stdout, aDepth+1);
nsRect lineArea = aLine->GetCombinedArea();
printf("%s line=%p bounds=%d,%d,%d,%d ca=%d,%d,%d,%d\n",
@ -6359,51 +6213,70 @@ static void DebugOutputDrawLine(nsFramePaintLayer aWhichLayer, PRInt32 aDepth,
}
#endif
static inline void
PaintLine(const nsRect& aLineArea, const nsRect& aDirtyRect,
nsBlockFrame::line_iterator& aLine, PRInt32 aDepth,
PRInt32& aDrawnLines, nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsFramePaintLayer aWhichLayer, nsBlockFrame* aFrame) {
static nsresult
DisplayLine(nsDisplayListBuilder* aBuilder, const nsRect& aLineArea,
const nsRect& aDirtyRect, nsBlockFrame::line_iterator& aLine,
PRInt32 aDepth, PRInt32& aDrawnLines, const nsDisplayListSet& aLists,
nsBlockFrame* aFrame) {
// If the line's combined area (which includes child frames that
// stick outside of the line's bounding box or our bounding box)
// intersects the dirty rect then paint the line.
if (aLineArea.Intersects(aDirtyRect)) {
PRBool intersect = aLineArea.Intersects(aDirtyRect);
#ifdef DEBUG
DebugOutputDrawLine(aWhichLayer, aDepth, aLine.get(), PR_TRUE);
if (nsBlockFrame::gLamePaintMetrics) {
aDrawnLines++;
}
if (nsBlockFrame::gLamePaintMetrics) {
aDrawnLines++;
}
DebugOutputDrawLine(aDepth, aLine.get(), intersect);
#endif
nsIFrame* kid = aLine->mFirstChild;
PRInt32 n = aLine->GetChildCount();
while (--n >= 0) {
aFrame->PaintChild(aPresContext, aRenderingContext, aDirtyRect, kid,
aWhichLayer);
kid = kid->GetNextSibling();
}
if (!intersect && !(aFrame->GetStateBits() & NS_FRAME_HAS_DESCENDANT_PLACEHOLDER))
return NS_OK;
nsresult rv;
nsDisplayList aboveTextDecorations;
PRBool lineInline = aLine->IsInline();
if (lineInline) {
// Display the text-decoration for the hypothetical anonymous inline box
// that wraps these inlines
rv = aFrame->DisplayTextDecorations(aBuilder, aLists.Content(),
&aboveTextDecorations, aLine);
NS_ENSURE_SUCCESS(rv, rv);
}
#ifdef DEBUG
else {
DebugOutputDrawLine(aWhichLayer, aDepth, aLine.get(), PR_FALSE);
// Block-level child backgrounds go on the blockBorderBackgrounds list ...
// Inline-level child backgrounds go on the regular child content list.
nsDisplayListSet childLists(aLists,
lineInline ? aLists.Content() : aLists.BlockBorderBackgrounds());
nsIFrame* kid = aLine->mFirstChild;
PRInt32 n = aLine->GetChildCount();
while (--n >= 0) {
rv = aFrame->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, childLists,
lineInline ? nsIFrame::DISPLAY_CHILD_INLINE : 0);
NS_ENSURE_SUCCESS(rv, rv);
kid = kid->GetNextSibling();
}
#endif
aLists.Content()->AppendToTop(&aboveTextDecorations);
return NS_OK;
}
void
nsBlockFrame::PaintChildren(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
NS_IMETHODIMP
nsBlockFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
PRInt32 drawnLines; // Will only be used if set (gLamePaintMetrics).
PRInt32 depth = 0;
#ifdef DEBUG
if (gNoisyDamageRepair) {
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
depth = GetDepth();
}
nsRect ca;
::ComputeCombinedArea(mLines, mRect.width, mRect.height, ca);
nsFrame::IndentBy(stdout, depth);
ListTag(stdout);
printf(": bounds=%d,%d,%d,%d dirty(absolute)=%d,%d,%d,%d ca=%d,%d,%d,%d\n",
mRect.x, mRect.y, mRect.width, mRect.height,
aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height,
ca.x, ca.y, ca.width, ca.height);
}
PRTime start = LL_ZERO; // Initialize these variables to silence the compiler.
if (gLamePaintMetrics) {
@ -6412,9 +6285,19 @@ nsBlockFrame::PaintChildren(nsPresContext* aPresContext,
}
#endif
nsLineBox* cursor = GetFirstLineContaining(aDirtyRect.y);
line_iterator line_end = end_lines();
DisplayBorderBackgroundOutline(aBuilder, aLists);
MarkOutOfFlowChildrenForDisplayList(mFloats.FirstChild(), aDirtyRect);
MarkOutOfFlowChildrenForDisplayList(mAbsoluteContainer.GetFirstChild(), aDirtyRect);
// Don't use the line cursor if we have a descendant placeholder ... we could
// skip lines that contain placeholders but don't themselves intersect with
// the dirty area.
nsLineBox* cursor = GetStateBits() & NS_FRAME_HAS_DESCENDANT_PLACEHOLDER
? nsnull : GetFirstLineContaining(aDirtyRect.y);
line_iterator line_end = end_lines();
nsresult rv = NS_OK;
if (cursor) {
for (line_iterator line = mLines.begin(cursor);
line != line_end;
@ -6426,8 +6309,10 @@ nsBlockFrame::PaintChildren(nsPresContext* aPresContext,
if (lineArea.y >= aDirtyRect.YMost()) {
break;
}
PaintLine(lineArea, aDirtyRect, line, depth, drawnLines, aPresContext,
aRenderingContext, aWhichLayer, this);
rv = DisplayLine(aBuilder, lineArea, aDirtyRect, line, depth, drawnLines,
aLists, this);
if (NS_FAILED(rv))
break;
}
}
} else {
@ -6439,6 +6324,10 @@ nsBlockFrame::PaintChildren(nsPresContext* aPresContext,
line != line_end;
++line) {
nsRect lineArea = line->GetCombinedArea();
rv = DisplayLine(aBuilder, lineArea, aDirtyRect, line, depth, drawnLines,
aLists, this);
if (NS_FAILED(rv))
break;
if (!lineArea.IsEmpty()) {
if (lineArea.y < lastY
|| lineArea.YMost() < lastYMost) {
@ -6446,24 +6335,18 @@ nsBlockFrame::PaintChildren(nsPresContext* aPresContext,
}
lastY = lineArea.y;
lastYMost = lineArea.YMost();
PaintLine(lineArea, aDirtyRect, line, depth, drawnLines, aPresContext,
aRenderingContext, aWhichLayer, this);
}
lineCount++;
}
if (nonDecreasingYs && lineCount >= MIN_LINES_NEEDING_CURSOR) {
if (NS_SUCCEEDED(rv) && nonDecreasingYs && lineCount >= MIN_LINES_NEEDING_CURSOR) {
SetupLineCursor();
}
}
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
if ((nsnull != mBullet) && HaveOutsideBullet()) {
// Paint outside bullets manually
PaintChild(aPresContext, aRenderingContext, aDirtyRect, mBullet,
aWhichLayer);
}
if (NS_SUCCEEDED(rv) && (nsnull != mBullet) && HaveOutsideBullet()) {
// Display outside bullets manually
rv = BuildDisplayListForChild(aBuilder, mBullet, aDirtyRect, aLists);
}
#ifdef DEBUG
@ -6486,6 +6369,11 @@ nsBlockFrame::PaintChildren(nsPresContext* aPresContext,
printf("%s\n", buf);
}
#endif
UnmarkOutOfFlowChildrenForDisplayList(mFloats.FirstChild());
UnmarkOutOfFlowChildrenForDisplayList(mAbsoluteContainer.GetFirstChild());
return rv;
}
#ifdef ACCESSIBILITY
@ -6568,145 +6456,6 @@ nsLineBox* nsBlockFrame::GetFirstLineContaining(nscoord y) {
return cursor.get();
}
static inline nsIFrame*
GetFrameFromLine(nsIFrame* aBlock, const nsRect& aLineArea, const nsPoint& aTmp,
nsBlockFrame::line_iterator& aLine,
nsFramePaintLayer aWhichLayer) {
nsIFrame* frame = nsnull;
if (aLineArea.Contains(aTmp)) {
nsIFrame* kid = aLine->mFirstChild;
PRInt32 n = aLine->GetChildCount();
while (--n >= 0) {
nsIFrame *hit = kid->GetFrameForPoint(aTmp - kid->GetOffsetTo(aBlock),
aWhichLayer);
if (hit)
frame = hit;
kid = kid->GetNextSibling();
}
}
return frame;
}
// Optimized function that uses line combined areas to skip lines
// we know can't contain the point
nsIFrame*
nsBlockFrame::GetFrameForPointUsing(const nsPoint& aPoint,
nsIAtom* aList,
nsFramePaintLayer aWhichLayer,
PRBool aConsiderSelf)
{
if (aList)
return nsContainerFrame::GetFrameForPointUsing(aPoint, aList, aWhichLayer,
aConsiderSelf);
nsRect thisRect(nsPoint(0,0), GetSize());
nsIFrame* frame = nsnull;
PRBool inThisFrame = thisRect.Contains(aPoint);
if (!((mState & NS_FRAME_OUTSIDE_CHILDREN) || inThisFrame)) {
return nsnull;
}
nsLineBox* cursor = GetFirstLineContaining(aPoint.y);
line_iterator line_end = end_lines();
if (cursor) {
// This is the fast path for large blocks
for (line_iterator line = mLines.begin(cursor);
line != line_end;
++line) {
nsRect lineArea = line->GetCombinedArea();
// Because we have a cursor, the combinedArea.ys are non-decreasing.
// Once we've passed tmp.y, we can never see it again.
if (!lineArea.IsEmpty()) {
if (lineArea.y > aPoint.y) {
break;
}
nsIFrame* hit = GetFrameFromLine(this, lineArea, aPoint, line,
aWhichLayer);
if (hit)
frame = hit;
}
}
} else {
PRBool nonDecreasingYs = PR_TRUE;
PRInt32 lineCount = 0;
nscoord lastY = PR_INT32_MIN;
nscoord lastYMost = PR_INT32_MIN;
for (line_iterator line = mLines.begin();
line != line_end;
++line) {
nsRect lineArea = line->GetCombinedArea();
if (!lineArea.IsEmpty()) {
if (lineArea.y < lastY
|| lineArea.YMost() < lastYMost) {
nonDecreasingYs = PR_FALSE;
}
lastY = lineArea.y;
lastYMost = lineArea.YMost();
nsIFrame* hit = GetFrameFromLine(this, lineArea, aPoint, line,
aWhichLayer);
if (hit)
frame = hit;
}
lineCount++;
}
if (nonDecreasingYs && lineCount >= MIN_LINES_NEEDING_CURSOR) {
SetupLineCursor();
}
}
if (frame)
return frame;
if (inThisFrame && aConsiderSelf && GetStyleVisibility()->IsVisible())
return this;
return nsnull;
}
nsIFrame*
nsBlockFrame::GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer)
{
nsIFrame* frame;
switch (aWhichLayer) {
case NS_FRAME_PAINT_LAYER_FOREGROUND:
frame = GetFrameForPointUsing(aPoint, nsnull,
NS_FRAME_PAINT_LAYER_FOREGROUND, PR_FALSE);
if (frame)
return frame;
if (mBullet)
return GetFrameForPointUsing(aPoint, nsLayoutAtoms::bulletList,
NS_FRAME_PAINT_LAYER_FOREGROUND,
PR_FALSE);
return nsnull;
case NS_FRAME_PAINT_LAYER_FLOATS:
// we painted our floats before our children, and thus
// we should check floats within children first
frame = GetFrameForPointUsing(aPoint, nsnull,
NS_FRAME_PAINT_LAYER_FLOATS, PR_FALSE);
if (frame)
return frame;
if (mFloats.NotEmpty())
return GetFrameForPointUsing(aPoint, nsLayoutAtoms::floatList,
NS_FRAME_PAINT_LAYER_ALL, PR_FALSE);
return nsnull;
case NS_FRAME_PAINT_LAYER_BACKGROUND:
// Because this frame is a block, pass PR_TRUE to consider this frame
return GetFrameForPointUsing(aPoint, nsnull,
NS_FRAME_PAINT_LAYER_BACKGROUND, PR_TRUE);
}
// we shouldn't get here
NS_NOTREACHED("aWhichLayer was not understood");
return nsnull;
}
NS_IMETHODIMP
nsBlockFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild)
{

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

@ -159,11 +159,9 @@ public:
NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const;
virtual PRBool IsContainingBlock() const;
virtual PRBool IsFloatContainingBlock() const;
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
virtual nsIAtom* GetType() const;
#ifdef DEBUG
NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
@ -183,7 +181,7 @@ public:
// empty combinedAreas never participate in event handling or
// painting), and the block has sufficient number of lines. The
// cursor property points to a "recently used" line. If we get a
// series of GetFrameForPoint or Paint requests that work on lines
// series of requests that work on lines
// "near" the cursor, then we can find those nearby lines quickly by
// starting our search at the cursor.
@ -200,18 +198,8 @@ public:
// are non-decreasing.
void SetupLineCursor();
virtual nsIFrame* GetFrameForPointUsing(const nsPoint& aPoint,
nsIAtom* aList,
nsFramePaintLayer aWhichLayer,
PRBool aConsiderSelf);
virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild);
NS_IMETHOD IsVisibleForPainting(nsPresContext * aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aCheckVis,
PRBool* aIsVisible);
virtual PRBool IsVisibleInSelection(nsISelection* aSelection);
virtual PRBool IsEmpty();
virtual PRBool IsSelfEmpty();
@ -257,16 +245,6 @@ public:
void UndoSplitPlaceholders(nsBlockReflowState& aState,
nsIFrame* aLastPlaceholder);
virtual void PaintChild(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsIFrame* aFrame,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0) {
nsContainerFrame::PaintChild(aPresContext, aRenderingContext,
aDirtyRect, aFrame, aWhichLayer, aFlags);
}
PRBool HandleOverflowPlaceholdersForPulledFrame(
nsBlockReflowState& aState, nsIFrame* aFrame);
@ -288,11 +266,13 @@ protected:
* Overides member function of nsHTMLContainerFrame. Needed to handle the
* lines in a nsBlockFrame properly.
*/
virtual void PaintTextDecorationLines(nsIRenderingContext& aRenderingContext,
nscolor aColor,
nscoord aOffset,
nscoord aAscent,
nscoord aSize);
virtual void PaintTextDecorationLine(nsIRenderingContext& aRenderingContext,
nsPoint aPt,
nsLineBox* aLine,
nscolor aColor,
nscoord aOffset,
nscoord aAscent,
nscoord aSize);
void TryAllLines(nsLineList::iterator* aIterator,
nsLineList::iterator* aEndIterator,
@ -528,18 +508,6 @@ protected:
void ReparentFloats(nsIFrame* aFirstFrame,
nsBlockFrame* aOldParent, PRBool aFromOverflow);
//----------------------------------------
//XXX
virtual void PaintChildren(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
void PaintFloats(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
void PropagateFloatDamage(nsBlockReflowState& aState,
nsLineBox* aLine,
nscoord aDeltaY);

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

@ -54,6 +54,7 @@
#ifdef IBMBIDI
#include "nsBidiPresUtils.h"
#endif // IBMBIDI
#include "nsDisplayList.h"
#include "imgILoader.h"
#include "imgIContainer.h"
@ -173,211 +174,228 @@ nsBulletFrame::DidSetStyleContext(nsPresContext* aPresContext)
return NS_OK;
}
NS_IMETHODIMP
nsBulletFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
class nsDisplayBullet : public nsDisplayItem {
public:
nsDisplayBullet(nsBulletFrame* aFrame) : mFrame(aFrame) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("Bullet")
private:
nsBulletFrame* mFrame;
};
void nsDisplayBullet::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
{
if (NS_FRAME_PAINT_LAYER_FOREGROUND != aWhichLayer) {
mFrame->PaintBullet(*aCtx, aBuilder->ToReferenceFrame(mFrame));
}
NS_IMETHODIMP
nsBulletFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
if (!IsVisibleForPainting(aBuilder))
return NS_OK;
}
return aLists.Content()->AppendNewToTop(new (aBuilder) nsDisplayBullet(this));
}
PRBool isVisible;
if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && isVisible) {
const nsStyleList* myList = GetStyleList();
PRUint8 listStyleType = myList->mListStyleType;
void
nsBulletFrame::PaintBullet(nsIRenderingContext& aRenderingContext, nsPoint aPt)
{
const nsStyleList* myList = GetStyleList();
PRUint8 listStyleType = myList->mListStyleType;
if (myList->mListStyleImage && mImageRequest) {
PRUint32 status;
mImageRequest->GetImageStatus(&status);
if (status & imgIRequest::STATUS_LOAD_COMPLETE &&
!(status & imgIRequest::STATUS_ERROR)) {
nsCOMPtr<imgIContainer> imageCon;
mImageRequest->GetImage(getter_AddRefs(imageCon));
if (imageCon) {
nsRect innerArea(0, 0,
mRect.width - (mPadding.left + mPadding.right),
mRect.height - (mPadding.top + mPadding.bottom));
nsRect dest(mPadding.left, mPadding.top, innerArea.width, innerArea.height);
aRenderingContext.DrawImage(imageCon, innerArea, dest);
return NS_OK;
}
if (myList->mListStyleImage && mImageRequest) {
PRUint32 status;
mImageRequest->GetImageStatus(&status);
if (status & imgIRequest::STATUS_LOAD_COMPLETE &&
!(status & imgIRequest::STATUS_ERROR)) {
nsCOMPtr<imgIContainer> imageCon;
mImageRequest->GetImage(getter_AddRefs(imageCon));
if (imageCon) {
nsRect innerArea(0, 0,
mRect.width - (mPadding.left + mPadding.right),
mRect.height - (mPadding.top + mPadding.bottom));
nsRect dest(mPadding.left, mPadding.top, innerArea.width, innerArea.height);
aRenderingContext.DrawImage(imageCon, innerArea, dest + aPt);
return;
}
}
}
const nsStyleFont* myFont = GetStyleFont();
const nsStyleColor* myColor = GetStyleColor();
const nsStyleFont* myFont = GetStyleFont();
const nsStyleColor* myColor = GetStyleColor();
nsCOMPtr<nsIFontMetrics> fm;
aRenderingContext.SetColor(myColor->mColor);
nsCOMPtr<nsIFontMetrics> fm;
aRenderingContext.SetColor(myColor->mColor);
#ifdef IBMBIDI
nsCharType charType = eCharType_LeftToRight;
PRUint8 level = 0;
PRBool isBidiSystem = PR_FALSE;
const nsStyleVisibility* vis = GetStyleVisibility();
PRUint32 hints = 0;
nsCharType charType = eCharType_LeftToRight;
PRUint8 level = 0;
PRBool isBidiSystem = PR_FALSE;
const nsStyleVisibility* vis = GetStyleVisibility();
PRUint32 hints = 0;
#endif // IBMBIDI
nsAutoString text;
switch (listStyleType) {
case NS_STYLE_LIST_STYLE_NONE:
break;
nsAutoString text;
switch (listStyleType) {
case NS_STYLE_LIST_STYLE_NONE:
break;
default:
case NS_STYLE_LIST_STYLE_DISC:
aRenderingContext.FillEllipse(mPadding.left, mPadding.top,
mRect.width - (mPadding.left + mPadding.right),
mRect.height - (mPadding.top + mPadding.bottom));
break;
default:
case NS_STYLE_LIST_STYLE_DISC:
aRenderingContext.FillEllipse(mPadding.left + aPt.x, mPadding.top + aPt.y,
mRect.width - (mPadding.left + mPadding.right),
mRect.height - (mPadding.top + mPadding.bottom));
break;
case NS_STYLE_LIST_STYLE_CIRCLE:
aRenderingContext.DrawEllipse(mPadding.left, mPadding.top,
mRect.width - (mPadding.left + mPadding.right),
mRect.height - (mPadding.top + mPadding.bottom));
break;
case NS_STYLE_LIST_STYLE_CIRCLE:
aRenderingContext.DrawEllipse(mPadding.left + aPt.x, mPadding.top + aPt.y,
mRect.width - (mPadding.left + mPadding.right),
mRect.height - (mPadding.top + mPadding.bottom));
break;
case NS_STYLE_LIST_STYLE_SQUARE:
aRenderingContext.FillRect(mPadding.left, mPadding.top,
mRect.width - (mPadding.left + mPadding.right),
mRect.height - (mPadding.top + mPadding.bottom));
break;
case NS_STYLE_LIST_STYLE_SQUARE:
aRenderingContext.FillRect(mPadding.left + aPt.x, mPadding.top + aPt.y,
mRect.width - (mPadding.left + mPadding.right),
mRect.height - (mPadding.top + mPadding.bottom));
break;
case NS_STYLE_LIST_STYLE_DECIMAL:
case NS_STYLE_LIST_STYLE_OLD_DECIMAL:
case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO:
case NS_STYLE_LIST_STYLE_DECIMAL:
case NS_STYLE_LIST_STYLE_OLD_DECIMAL:
case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO:
#ifdef IBMBIDI
GetListItemText(*myList, text);
GetListItemText(*myList, text);
charType = eCharType_EuropeanNumber;
break;
case NS_STYLE_LIST_STYLE_MOZ_ARABIC_INDIC:
if (GetListItemText(*myList, text))
charType = eCharType_ArabicNumber;
else
charType = eCharType_EuropeanNumber;
break;
break;
case NS_STYLE_LIST_STYLE_MOZ_ARABIC_INDIC:
if (GetListItemText(*myList, text))
charType = eCharType_ArabicNumber;
else
case NS_STYLE_LIST_STYLE_HEBREW:
aRenderingContext.GetHints(hints);
isBidiSystem = (hints & NS_RENDERING_HINT_BIDI_REORDERING);
if (!isBidiSystem) {
if (GetListItemText(*myList, text)) {
charType = eCharType_RightToLeft;
level = 1;
} else {
charType = eCharType_EuropeanNumber;
break;
case NS_STYLE_LIST_STYLE_HEBREW:
aRenderingContext.GetHints(hints);
isBidiSystem = (hints & NS_RENDERING_HINT_BIDI_REORDERING);
if (!isBidiSystem) {
if (GetListItemText(*myList, text)) {
charType = eCharType_RightToLeft;
level = 1;
} else {
charType = eCharType_EuropeanNumber;
}
if (NS_STYLE_DIRECTION_RTL == vis->mDirection) {
text.Cut(0, 1);
text.AppendLiteral(".");
}
break;
}
// else fall through
#endif // IBMBIDI
case NS_STYLE_LIST_STYLE_LOWER_ROMAN:
case NS_STYLE_LIST_STYLE_UPPER_ROMAN:
case NS_STYLE_LIST_STYLE_LOWER_ALPHA:
case NS_STYLE_LIST_STYLE_UPPER_ALPHA:
case NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN:
case NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN:
case NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA:
case NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA:
case NS_STYLE_LIST_STYLE_LOWER_GREEK:
#ifndef IBMBIDI
case NS_STYLE_LIST_STYLE_HEBREW:
#endif
case NS_STYLE_LIST_STYLE_ARMENIAN:
case NS_STYLE_LIST_STYLE_GEORGIAN:
case NS_STYLE_LIST_STYLE_CJK_IDEOGRAPHIC:
case NS_STYLE_LIST_STYLE_HIRAGANA:
case NS_STYLE_LIST_STYLE_KATAKANA:
case NS_STYLE_LIST_STYLE_HIRAGANA_IROHA:
case NS_STYLE_LIST_STYLE_KATAKANA_IROHA:
case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_INFORMAL:
case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_FORMAL:
case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_INFORMAL:
case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_FORMAL:
case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_INFORMAL:
case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_FORMAL:
case NS_STYLE_LIST_STYLE_MOZ_CJK_HEAVENLY_STEM:
case NS_STYLE_LIST_STYLE_MOZ_CJK_EARTHLY_BRANCH:
#ifndef IBMBIDI
case NS_STYLE_LIST_STYLE_MOZ_ARABIC_INDIC:
#endif
case NS_STYLE_LIST_STYLE_MOZ_PERSIAN:
case NS_STYLE_LIST_STYLE_MOZ_URDU:
case NS_STYLE_LIST_STYLE_MOZ_DEVANAGARI:
case NS_STYLE_LIST_STYLE_MOZ_GURMUKHI:
case NS_STYLE_LIST_STYLE_MOZ_GUJARATI:
case NS_STYLE_LIST_STYLE_MOZ_ORIYA:
case NS_STYLE_LIST_STYLE_MOZ_KANNADA:
case NS_STYLE_LIST_STYLE_MOZ_MALAYALAM:
case NS_STYLE_LIST_STYLE_MOZ_BENGALI:
case NS_STYLE_LIST_STYLE_MOZ_TAMIL:
case NS_STYLE_LIST_STYLE_MOZ_TELUGU:
case NS_STYLE_LIST_STYLE_MOZ_THAI:
case NS_STYLE_LIST_STYLE_MOZ_LAO:
case NS_STYLE_LIST_STYLE_MOZ_MYANMAR:
case NS_STYLE_LIST_STYLE_MOZ_KHMER:
case NS_STYLE_LIST_STYLE_MOZ_HANGUL:
case NS_STYLE_LIST_STYLE_MOZ_HANGUL_CONSONANT:
case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME:
case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_NUMERIC:
case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_AM:
case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ER:
case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ET:
fm = aPresContext->GetMetricsFor(myFont->mFont);
#ifdef IBMBIDI
// If we can't render our numeral using the chars in the numbering
// system, we'll be using "decimal"...
PRBool usedChars =
#endif // IBMBIDI
GetListItemText(*myList, text);
#ifdef IBMBIDI
if (!usedChars)
charType = eCharType_EuropeanNumber;
#endif
aRenderingContext.SetFont(fm);
nscoord ascent;
fm->GetMaxAscent(ascent);
aRenderingContext.DrawString(text, mPadding.left, mPadding.top + ascent);
if (NS_STYLE_DIRECTION_RTL == vis->mDirection) {
text.Cut(0, 1);
text.AppendLiteral(".");
}
break;
}
#ifdef IBMBIDI
if (charType != eCharType_LeftToRight) {
fm = aPresContext->GetMetricsFor(myFont->mFont);
aRenderingContext.SetFont(fm);
nscoord ascent;
fm->GetMaxAscent(ascent);
nsBidiPresUtils* bidiUtils = aPresContext->GetBidiUtils();
if (bidiUtils) {
const PRUnichar* buffer = text.get();
PRInt32 textLength = text.Length();
if (eCharType_RightToLeft == charType) {
bidiUtils->FormatUnicodeText(aPresContext, (PRUnichar*)buffer, textLength,
charType, level, PR_FALSE);
}
else {
//Mohamed
aRenderingContext.GetHints(hints);
isBidiSystem = (hints & NS_RENDERING_HINT_ARABIC_SHAPING);
bidiUtils->FormatUnicodeText(aPresContext, (PRUnichar*)buffer, textLength,
charType, level, isBidiSystem);//Mohamed
}
}
aRenderingContext.DrawString(text, mPadding.left, mPadding.top + ascent);
}
// else fall through
#endif // IBMBIDI
case NS_STYLE_LIST_STYLE_LOWER_ROMAN:
case NS_STYLE_LIST_STYLE_UPPER_ROMAN:
case NS_STYLE_LIST_STYLE_LOWER_ALPHA:
case NS_STYLE_LIST_STYLE_UPPER_ALPHA:
case NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN:
case NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN:
case NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA:
case NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA:
case NS_STYLE_LIST_STYLE_LOWER_GREEK:
#ifndef IBMBIDI
case NS_STYLE_LIST_STYLE_HEBREW:
#endif
case NS_STYLE_LIST_STYLE_ARMENIAN:
case NS_STYLE_LIST_STYLE_GEORGIAN:
case NS_STYLE_LIST_STYLE_CJK_IDEOGRAPHIC:
case NS_STYLE_LIST_STYLE_HIRAGANA:
case NS_STYLE_LIST_STYLE_KATAKANA:
case NS_STYLE_LIST_STYLE_HIRAGANA_IROHA:
case NS_STYLE_LIST_STYLE_KATAKANA_IROHA:
case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_INFORMAL:
case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_FORMAL:
case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_INFORMAL:
case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_FORMAL:
case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_INFORMAL:
case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_FORMAL:
case NS_STYLE_LIST_STYLE_MOZ_CJK_HEAVENLY_STEM:
case NS_STYLE_LIST_STYLE_MOZ_CJK_EARTHLY_BRANCH:
#ifndef IBMBIDI
case NS_STYLE_LIST_STYLE_MOZ_ARABIC_INDIC:
#endif
case NS_STYLE_LIST_STYLE_MOZ_PERSIAN:
case NS_STYLE_LIST_STYLE_MOZ_URDU:
case NS_STYLE_LIST_STYLE_MOZ_DEVANAGARI:
case NS_STYLE_LIST_STYLE_MOZ_GURMUKHI:
case NS_STYLE_LIST_STYLE_MOZ_GUJARATI:
case NS_STYLE_LIST_STYLE_MOZ_ORIYA:
case NS_STYLE_LIST_STYLE_MOZ_KANNADA:
case NS_STYLE_LIST_STYLE_MOZ_MALAYALAM:
case NS_STYLE_LIST_STYLE_MOZ_BENGALI:
case NS_STYLE_LIST_STYLE_MOZ_TAMIL:
case NS_STYLE_LIST_STYLE_MOZ_TELUGU:
case NS_STYLE_LIST_STYLE_MOZ_THAI:
case NS_STYLE_LIST_STYLE_MOZ_LAO:
case NS_STYLE_LIST_STYLE_MOZ_MYANMAR:
case NS_STYLE_LIST_STYLE_MOZ_KHMER:
case NS_STYLE_LIST_STYLE_MOZ_HANGUL:
case NS_STYLE_LIST_STYLE_MOZ_HANGUL_CONSONANT:
case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME:
case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_NUMERIC:
case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_AM:
case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ER:
case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ET:
fm = GetPresContext()->GetMetricsFor(myFont->mFont);
#ifdef IBMBIDI
// If we can't render our numeral using the chars in the numbering
// system, we'll be using "decimal"...
PRBool usedChars =
#endif // IBMBIDI
GetListItemText(*myList, text);
#ifdef IBMBIDI
if (!usedChars)
charType = eCharType_EuropeanNumber;
#endif
aRenderingContext.SetFont(fm);
nscoord ascent;
fm->GetMaxAscent(ascent);
aRenderingContext.DrawString(text, mPadding.left + aPt.x,
mPadding.top + aPt.y + ascent);
break;
}
DO_GLOBAL_REFLOW_COUNT_DSP("nsBulletFrame", &aRenderingContext);
return NS_OK;
#ifdef IBMBIDI
if (charType != eCharType_LeftToRight) {
nsPresContext* presContext = GetPresContext();
fm = presContext->GetMetricsFor(myFont->mFont);
aRenderingContext.SetFont(fm);
nscoord ascent;
fm->GetMaxAscent(ascent);
nsBidiPresUtils* bidiUtils = presContext->GetBidiUtils();
if (bidiUtils) {
const PRUnichar* buffer = text.get();
PRInt32 textLength = text.Length();
if (eCharType_RightToLeft == charType) {
bidiUtils->FormatUnicodeText(presContext, (PRUnichar*)buffer, textLength,
charType, level, PR_FALSE);
}
else {
//Mohamed
aRenderingContext.GetHints(hints);
isBidiSystem = (hints & NS_RENDERING_HINT_ARABIC_SHAPING);
bidiUtils->FormatUnicodeText(presContext, (PRUnichar*)buffer, textLength,
charType, level, isBidiSystem);//Mohamed
}
}
aRenderingContext.DrawString(text, mPadding.left + aPt.x,
mPadding.top + aPt.y + ascent);
}
#endif // IBMBIDI
}
PRInt32

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

@ -55,11 +55,9 @@ public:
// nsIFrame
NS_IMETHOD Destroy(nsPresContext* aPresContext);
NS_IMETHOD Paint(nsPresContext* aCX,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
virtual nsIAtom* GetType() const;
NS_IMETHOD DidSetStyleContext(nsPresContext* aPresContext);
#ifdef NS_DEBUG
@ -95,6 +93,8 @@ public:
/* get list item text, with '.' */
PRBool GetListItemText(const nsStyleList& aStyleList,
nsString& aResult);
void PaintBullet(nsIRenderingContext& aRenderingContext, nsPoint aPt);
protected:
void GetDesiredSize(nsPresContext* aPresContext,

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

@ -69,12 +69,16 @@ public:
NS_IMETHOD RemoveFrame(nsIAtom* aListName,
nsIFrame* aOldFrame);
virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer);
// REVIEW: Now by default the background of a frame receives events,
// so this GetFrameForPoint override is no longer necessary.
virtual nsIFrame* GetContentInsertionFrame() {
return GetFirstChild(nsnull)->GetContentInsertionFrame();
}
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
virtual nsIAtom* GetType() const;
@ -162,15 +166,6 @@ nsColumnSetFrame::GetType() const
return nsLayoutAtoms::columnSetFrame;
}
nsIFrame*
nsColumnSetFrame::GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer)
{
// This frame counts as part of the background.
return GetFrameForPointUsing(aPoint, nsnull, aWhichLayer,
aWhichLayer == NS_FRAME_PAINT_LAYER_BACKGROUND);
}
NS_IMETHODIMP
nsColumnSetFrame::SetInitialChildList(nsPresContext* aPresContext,
nsIAtom* aListName,
@ -877,6 +872,23 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
return NS_OK;
}
NS_IMETHODIMP
nsColumnSetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) {
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
nsIFrame* kid = mFrames.FirstChild();
// Our children won't have backgrounds so it doesn't matter where we put them.
while (kid) {
nsresult rv = BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
NS_ENSURE_SUCCESS(rv, rv);
kid = kid->GetNextSibling();
}
return NS_OK;
}
PRIntn
nsColumnSetFrame::GetSkipSides() const
{

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

@ -62,6 +62,7 @@
#include "nsTransform2D.h"
#include "nsRegion.h"
#include "nsLayoutErrors.h"
#include "nsDisplayList.h"
#ifdef NS_DEBUG
#undef NOISY
@ -199,154 +200,32 @@ nsContainerFrame::GetAdditionalChildListName(PRInt32 aIndex) const
// Painting/Events
NS_IMETHODIMP
nsContainerFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
nsContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, aFlags);
return NS_OK;
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
return BuildDisplayListForNonBlockChildren(aBuilder, aDirtyRect, aLists);
}
// Paint the children of a container, assuming nothing about the
// children's spatial arrangement. Given relative positioning, negative
// margins, etc, that's probably a good thing.
//
// Note: aDirtyRect is in our coordinate system (and of course, child
// rect's are also in our coordinate system)
void
nsContainerFrame::PaintChildren(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
nsresult
nsContainerFrame::BuildDisplayListForNonBlockChildren(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists,
PRUint32 aFlags)
{
nsIFrame* kid = mFrames.FirstChild();
// Put each child's background directly onto the content list
nsDisplayListSet set(aLists, aLists.Content());
// The children should be in content order
while (kid) {
PaintChild(aPresContext, aRenderingContext, aDirtyRect, kid, aWhichLayer, aFlags);
nsresult rv = BuildDisplayListForChild(aBuilder, kid, aDirtyRect, set, aFlags);
NS_ENSURE_SUCCESS(rv, rv);
kid = kid->GetNextSibling();
}
}
// Paint one child frame
void
nsContainerFrame::PaintChild(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsIFrame* aFrame,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
{
NS_ASSERTION(aFrame, "no frame to paint!");
if (!aFrame->HasView()) {
nsRect kidRect = aFrame->GetRect();
// Compute the constrained damage area; set the overlap flag to
// PR_TRUE if any portion of the child frame intersects the
// dirty rect.
nsRect damageArea;
PRBool overlap;
if (NS_FRAME_OUTSIDE_CHILDREN & aFrame->GetStateBits()) {
// If the child frame has children that leak out of our box
// then we don't constrain the damageArea to just the childs
// bounding rect.
damageArea = aDirtyRect;
overlap = PR_TRUE;
}
else {
// Compute the intersection of the dirty rect and the childs
// rect (both are in our coordinate space). This limits the
// damageArea to just the portion that intersects the childs
// rect.
overlap = damageArea.IntersectRect(aDirtyRect, kidRect);
#ifdef NS_DEBUG
if (!overlap && (0 == kidRect.width) && (0 == kidRect.height)) {
overlap = PR_TRUE;
}
#endif
}
if (overlap) {
// Translate damage area into the kids coordinate
// system. Translate rendering context into the kids
// coordinate system.
damageArea.x -= kidRect.x;
damageArea.y -= kidRect.y;
{
nsIRenderingContext::AutoPushTranslation
translate(&aRenderingContext, kidRect.x, kidRect.y);
// Paint the kid
aFrame->Paint(aPresContext, aRenderingContext, damageArea, aWhichLayer, aFlags);
}
#ifdef NS_DEBUG
// Draw a border around the child
if (nsIFrameDebug::GetShowFrameBorders() && !kidRect.IsEmpty()) {
aRenderingContext.SetColor(NS_RGB(255,0,0));
aRenderingContext.DrawRect(kidRect);
}
#endif
}
}
}
nsIFrame*
nsContainerFrame::GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer)
{
return GetFrameForPointUsing(aPoint, nsnull, aWhichLayer,
aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND);
}
nsIFrame*
nsContainerFrame::GetFrameForPointUsing(const nsPoint& aPoint,
nsIAtom* aList,
nsFramePaintLayer aWhichLayer,
PRBool aConsiderSelf)
{
nsRect thisRect(nsPoint(0,0), GetSize());
PRBool inThisFrame = thisRect.Contains(aPoint);
if (!((mState & NS_FRAME_OUTSIDE_CHILDREN) || inThisFrame))
return nsnull;
nsIFrame* frame = nsnull;
nsIFrame* kid = GetFirstChild(aList);
while (kid) {
nsIFrame* hit;
nsPoint kidPoint = aPoint - kid->GetOffsetTo(this);
if (aWhichLayer == NS_FRAME_PAINT_LAYER_ALL) {
// Check all layers on this kid before moving on to the next one
hit = kid->GetFrameForPoint(kidPoint,
NS_FRAME_PAINT_LAYER_FOREGROUND);
if (!hit) {
hit = kid->GetFrameForPoint(kidPoint,
NS_FRAME_PAINT_LAYER_FLOATS);
if (!hit) {
hit = kid->GetFrameForPoint(kidPoint,
NS_FRAME_PAINT_LAYER_BACKGROUND);
}
}
} else {
hit = kid->GetFrameForPoint(kidPoint, aWhichLayer);
}
if (hit)
frame = hit;
kid = kid->GetNextSibling();
}
if (frame)
return frame;
if (inThisFrame && aConsiderSelf && GetStyleVisibility()->IsVisible())
return this;
return nsnull;
return NS_OK;
}
NS_IMETHODIMP
@ -401,6 +280,8 @@ nsContainerFrame::PositionFrameView(nsIFrame* aKidFrame)
vm->MoveViewTo(view, pt.x, pt.y);
}
// This code is duplicated in nsDisplayList.cpp. We'll remove the duplication
// when we remove all this view sync code.
static PRBool
NonZeroStyleCoord(const nsStyleCoord& aCoord) {
switch (aCoord.GetUnit()) {
@ -421,13 +302,13 @@ HasNonZeroBorderRadius(nsStyleContext* aStyleContext) {
nsStyleCoord coord;
border->mBorderRadius.GetTop(coord);
if (NonZeroStyleCoord(coord)) return PR_TRUE;
if (NonZeroStyleCoord(coord)) return PR_TRUE;
border->mBorderRadius.GetRight(coord);
if (NonZeroStyleCoord(coord)) return PR_TRUE;
if (NonZeroStyleCoord(coord)) return PR_TRUE;
border->mBorderRadius.GetBottom(coord);
if (NonZeroStyleCoord(coord)) return PR_TRUE;
if (NonZeroStyleCoord(coord)) return PR_TRUE;
border->mBorderRadius.GetLeft(coord);
if (NonZeroStyleCoord(coord)) return PR_TRUE;
if (NonZeroStyleCoord(coord)) return PR_TRUE;
return PR_FALSE;
}
@ -446,13 +327,6 @@ SyncFrameViewGeometryDependentProperties(nsPresContext* aPresContext,
PRBool hasBG =
nsCSSRendering::FindBackground(aPresContext, aFrame, &bg, &isCanvas);
// background-attachment: fixed is not really geometry dependent, but
// we set it here because it's cheap to do so
PRBool fixedBackground = hasBG && bg->HasFixedBackground();
// If the frame has a fixed background attachment, then indicate that the
// view's contents should be repainted and not bitblt'd
vm->SetViewBitBltEnabled(aView, !fixedBackground);
const nsStyleDisplay* display = aStyleContext->GetStyleDisplay();
// If the frame has a solid background color, 'background-clip:border',
// and it's a kind of frame that paints its background, and rounded borders aren't
@ -462,7 +336,6 @@ SyncFrameViewGeometryDependentProperties(nsPresContext* aPresContext,
PRBool viewHasTransparentContent =
!(hasBG && !(bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) &&
!display->mAppearance && bg->mBackgroundClip == NS_STYLE_BG_CLIP_BORDER &&
aFrame->CanPaintBackground() &&
!HasNonZeroBorderRadius(aStyleContext));
PRBool drawnOnUniformField = PR_FALSE;

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

@ -65,13 +65,6 @@ public:
virtual nsIFrame* GetFirstChild(nsIAtom* aListName) const;
virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
NS_IMETHOD Destroy(nsPresContext* aPresContext);
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild);
virtual PRBool IsLeaf() const;
@ -178,28 +171,37 @@ public:
static void PositionChildViews(nsIFrame* aFrame);
/**
* Builds display lists for the children. The background
* of each child is placed in the Content() list (suitable for inline
* children and other elements that behave like inlines,
* but not for in-flow block children of blocks). DOES NOT
* paint the background/borders/outline of this frame. This should
* probably be avoided and eventually removed. It's currently here
* to emulate what nsContainerFrame::Paint did.
*/
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
protected:
nsContainerFrame();
~nsContainerFrame();
virtual nsIFrame* GetFrameForPointUsing(const nsPoint& aPoint,
nsIAtom* aList,
nsFramePaintLayer aWhichLayer,
PRBool aConsiderSelf);
virtual void PaintChildren(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
virtual void PaintChild(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsIFrame* aFrame,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
/**
* Builds a display list for non-block children that behave like
* inlines. This puts the background of each child into the
* Content() list (suitable for inline children but not for
* in-flow block children of blocks).
* @param aForcePseudoStack forces each child into a pseudo-stacking-context
* so its background and all other display items (except for positioned
* display items) go into the Content() list.
*/
nsresult BuildDisplayListForNonBlockChildren(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists,
PRUint32 aFlags = 0);
/**
* Get the frames on the overflow list

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

@ -64,11 +64,6 @@ public:
NS_IMETHOD GetFrameName(nsAString& aResult) const;
#endif
virtual nsIAtom* GetType() const;
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
@ -190,28 +185,6 @@ nsFirstLetterFrame::GetChildFrameContainingOffset(PRInt32 inContentOffset,
return nsFrame::GetChildFrameContainingOffset(inContentOffset, inHint, outFrameContentOffset, outChildFrame);
}
NS_IMETHODIMP
nsFirstLetterFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
{
if (NS_FRAME_IS_UNFLOWABLE & mState) {
return NS_OK;
}
// Paint inline element backgrounds in the foreground layer.
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
PaintSelf(aPresContext, aRenderingContext, aDirtyRect);
}
PaintDecorationsAndChildren(aPresContext, aRenderingContext, aDirtyRect,
aWhichLayer, PR_FALSE, aFlags);
return NS_OK;
}
NS_IMETHODIMP
nsFirstLetterFrame::Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aMetrics,

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

@ -112,6 +112,7 @@
#include "nsHTMLContainerFrame.h"
#include "nsBoxLayoutState.h"
#include "nsBlockFrame.h"
#include "nsDisplayList.h"
static NS_DEFINE_CID(kSelectionImageService, NS_SELECTIONIMAGESERVICE_CID);
static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
@ -762,81 +763,73 @@ nsFrame::DisplaySelection(nsPresContext* aPresContext, PRBool isOkToTurnOn)
return selType;
}
void
nsFrame::SetOverflowClipRect(nsIRenderingContext& aRenderingContext)
class nsDisplaySelectionOverlay : public nsDisplayItem {
public:
nsDisplaySelectionOverlay(nsFrame* aFrame, PRInt16 aSelectionValue)
: mFrame(aFrame), mSelectionValue(aSelectionValue) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("SelectionOverlay")
private:
nsFrame* mFrame;
PRInt16 mSelectionValue;
};
void nsDisplaySelectionOverlay::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
{
// 'overflow-clip' only applies to block-level elements and replaced
// elements that have 'overflow' set to 'hidden', and it is relative
// to the content area and applies to content only (not border or background)
const nsStyleBorder* borderStyle = GetStyleBorder();
const nsStylePadding* paddingStyle = GetStylePadding();
nsCOMPtr<nsISelectionImageService> imageService
= do_GetService(kSelectionImageService);
if (!imageService)
return;
nsCOMPtr<imgIContainer> container;
imageService->GetImage(mSelectionValue, getter_AddRefs(container));
if (!container)
return;
// Start with the 'auto' values and then factor in user specified values
nsRect clipRect(0, 0, mRect.width, mRect.height);
// XXX We don't support the 'overflow-clip' property yet, so just use the
// content area (which is the default value) as the clip shape
clipRect.Deflate(borderStyle->GetBorder());
// XXX We need to handle percentage padding
nsMargin padding;
if (paddingStyle->GetPadding(padding)) {
clipRect.Deflate(padding);
}
#ifdef DEBUG
else {
NS_WARNING("Percentage padding and CLIP overflow don't mix yet");
}
#endif
// Set updated clip-rect into the rendering context
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect);
nsRect rect(aBuilder->ToReferenceFrame(mFrame), mFrame->GetSize());
rect.IntersectRect(rect, aDirtyRect);
aCtx->DrawTile(container, 0, 0, &rect);
}
/********************************************************
* Refreshes each content's frame
*********************************************************/
NS_IMETHODIMP
nsFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
nsresult
nsFrame::DisplaySelectionOverlay(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists,
PRUint16 aContentType)
{
if (aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND)
return NS_OK;
nsresult result;
nsIPresShell *shell = aPresContext->PresShell();
PRInt16 displaySelection = nsISelectionDisplay::DISPLAY_ALL;
if (!(aFlags & nsISelectionDisplay::DISPLAY_IMAGES))
{
result = shell->GetSelectionFlags(&displaySelection);
if (NS_FAILED(result))
return result;
if (!(displaySelection & nsISelectionDisplay::DISPLAY_FRAMES))
return NS_OK;
}
//check frame selection state
PRBool isSelected;
isSelected = (GetStateBits() & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
//if not selected then return
if (!isSelected)
return NS_OK; //nothing to do
if ((GetStateBits() & NS_FRAME_SELECTED_CONTENT) != NS_FRAME_SELECTED_CONTENT)
return NS_OK;
if (!IsVisibleForPainting(aBuilder))
return NS_OK;
nsPresContext* presContext = GetPresContext();
nsIPresShell *shell = presContext->PresShell();
if (!shell)
return NS_OK;
PRInt16 displaySelection;
nsresult rv = shell->GetSelectionFlags(&displaySelection);
if (NS_FAILED(rv))
return rv;
if (!(displaySelection & aContentType))
return NS_OK;
//get the selection controller
nsCOMPtr<nsISelectionController> selCon;
result = GetSelectionController(aPresContext, getter_AddRefs(selCon));
rv = GetSelectionController(presContext, getter_AddRefs(selCon));
if (NS_FAILED(rv) || !selCon)
return rv;
PRInt16 selectionValue;
selCon->GetDisplaySelection(&selectionValue);
displaySelection = selectionValue > nsISelectionController::SELECTION_HIDDEN;
//check display selection state.
if (!displaySelection)
return NS_OK; //if frame does not allow selection. do nothing
if (selectionValue <= nsISelectionController::SELECTION_HIDDEN)
return NS_OK; // selection is hidden or off
nsIContent *newContent = mContent->GetParent();
@ -848,87 +841,629 @@ nsFrame::Paint(nsPresContext* aPresContext,
}
SelectionDetails *details;
if (NS_SUCCEEDED(result) && shell)
{
nsCOMPtr<nsIFrameSelection> frameSelection;
if (NS_SUCCEEDED(result) && selCon)
{
frameSelection = do_QueryInterface(selCon); //this MAY implement
}
if (!frameSelection)
frameSelection = shell->FrameSelection();
result = frameSelection->LookUpSelection(newContent, offset,
1, &details, PR_FALSE);//look up to see what selection(s) are on this frame
}
nsCOMPtr<nsIFrameSelection> frameSelection = do_QueryInterface(selCon);
//this MAY implement
if (!frameSelection)
frameSelection = shell->FrameSelection();
rv = frameSelection->LookUpSelection(newContent, offset,
1, &details, PR_FALSE);//look up to see what selection(s) are on this frame
// XXX is the above really necessary? We don't actually DO anything
// with the details other than test that they're non-null
if (NS_FAILED(rv) || !details)
return rv;
if (details)
{
nsRect rect = GetRect();
rect.width-=2;
rect.height-=2;
rect.x=1; //we are in the coordinate system of the frame now with regards to the rendering context.
rect.y=1;
nsCOMPtr<nsISelectionImageService> imageService;
imageService = do_GetService(kSelectionImageService, &result);
if (NS_SUCCEEDED(result) && imageService)
{
nsCOMPtr<imgIContainer> container;
imageService->GetImage(selectionValue, getter_AddRefs(container));
if (container)
{
nsRect rect(0, 0, mRect.width, mRect.height);
rect.IntersectRect(rect,aDirtyRect);
aRenderingContext.DrawTile(container,0,0,&rect);
}
}
SelectionDetails *deletingDetails = details;
while ((deletingDetails = details->mNext) != nsnull) {
delete details;
details = deletingDetails;
}
while (details) {
SelectionDetails *next = details->mNext;
delete details;
details = next;
}
return NS_OK;
return aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplaySelectionOverlay(this, selectionValue));
}
void
nsFrame::PaintSelf(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
PRIntn aSkipSides,
PRBool aUsePrintBackgroundSettings)
nsresult
nsFrame::DisplayOutlineUnconditional(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists)
{
if (GetStyleOutline()->GetOutlineStyle() == NS_STYLE_BORDER_STYLE_NONE)
return NS_OK;
return aLists.Outlines()->AppendNewToTop(new (aBuilder) nsDisplayOutline(this));
}
nsresult
nsFrame::DisplayOutline(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists)
{
if (!IsVisibleForPainting(aBuilder))
return NS_OK;
return DisplayOutlineUnconditional(aBuilder, aLists);
}
nsresult
nsFrame::DisplayBorderBackgroundOutline(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists,
PRBool aForceBackground)
{
// The visibility check belongs here since child elements have the
// opportunity to override the visibility property and display even if
// their parent is hidden.
if (!IsVisibleForPainting(aBuilder))
return NS_OK;
PRBool isVisible;
if (mRect.height == 0 || mRect.width == 0 ||
NS_FAILED(IsVisibleForPainting(aPresContext, aRenderingContext,
PR_TRUE, &isVisible)) ||
!isVisible) {
return;
// Here we don't try to detect background propagation. Frames that might
// receive a propagated background should just set aForceBackground to
// PR_TRUE.
if (aBuilder->IsForEventDelivery() || aForceBackground ||
!GetStyleBackground()->IsTransparent() || GetStyleDisplay()->mAppearance) {
nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayBackground(this));
NS_ENSURE_SUCCESS(rv, rv);
}
if (HasBorder()) {
nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayBorder(this));
NS_ENSURE_SUCCESS(rv, rv);
}
// Paint our background and border
const nsStyleBorder* border = GetStyleBorder();
const nsStylePadding* padding = GetStylePadding();
const nsStyleOutline* outline = GetStyleOutline();
return DisplayOutlineUnconditional(aBuilder, aLists);
}
nsRect rect(0, 0, mRect.width, mRect.height);
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *border, *padding,
aUsePrintBackgroundSettings);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *border, mStyleContext,
aSkipSides);
nsCSSRendering::PaintOutline(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *border, *outline,
mStyleContext, 0);
static PRBool ApplyAbsPosClipping(nsDisplayListBuilder* aBuilder,
const nsStyleDisplay* aDisp, nsIFrame* aFrame,
nsRect* aRect) {
// REVIEW: from nsContainerFrame.cpp SyncFrameViewGeometryDependentProperties
if (!aDisp->IsAbsolutelyPositioned() ||
!(aDisp->mClipFlags & NS_STYLE_CLIP_RECT))
return PR_FALSE;
// A moving frame should not be allowed to clip a non-moving frame.
// Abs-pos clipping always clips frames below it in the frame tree, except
// for when an abs-pos frame clips a fixed-pos frame. So when fixed-pos
// elements are present we do not allow a moving abs-pos frame with
// an out-of-flow descendant (which could be a fixed frame) child to clip
// anything. It's OK to not clip anything, even the moving children ...
// all that could happen is that we get unnecessarily conservative results
// for nsLayoutUtils::ComputeRepaintRegionForCopy ... but this is a rare
// situation.
if (aBuilder->HasMovingFrames() &&
(aFrame->GetStateBits() & NS_FRAME_HAS_DESCENDANT_PLACEHOLDER) &&
aFrame->GetPresContext()->FrameManager()->GetRootFrame()->
GetFirstChild(nsLayoutAtoms::fixedList) &&
aBuilder->IsMovingFrame(aFrame))
return PR_FALSE;
// Start with the 'auto' values and then factor in user specified values
aRect->SetRect(aBuilder->ToReferenceFrame(aFrame), aFrame->GetSize());
if (0 == (NS_STYLE_CLIP_TOP_AUTO & aDisp->mClipFlags)) {
aRect->y += aDisp->mClip.y;
}
if (0 == (NS_STYLE_CLIP_LEFT_AUTO & aDisp->mClipFlags)) {
aRect->x += aDisp->mClip.x;
}
if (0 == (NS_STYLE_CLIP_RIGHT_AUTO & aDisp->mClipFlags)) {
aRect->width = aDisp->mClip.width;
}
if (0 == (NS_STYLE_CLIP_BOTTOM_AUTO & aDisp->mClipFlags)) {
aRect->height = aDisp->mClip.height;
}
return PR_TRUE;
}
/**
* Returns PR_TRUE if aFrame is overflow:hidden and we should interpret
* that as -moz-hidden-unscrollable.
*/
static PRBool ApplyOverflowHiddenClipping(nsIFrame* aFrame,
const nsStyleDisplay* aDisp)
{
if (aDisp->mOverflowX != NS_STYLE_OVERFLOW_HIDDEN)
return PR_FALSE;
nsIAtom* type = aFrame->GetType();
// REVIEW: these are the frame types that call IsTableClip and set up
// clipping. Actually there were also table rows and the inner table frame
// doing this, but 'overflow' isn't applicable to them according to
// CSS 2.1 so I removed them. Also, we used to clip at tableOuterFrame
// but we should actually clip at tableFrame (as per discussion with Hixie and
// bz).
return type == nsLayoutAtoms::tableFrame ||
type == nsLayoutAtoms::tableCellFrame ||
type == nsLayoutAtoms::bcTableCellFrame;
}
static PRBool ApplyOverflowClipping(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
const nsStyleDisplay* aDisp, nsRect* aRect) {
// REVIEW: from nsContainerFrame.cpp SyncFrameViewGeometryDependentProperties,
// except that that function used the border-edge for
// -moz-hidden-unscrollable which I don't think is correct... Also I've
// changed -moz-hidden-unscrollable to apply to any kind of frame.
// Only -moz-hidden-unscrollable is handled here (and 'hidden' for table
// frames). Other overflow clipping is applied by nsHTML/XULScrollFrame.
if (!ApplyOverflowHiddenClipping(aFrame, aDisp)) {
PRBool clip = aDisp->mOverflowX == NS_STYLE_OVERFLOW_CLIP;
if (!clip)
return PR_FALSE;
// We allow -moz-hidden-unscrollable to apply to any kind of frame. This
// is required by comboboxes which make their display text (an inline frame)
// have clipping.
}
aRect->SetRect(aBuilder->ToReferenceFrame(aFrame), aFrame->GetSize());
const nsStyleBorder* borderStyle = aFrame->GetStyleContext()->GetStyleBorder();
aRect->Deflate(borderStyle->GetBorder());
return PR_TRUE;
}
class nsOverflowClipWrapper : public nsDisplayWrapper
{
public:
/**
* Create a wrapper to apply overflow clipping for aContainer.
* @param aClipBorderBackground set to PR_TRUE to clip the BorderBackground()
* list, otherwise it will not be clipped
* @param aClipAll set to PR_TRUE to clip all descendants, even those for
* which we aren't the containing block
*/
nsOverflowClipWrapper(nsIFrame* aContainer, const nsRect& aRect,
PRBool aClipBorderBackground, PRBool aClipAll)
: mContainer(aContainer), mRect(aRect),
mClipBorderBackground(aClipBorderBackground), mClipAll(aClipAll) {}
virtual PRBool WrapBorderBackground() { return mClipBorderBackground; }
virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList) {
// We are not a stacking context root. There is no valid underlying
// frame for the whole list. These items are all in-flow descendants so
// we can safely just clip them.
return new (aBuilder) nsDisplayClip(nsnull, aList, mRect);
}
virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem) {
nsIFrame* f = aItem->GetUnderlyingFrame();
if (mClipAll || nsLayoutUtils::IsProperAncestorFrame(mContainer, f, nsnull))
return new (aBuilder) nsDisplayClip(f, aItem, mRect);
return aItem;
}
protected:
nsIFrame* mContainer;
nsRect mRect;
PRPackedBool mClipBorderBackground;
PRPackedBool mClipAll;
};
class nsAbsPosClipWrapper : public nsDisplayWrapper
{
public:
nsAbsPosClipWrapper(const nsRect& aRect)
: mRect(aRect) {}
virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList) {
// We are not a stacking context root. There is no valid underlying
// frame for the whole list.
return new (aBuilder) nsDisplayClip(nsnull, aList, mRect);
}
virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem) {
return new (aBuilder) nsDisplayClip(aItem->GetUnderlyingFrame(), aItem, mRect);
}
protected:
nsRect mRect;
};
nsresult
nsIFrame::OverflowClip(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aFromSet,
const nsDisplayListSet& aToSet,
const nsRect& aClipRect,
PRBool aClipBorderBackground,
PRBool aClipAll)
{
nsOverflowClipWrapper wrapper(this, aClipRect, aClipBorderBackground, aClipAll);
return wrapper.WrapLists(aBuilder, this, aFromSet, aToSet);
}
nsresult
nsIFrame::Clip(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aFromSet,
const nsDisplayListSet& aToSet,
const nsRect& aClipRect)
{
nsAbsPosClipWrapper wrapper(aClipRect);
return wrapper.WrapLists(aBuilder, this, aFromSet, aToSet);
}
static nsresult
BuildDisplayListWithOverflowClip(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsRect& aDirtyRect, const nsDisplayListSet& aSet,
const nsRect& aClipRect)
{
nsDisplayListCollection set;
nsresult rv = aFrame->BuildDisplayList(aBuilder, aDirtyRect, set);
NS_ENSURE_SUCCESS(rv, rv);
return aFrame->OverflowClip(aBuilder, set, aSet, aClipRect);
}
nsresult
nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
nsDisplayList* aList) {
if (GetStateBits() & NS_FRAME_IS_UNFLOWABLE) {
RemoveStateBits(NS_FRAME_HAS_DESCENDANT_PLACEHOLDER);
return NS_OK;
}
// Replaced elements have their visibility handled here, because
// they're visually atomic
if ((GetStateBits() & NS_FRAME_REPLACED_ELEMENT) &&
!IsVisibleForPainting(aBuilder))
return NS_OK;
if (GetStyleVisibility()->mVisible == NS_STYLE_VISIBILITY_COLLAPSE)
return NS_OK;
nsRect absPosClip;
const nsStyleDisplay* disp = GetStyleDisplay();
PRBool applyAbsPosClipping =
ApplyAbsPosClipping(aBuilder, disp, this, &absPosClip);
nsRect dirtyRect = aDirtyRect;
if (applyAbsPosClipping) {
dirtyRect.IntersectRect(dirtyRect,
absPosClip - aBuilder->ToReferenceFrame(this));
}
nsDisplayListCollection set;
nsresult rv;
{
nsDisplayListBuilder::AutoIsRootSetter rootSetter(aBuilder, PR_TRUE);
rv = BuildDisplayList(aBuilder, dirtyRect, set);
}
RemoveStateBits(NS_FRAME_HAS_DESCENDANT_PLACEHOLDER);
NS_ENSURE_SUCCESS(rv, rv);
if (aBuilder->IsBackgroundOnly()) {
set.BlockBorderBackgrounds()->DeleteAll();
set.Floats()->DeleteAll();
set.Content()->DeleteAll();
set.PositionedDescendants()->DeleteAll();
set.Outlines()->DeleteAll();
}
// This z-order sort also sorts secondarily by content order. We need to do
// this so that boxes produced by the same element are placed together
// in the sort. Consider a position:relative inline element that breaks
// across lines and has absolutely positioned children; all the abs-pos
// children should be z-ordered after all the boxes for the position:relative
// element itself.
set.PositionedDescendants()->SortByZOrder(aBuilder, GetContent());
nsRect overflowClip;
if (ApplyOverflowClipping(aBuilder, this, disp, &overflowClip)) {
nsOverflowClipWrapper wrapper(this, overflowClip, PR_FALSE, PR_FALSE);
rv = wrapper.WrapListsInPlace(aBuilder, this, set);
NS_ENSURE_SUCCESS(rv, rv);
}
// We didn't use overflowClip to restrict the dirty rect, since some of the
// descendants may not be clipped by it. Even if we end up with unnecessary
// display items, they'll be pruned during OptimizeVisibility.
nsDisplayList resultList;
// Now follow the rules of http://www.w3.org/TR/CSS21/zindex.html
// 1,2: backgrounds and borders
resultList.AppendToTop(set.BorderBackground());
// 3: negative z-index children.
for (;;) {
nsDisplayItem* item = set.PositionedDescendants()->GetBottom();
if (item) {
nsIFrame* f = item->GetUnderlyingFrame();
NS_ASSERTION(f, "After sorting, every item in the list should have an underlying frame");
if (nsLayoutUtils::GetZIndex(f) < 0) {
set.PositionedDescendants()->RemoveBottom();
resultList.AppendToTop(item);
continue;
}
}
break;
}
// 4: block backgrounds
resultList.AppendToTop(set.BlockBorderBackgrounds());
// 5: floats
resultList.AppendToTop(set.Floats());
// 6: general content
resultList.AppendToTop(set.Content());
// 7, 8: non-negative z-index children
resultList.AppendToTop(set.PositionedDescendants());
// 9: outlines, in content tree order. We need to sort by content order
// because an element with outline that breaks and has children with outline
// might have placed child outline items between its own outline items.
// The element's outline items need to all come before any child outline
// items.
set.Outlines()->SortByContentOrder(aBuilder, GetContent());
resultList.AppendToTop(set.Outlines());
if (applyAbsPosClipping) {
nsAbsPosClipWrapper wrapper(absPosClip);
nsDisplayItem* item = wrapper.WrapList(aBuilder, this, &resultList);
if (!item)
return NS_ERROR_OUT_OF_MEMORY;
// resultList was emptied
resultList.AppendToTop(item);
}
if (disp->mOpacity == 1.0f) {
aList->AppendToTop(&resultList);
} else {
rv = aList->AppendNewToTop(new (aBuilder) nsDisplayOpacity(this, &resultList));
}
return rv;
}
static nsIFrame* GetParentOrPlaceholderFor(nsFrameManager* aFrameManager, nsIFrame* aFrame) {
if (aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
return aFrameManager->GetPlaceholderFrameFor(aFrame);
}
return aFrame->GetParent();
}
static void MarkOutOfFlowChild(nsIFrame* aFrame, nsIFrame* aChild,
const nsRect& aDirtyRect, PRBool aMark) {
if (aMark) {
nsRect dirty = aDirtyRect - aChild->GetOffsetTo(aFrame);
nsRect overflowRect = aChild->GetOverflowRect();
if (!dirty.IntersectRect(dirty, overflowRect))
return;
// if "new nsRect" fails, this won't do anything, but that's okay
aChild->SetProperty(nsLayoutAtoms::outOfFlowDirtyRectProperty,
new nsRect(dirty));
} else {
aChild->DeleteProperty(nsLayoutAtoms::outOfFlowDirtyRectProperty);
}
nsFrameManager* frameManager = aChild->GetPresContext()->PresShell()->FrameManager();
nsIFrame* placeholder = frameManager->GetPlaceholderFrameFor(aChild);
NS_ASSERTION(placeholder, "No placeholder for out of flow?");
if (!placeholder)
return;
nsIFrame* f;
for (f = placeholder; f; f = GetParentOrPlaceholderFor(frameManager, f)) {
if (((f->GetStateBits() & NS_FRAME_HAS_DESCENDANT_PLACEHOLDER) != 0)
== aMark)
return;
if (aMark) {
f->AddStateBits(NS_FRAME_HAS_DESCENDANT_PLACEHOLDER);
} else {
f->RemoveStateBits(NS_FRAME_HAS_DESCENDANT_PLACEHOLDER);
}
if (f == aFrame)
break;
}
NS_ASSERTION(f, "Did not find ourselves on the placeholder's ancestor chain");
}
void
nsIFrame::MarkOutOfFlowChildrenForDisplayList(nsIFrame* aFirstChild,
const nsRect& aDirtyRect) {
while (aFirstChild) {
MarkOutOfFlowChild(this, aFirstChild, aDirtyRect, PR_TRUE);
aFirstChild = aFirstChild->GetNextSibling();
}
}
void
nsIFrame::UnmarkOutOfFlowChildrenForDisplayList(nsIFrame* aFirstChild) {
nsRect empty;
while (aFirstChild) {
MarkOutOfFlowChild(this, aFirstChild, empty, PR_FALSE);
aFirstChild = aFirstChild->GetNextSibling();
}
}
#ifdef NS_DEBUG
static void PaintDebugBorder(nsIFrame* aFrame, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aPt) {
nsRect r(aPt, aFrame->GetSize());
if (aFrame->HasView()) {
aCtx->SetColor(NS_RGB(0,0,255));
} else {
aCtx->SetColor(NS_RGB(255,0,0));
}
aCtx->DrawRect(r);
}
#endif
nsresult
nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
nsIFrame* aChild,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists,
PRUint32 aFlags) {
// If painting is restricted to just the background of the top level frame,
// then we have nothing to do here.
if (aBuilder->IsBackgroundOnly())
return NS_OK;
if (aChild->GetStateBits() & NS_FRAME_IS_UNFLOWABLE)
return NS_OK;
// PR_TRUE if this is a real or pseudo stacking context
PRBool pseudoStackingContext =
(aFlags & DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT) != 0;
if ((aFlags & DISPLAY_CHILD_INLINE) && aChild->IsContainingBlock()) {
// child is a block or table-like frame in an inline context, i.e.,
// it acts like inline-block or inline-table. Therefore it is a
// pseudo-stacking-context.
pseudoStackingContext = PR_TRUE;
}
// dirty rect in child-relative coordinates
nsRect dirty = aDirtyRect - aChild->GetOffsetTo(this);
if (aChild->GetType() == nsLayoutAtoms::placeholderFrame) {
nsPlaceholderFrame* placeholder = NS_STATIC_CAST(nsPlaceholderFrame*, aChild);
aChild = placeholder->GetOutOfFlowFrame();
NS_ASSERTION(aChild, "No out of flow frame?");
if (!aChild)
return NS_OK;
// Recheck NS_FRAME_IS_FLOWABLE
if (aChild->GetStateBits() & NS_FRAME_IS_UNFLOWABLE)
return NS_OK;
nsRect* savedDirty = NS_STATIC_CAST(nsRect*,
aChild->GetProperty(nsLayoutAtoms::outOfFlowDirtyRectProperty));
if (savedDirty) {
dirty = *savedDirty;
} else {
// The out-of-flow frame did not intersect the dirty area. We may still
// need to traverse into it, since it may contain placeholders we need
// to enter to reach other out-of-flow frames that are visible.
dirty.Empty();
}
pseudoStackingContext = PR_TRUE;
} else {
dirty.IntersectRect(dirty, aChild->GetOverflowRect());
}
// If this child has a placeholder of interest then we must descend into
// it even if the child's descendant frames don't intersect the dirty
// area themselves.
// If the child is a scrollframe that we want to ignore, then we need
// to descend into it because its scrolled child may intersect the dirty
// area even if the scrollframe itself doesn't.
if (dirty.IsEmpty() &&
!(aChild->GetStateBits() & NS_FRAME_HAS_DESCENDANT_PLACEHOLDER) &&
aChild != aBuilder->GetIgnoreScrollFrame())
return NS_OK;
// Don't remove NS_FRAME_HAS_DESCENDANT_PLACEHOLDER until after we've
// processed the frame ... it could be useful for frames to know this
if (aChild->GetStyleVisibility()->mVisible == NS_STYLE_VISIBILITY_COLLAPSE)
return NS_OK;
// XXX need to have inline-block and inline-table set pseudoStackingContext
const nsStyleDisplay* ourDisp = GetStyleDisplay();
// REVIEW: Taken from nsBoxFrame::Paint
// Don't paint our children if the theme object is a leaf.
if (IsThemed(ourDisp) &&
!GetPresContext()->GetTheme()->WidgetIsContainer(ourDisp->mAppearance))
return NS_OK;
#ifdef NS_DEBUG
// Draw a border around the child
// REVIEW: From nsContainerFrame::PaintChild
if (nsIFrameDebug::GetShowFrameBorders() && !aChild->GetRect().IsEmpty()) {
nsresult rv = aLists.Outlines()->AppendNewToTop(new (aBuilder)
nsDisplayGeneric(aChild, PaintDebugBorder, "DebugBorder"));
NS_ENSURE_SUCCESS(rv, rv);
}
#endif
const nsStyleDisplay* disp = aChild->GetStyleDisplay();
PRBool isComposited = disp->mOpacity != 1.0f;
PRBool isPositioned = disp->IsPositioned();
if (isComposited || isPositioned) {
// If you change this, also change IsPseudoStackingContextFromStyle()
pseudoStackingContext = PR_TRUE;
}
nsRect overflowClip;
PRBool applyOverflowClip =
ApplyOverflowClipping(aBuilder, aChild, disp, &overflowClip);
// Don't use overflowClip to restrict the dirty rect, since some of the
// descendants may not be clipped by it. Even if we end up with unnecessary
// display items, they'll be pruned during OptimizeVisibility. Note that
// this overflow-clipping here only applies to overflow:-moz-hidden-unscrollable;
// overflow:hidden etc creates an nsHTML/XULScrollFrame which does its own
// clipping.
nsDisplayListBuilder::AutoIsRootSetter rootSetter(aBuilder, pseudoStackingContext);
nsresult rv;
if (!pseudoStackingContext) {
// THIS IS THE COMMON CASE.
// Not a pseudo or real stacking context. Do the simple thing and
// return early.
if (applyOverflowClip) {
rv = BuildDisplayListWithOverflowClip(aBuilder, aChild, dirty, aLists,
overflowClip);
} else {
rv = aChild->BuildDisplayList(aBuilder, dirty, aLists);
}
aChild->RemoveStateBits(NS_FRAME_HAS_DESCENDANT_PLACEHOLDER);
return NS_OK;
}
nsDisplayList list;
nsDisplayList extraPositionedDescendants;
const nsStylePosition* pos = aChild->GetStylePosition();
if ((isPositioned && pos->mZIndex.GetUnit() == eStyleUnit_Integer) ||
isComposited) {
// True stacking context
rv = aChild->BuildDisplayListForStackingContext(aBuilder, dirty, &list);
} else {
nsRect clipRect;
PRBool applyAbsPosClipping =
ApplyAbsPosClipping(aBuilder, disp, aChild, &clipRect);
// A psuedo-stacking context (e.g., a positioned element with z-index auto).
// we allow positioned descendants of this element to escape to our
// container's positioned descendant list, because they might be
// z-index:non-auto
nsDisplayListCollection pseudoStack;
nsRect clippedDirtyRect = dirty;
if (applyAbsPosClipping) {
// clipRect is in builder-reference-frame coordinates,
// dirty/clippedDirtyRect are in aChild coordinates
clippedDirtyRect.IntersectRect(clippedDirtyRect,
clipRect - aBuilder->ToReferenceFrame(aChild));
}
if (applyOverflowClip) {
rv = BuildDisplayListWithOverflowClip(aBuilder, aChild, clippedDirtyRect,
pseudoStack, overflowClip);
} else {
rv = aChild->BuildDisplayList(aBuilder, clippedDirtyRect, pseudoStack);
}
aChild->RemoveStateBits(NS_FRAME_HAS_DESCENDANT_PLACEHOLDER);
if (NS_SUCCEEDED(rv)) {
if (isPositioned && applyAbsPosClipping) {
nsAbsPosClipWrapper wrapper(clipRect);
rv = wrapper.WrapListsInPlace(aBuilder, aChild, pseudoStack);
}
}
list.AppendToTop(pseudoStack.BorderBackground());
list.AppendToTop(pseudoStack.BlockBorderBackgrounds());
list.AppendToTop(pseudoStack.Floats());
list.AppendToTop(pseudoStack.Content());
extraPositionedDescendants.AppendToTop(pseudoStack.PositionedDescendants());
aLists.Outlines()->AppendToTop(pseudoStack.Outlines());
}
NS_ENSURE_SUCCESS(rv, rv);
if (isPositioned || isComposited) {
// Genuine stacking contexts, and positioned pseudo-stacking-contexts,
// go in this level.
rv = aLists.PositionedDescendants()->AppendNewToTop(new (aBuilder)
nsDisplayWrapList(aChild, &list));
NS_ENSURE_SUCCESS(rv, rv);
} else if (disp->IsFloating()) {
rv = aLists.Floats()->AppendNewToTop(new (aBuilder)
nsDisplayWrapList(aChild, &list));
NS_ENSURE_SUCCESS(rv, rv);
} else {
aLists.Content()->AppendToTop(&list);
}
// We delay placing the positioned descendants of positioned frames to here,
// because in the absence of z-index this is the correct order for them.
// This doesn't affect correctness because the positioned descendants list
// is sorted by z-order and content in BuildDisplayListForStackingContext,
// but it means that sort routine needs to do less work.
aLists.PositionedDescendants()->AppendToTop(&extraPositionedDescendants);
return NS_OK;
}
nsresult
@ -2198,18 +2733,6 @@ nsFrame::GetCursor(const nsPoint& aPoint,
return NS_OK;
}
nsIFrame*
nsFrame::GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer)
{
nsRect thisRect(nsPoint(0,0), GetSize());
if (aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND &&
thisRect.Contains(aPoint) && GetStyleVisibility()->IsVisible()) {
return this;
}
return nsnull;
}
// Resize and incremental reflow
// nsIHTMLReflow member functions
@ -2963,66 +3486,58 @@ nsFrame::ParentDisablesSelection() const
return PR_FALSE;
}
nsresult
nsFrame::GetSelectionForVisCheck(nsPresContext * aPresContext, nsISelection** aSelection)
{
*aSelection = nsnull;
nsresult rv = NS_OK;
// start by checking to see if we are paginated which probably means
// we are in print preview or printing
if (aPresContext->IsPaginated()) {
// now see if we are rendering selection only
if (aPresContext->IsRenderingOnlySelection()) {
// Check the quick way first (typically only leaf nodes)
PRBool isSelected = (mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
// if we aren't selected in the mState,
// we could be a container so check to see if we are in the selection range
// this is a expensive
if (!isSelected) {
nsIPresShell *shell = aPresContext->GetPresShell();
if (shell) {
nsCOMPtr<nsISelectionController> selcon(do_QueryInterface(shell));
if (selcon) {
rv = selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, aSelection);
}
}
}
}
}
return rv;
PRBool
nsIFrame::IsVisibleForPainting(nsDisplayListBuilder* aBuilder) {
if (!GetStyleVisibility()->IsVisible())
return PR_FALSE;
nsISelection* sel = aBuilder->GetBoundingSelection();
return !sel || IsVisibleInSelection(sel);
}
PRBool
nsIFrame::IsVisibleForPainting() {
if (!GetStyleVisibility()->IsVisible())
return PR_FALSE;
NS_IMETHODIMP
nsFrame::IsVisibleForPainting(nsPresContext * aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aCheckVis,
PRBool* aIsVisible)
nsPresContext* pc = GetPresContext();
if (!pc->IsRenderingOnlySelection())
return PR_TRUE;
nsCOMPtr<nsISelectionController> selcon(do_QueryInterface(pc->PresShell()));
if (selcon) {
nsCOMPtr<nsISelection> sel;
selcon->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(sel));
if (sel)
return IsVisibleInSelection(sel);
}
return PR_TRUE;
}
PRBool
nsIFrame::IsVisibleInSelection(nsDisplayListBuilder* aBuilder) {
nsISelection* sel = aBuilder->GetBoundingSelection();
return !sel || IsVisibleInSelection(sel);
}
PRBool
nsIFrame::IsVisibleOrCollapsedForPainting(nsDisplayListBuilder* aBuilder) {
if (!GetStyleVisibility()->IsVisibleOrCollapsed())
return PR_FALSE;
nsISelection* sel = aBuilder->GetBoundingSelection();
return !sel || IsVisibleInSelection(sel);
}
PRBool
nsIFrame::IsVisibleInSelection(nsISelection* aSelection)
{
// first check to see if we are visible
if (aCheckVis) {
if (!GetStyleVisibility()->IsVisible()) {
*aIsVisible = PR_FALSE;
return NS_OK;
}
}
// Start by assuming we are visible and need to be painted
*aIsVisible = PR_TRUE;
// NOTE: GetSelectionforVisCheck checks the pagination to make sure we are printing
// In otherwords, the selection will ALWAYS be null if we are not printing, meaning
// the visibility will be TRUE in that case
nsCOMPtr<nsISelection> selection;
nsresult rv = GetSelectionForVisCheck(aPresContext, getter_AddRefs(selection));
if (NS_SUCCEEDED(rv) && selection) {
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mContent));
selection->ContainsNode(node, PR_TRUE, aIsVisible);
}
return rv;
if ((mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT)
return PR_TRUE;
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mContent));
PRBool vis;
nsresult rv = aSelection->ContainsNode(node, PR_TRUE, &vis);
return NS_FAILED(rv) || vis;
}
/* virtual */ PRBool
@ -3603,9 +4118,8 @@ FindBlockFrameOrBR(nsIFrame* aFrame, nsDirection aDirection)
aFrame->GetType() == nsLayoutAtoms::brFrame) {
nsIContent* content = aFrame->GetContent();
result.mContent = content->GetParent();
if (result.mContent)
result.mOffset = result.mContent->IndexOf(content) +
(aDirection == eDirPrevious ? 1 : 0);
result.mOffset = result.mContent->IndexOf(content) +
(aDirection == eDirPrevious ? 1 : 0);
return result;
}

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

@ -184,11 +184,6 @@ public:
NS_IMETHOD SetParent(const nsIFrame* aParent);
virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
virtual nsIFrame* GetFirstChild(nsIAtom* aListName) const;
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus);
@ -197,8 +192,6 @@ public:
nsIContent** aContent);
NS_IMETHOD GetCursor(const nsPoint& aPoint,
nsIFrame::Cursor& aCursor);
virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD GetPointFromOffset(nsPresContext* inPresContext,
nsIRenderingContext* inRendContext,
@ -260,12 +253,6 @@ public:
nsIFrame** aProviderFrame,
PRBool* aIsChild);
// Check Style Visibility and mState for Selection (when printing)
NS_IMETHOD IsVisibleForPainting(nsPresContext * aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aCheckVis,
PRBool* aIsVisible);
virtual PRBool IsEmpty();
virtual PRBool IsSelfEmpty();
@ -446,21 +433,55 @@ public:
static void DisplayReflowShutdown();
#endif
/**
* Adds display items for standard CSS borders, background and outline for
* for this frame, as necessary. Checks IsVisibleForPainting and won't
* display anything if the frame is not visible.
* @param aForceBackground draw the background even if the frame
* background style appears to have no background --- this is useful
* for frames that might receive a propagated background via
* nsCSSRendering::FindBackground
*/
nsresult DisplayBorderBackgroundOutline(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists,
PRBool aForceBackground = PR_FALSE);
/**
* Add a display item for the CSS outline. Does not check visibility.
*/
nsresult DisplayOutlineUnconditional(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists);
/**
* Add a display item for the CSS outline, after calling
* IsVisibleForPainting to confirm we are visible.
*/
nsresult DisplayOutline(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists);
protected:
// Protected constructor and destructor
nsFrame();
virtual ~nsFrame();
/**
* To be called by |Paint| of this class or derived classes to paint
* the background, border, and outline, when in the correct layer to
* do so.
* @return PR_FALSE if this frame definitely has no borders at all
*/
PRBool HasBorder() {
const nsStyleBorder* border = GetStyleBorder();
for (PRInt32 i = 0; i < 4; ++i) {
if (border->GetBorderStyle(i) != NS_STYLE_BORDER_STYLE_NONE)
return PR_TRUE;
}
return PR_FALSE;
}
/**
* To be called by |BuildDisplayLists| of this class or derived classes to add
* a translucent overlay if this frame's content is selected.
* @param aContentType an nsISelectionDisplay DISPLAY_ constant identifying
* which kind of content this is for
*/
void PaintSelf(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
PRIntn aSkipSides = 0,
PRBool aUsePrintBackgroundSettings = PR_TRUE);
nsresult DisplaySelectionOverlay(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists, PRUint16 aContentType = nsISelectionDisplay::DISPLAY_FRAMES);
PRInt16 DisplaySelection(nsPresContext* aPresContext, PRBool isOkToTurnOn = PR_FALSE);
@ -470,9 +491,6 @@ protected:
// Style post processing hook
NS_IMETHOD DidSetStyleContext(nsPresContext* aPresContext);
// Helper routine for determining whether to print selection
nsresult GetSelectionForVisCheck(nsPresContext * aPresContext, nsISelection** aSelection);
//return the line number of the aFrame
static PRInt32 GetLineNumber(nsIFrame *aFrame);
@ -499,12 +517,6 @@ protected:
virtual PRBool ParentDisablesSelection() const;
// Set the overflow clip rect into the rendering-context. Used for block-level
// elements and replaced elements that have 'overflow' set to 'hidden'. This
// member function assumes that the caller has checked that the clip property
// applies to its situation.
void SetOverflowClipRect(nsIRenderingContext& aRenderingContext);
// Fills aCursor with the appropriate information from ui
static void FillCursorInformationFromStyle(const nsStyleUserInterface* ui,
nsIFrame::Cursor& aCursor);

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

@ -82,6 +82,7 @@
#include "nsIFrameFrame.h"
#include "nsAutoPtr.h"
#include "nsIDOMNSHTMLDocument.h"
#include "nsDisplayList.h"
#ifdef NS_PRINTING
#include "nsIWebBrowserPrint.h"
@ -127,6 +128,10 @@ public:
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
@ -288,6 +293,28 @@ nsSubDocumentFrame::GetSkipSides() const
return 0;
}
NS_IMETHODIMP
nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
if (!IsVisibleForPainting(aBuilder))
return NS_OK;
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
nsIView* subdocView = mInnerView->GetFirstChild();
if (!subdocView)
return NS_OK;
nsIFrame* f = NS_STATIC_CAST(nsIFrame*, subdocView->GetClientData());
if (!f)
return NS_OK;
nsRect dirty = aDirtyRect - f->GetOffsetTo(this);
return f->BuildDisplayListForStackingContext(aBuilder, dirty, aLists.Content());
}
void
nsSubDocumentFrame::GetDesiredSize(nsPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,

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

@ -71,6 +71,7 @@
#include "nsStyleSet.h"
#include "nsLayoutAtoms.h"
#include "nsIContent.h"
#include "nsDisplayList.h"
// masks for mEdgeVisibility
#define LEFT_VIS 0x0001
@ -135,17 +136,12 @@ public:
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus);
nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD GetCursor(const nsPoint& aPoint,
nsIFrame::Cursor& aCursor);
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
@ -156,6 +152,8 @@ public:
void SetVisibility(PRBool aVisibility);
void SetColor(nscolor aColor);
void PaintBorder(nsIRenderingContext& aRenderingContext, nsPoint aPt);
protected:
nsHTMLFramesetBorderFrame(PRInt32 aWidth, PRBool aVertical, PRBool aVisible);
virtual ~nsHTMLFramesetBorderFrame();
@ -184,11 +182,9 @@ public:
NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const;
#endif
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
@ -839,26 +835,22 @@ nsHTMLFramesetFrame::GetCursor(const nsPoint& aPoint,
return NS_OK;
}
nsIFrame*
nsHTMLFramesetFrame::GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer)
{
//XXX Temporary to deal with event handling in both this and FramsetBorderFrame
if (mDragger)
return this;
return nsContainerFrame::GetFrameForPoint(aPoint, aWhichLayer);
}
NS_IMETHODIMP
nsHTMLFramesetFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
nsHTMLFramesetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
//printf("frameset paint %X (%d,%d,%d,%d) \n", this, aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
return nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext,
aDirtyRect, aWhichLayer);
nsresult rv = nsHTMLContainerFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
NS_ENSURE_SUCCESS(rv, rv);
if (mDragger && aBuilder->IsForEventDelivery()) {
// REVIEW: GetFrameForPoint would always target ourselves if mDragger set
nsDisplayItem* item = new (aBuilder) nsDisplayEventReceiver(this);
if (!item)
return NS_ERROR_OUT_OF_MEMORY;
aLists.Content()->AppendToTop(item);
}
return rv;
}
void
@ -1315,7 +1307,6 @@ nsHTMLFramesetFrame::CanResize(PRBool aVertical,
PRBool
nsHTMLFramesetFrame::GetNoResize(nsIFrame* aChildFrame)
{
PRBool result = PR_FALSE;
nsIContent* content = aChildFrame->GetContent();
return content && content->HasAttr(kNameSpaceID_None, nsHTMLAtoms::noresize);
@ -1627,23 +1618,50 @@ nsHTMLFramesetBorderFrame::Reflow(nsPresContext* aPresContext,
return NS_OK;
}
NS_METHOD
nsHTMLFramesetBorderFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
class nsDisplayFramesetBorder : public nsDisplayItem {
public:
nsDisplayFramesetBorder(nsHTMLFramesetBorderFrame* aFrame) : mFrame(aFrame) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
// REVIEW: see old GetFrameForPoint
// Receives events in its bounds
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt) { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("FramesetBorder")
private:
nsHTMLFramesetBorderFrame* mFrame;
};
void nsDisplayFramesetBorder::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
{
mFrame->PaintBorder(*aCtx, aBuilder->ToReferenceFrame(mFrame));
}
NS_IMETHODIMP
nsHTMLFramesetBorderFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
nsDisplayItem* item = new (aBuilder) nsDisplayFramesetBorder(this);
if (!item)
return NS_ERROR_OUT_OF_MEMORY;
aLists.Content()->AppendToTop(item);
return NS_OK;
}
void nsHTMLFramesetBorderFrame::PaintBorder(nsIRenderingContext& aRenderingContext,
nsPoint aPt)
{
if (NS_FRAME_PAINT_LAYER_FOREGROUND != aWhichLayer) {
return NS_OK;
}
//printf("border frame paint %X (%d,%d,%d,%d) \n", this, aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
nscolor WHITE = NS_RGB(255, 255, 255);
nscolor bgColor = NS_RGB(200,200,200);
nscolor fgColor = NS_RGB(0,0,0);
nscolor hltColor = NS_RGB(255,255,255);
nscolor sdwColor = NS_RGB(128,128,128);
nsIRenderingContext::AutoPushTranslation
translate(&aRenderingContext, aPt.x, aPt.y);
{
nsCOMPtr<nsILookAndFeel> lookAndFeel = do_GetService(kLookAndFeelCID);
if (lookAndFeel) {
@ -1654,16 +1672,16 @@ nsHTMLFramesetBorderFrame::Paint(nsPresContext* aPresContext,
}
}
nsPresContext* presContext = GetPresContext();
float t2p;
t2p = aPresContext->TwipsToPixels();
t2p = presContext->TwipsToPixels();
nscoord widthInPixels = NSTwipsToIntPixels(mWidth, t2p);
float p2t;
p2t = aPresContext->PixelsToTwips();
p2t = presContext->PixelsToTwips();
nscoord pixelWidth = NSIntPixelsToTwips(1, p2t);
if (widthInPixels <= 0) {
return NS_OK;
}
if (widthInPixels <= 0)
return;
nscoord x0 = 0;
nscoord y0 = 0;
@ -1687,9 +1705,8 @@ nsHTMLFramesetBorderFrame::Paint(nsPresContext* aPresContext,
}
}
if (!mVisibility && !mVisibilityOverride) {
return NS_OK;
}
if (!mVisibility && !mVisibilityOverride)
return;
if (widthInPixels >= 5) {
aRenderingContext.SetColor(hltColor);
@ -1717,8 +1734,6 @@ nsHTMLFramesetBorderFrame::Paint(nsPresContext* aPresContext,
y1 = (mVertical) ? mRect.height : y0;
aRenderingContext.DrawLine(x0, y0, x1, y1);
}
return NS_OK;
}
@ -1747,17 +1762,6 @@ nsHTMLFramesetBorderFrame::HandleEvent(nsPresContext* aPresContext,
return NS_OK;
}
nsIFrame*
nsHTMLFramesetBorderFrame::GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer)
{
nsRect thisRect(nsPoint(0,0), GetSize());
if (aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND ||
!((mState & NS_FRAME_OUTSIDE_CHILDREN) || thisRect.Contains(aPoint)))
return nsnull;
return this;
}
NS_IMETHODIMP
nsHTMLFramesetBorderFrame::GetCursor(const nsPoint& aPoint,
nsIFrame::Cursor& aCursor)
@ -1808,37 +1812,23 @@ nsHTMLFramesetBlankFrame::Reflow(nsPresContext* aPresContext,
return NS_OK;
}
NS_METHOD
nsHTMLFramesetBlankFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
class nsDisplayFramesetBlank : public nsDisplayItem {
public:
nsDisplayFramesetBlank(nsIFrame* aFrame) : mFrame(aFrame) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("FramesetBlank")
private:
nsIFrame* mFrame;
};
void nsDisplayFramesetBlank::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
{
if (NS_FRAME_PAINT_LAYER_FOREGROUND != aWhichLayer) {
return NS_OK;
}
nscolor white = NS_RGB(255,255,255);
aRenderingContext.SetColor (white);
// XXX FillRect doesn't seem to work
//aRenderingContext.FillRect (mRect);
float p2t;
p2t = aPresContext->PixelsToTwips();
nscoord x0 = 0;
nscoord y0 = 0;
nscoord x1 = x0;
nscoord y1 = mRect.height;
nscoord pixel = NSIntPixelsToTwips(1, p2t);
aRenderingContext.SetColor(white);
for (int i = 0; i < mRect.width; i += pixel) {
aRenderingContext.DrawLine (x0, y0, x1, y1);
x0 += NSIntPixelsToTwips(1, p2t);
x1 = x0;
}
return NS_OK;
aCtx->SetColor (white);
aCtx->FillRect (nsRect(aBuilder->ToReferenceFrame(mFrame), mFrame->GetSize()));
}
#ifdef DEBUG
@ -1846,7 +1836,19 @@ NS_IMETHODIMP nsHTMLFramesetBlankFrame::List(FILE* out,
PRInt32 aIndent) const
{
for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out); // Indent
fprintf(out, "%p BLANK \n", this);
fprintf(out, "%p BLANK \n", (void*)this);
return nsLeafFrame::List(out, aIndent);
}
#endif
NS_IMETHODIMP
nsHTMLFramesetBlankFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
nsDisplayItem* item = new (aBuilder) nsDisplayFramesetBlank(this);
if (!item)
return NS_ERROR_OUT_OF_MEMORY;
aLists.Content()->AppendToTop(item);
return NS_OK;
}

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

@ -134,17 +134,12 @@ public:
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus);
virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD GetCursor(const nsPoint& aPoint,
nsIFrame::Cursor& aCursor);
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,

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

@ -80,6 +80,7 @@
#ifdef ACCESSIBILITY
#include "nsIAccessibilityService.h"
#endif
#include "nsDisplayList.h"
static const char kEventQueueServiceCID[] = NS_EVENTQUEUESERVICE_CONTRACTID;
@ -1355,6 +1356,63 @@ NS_IMETHODIMP_(nsrefcnt) nsGfxScrollFrameInner::Release(void)
NS_IMPL_QUERY_INTERFACE1(nsGfxScrollFrameInner, nsIScrollPositionListener)
nsresult
nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
nsresult rv = mOuter->DisplayBorderBackgroundOutline(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
if (aBuilder->GetIgnoreScrollFrame() == mOuter) {
// Don't clip the scrolled child, and don't paint scrollbars/scrollcorner.
// The scrolled frame shouldn't have its own background/border, so we
// can just pass aLists directly. We do need to replace aDirtyRect with
// the scrolled area though, since callers may have restricted aDirtyRect
// to our bounds.
nsRect newDirty = mScrolledFrame->GetOverflowRect() +
aBuilder->ToReferenceFrame(mScrolledFrame);
return mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, newDirty, aLists);
}
// Overflow clipping can never clip frames outside our subtree, so there
// is no need to worry about whether we are a moving frame that might clip
// non-moving frames.
nsRect frameClip = mScrollableView->View()->GetBounds();
nsRect dirtyRect;
// Not all our descendants will be clipped by overflow clipping, but all
// the ones that aren't clipped will be out of flow frames that have already
// had dirty rects saved for them by their parent frames calling
// MarkOutOfFlowChildrenForDisplayList, so it's safe to restrict our
// dirty rect here.
dirtyRect.IntersectRect(aDirtyRect, frameClip);
nsDisplayListCollection set;
rv = mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, set);
NS_ENSURE_SUCCESS(rv, rv);
nsRect clip = frameClip + aBuilder->ToReferenceFrame(mOuter);
// mScrolledFrame may have given us a background, e.g., the scrolled canvas
// frame below the viewport. If so, we want it to be clipped.
// If we are the viewport scrollframe, then clip all our descendants (to ensure
// that fixed-pos elements get clipped by us).
rv = mOuter->OverflowClip(aBuilder, set, aLists, clip, PR_TRUE, mIsRoot);
NS_ENSURE_SUCCESS(rv, rv);
// Now display the scrollbars and scrollcorner
nsIFrame* kid = mOuter->GetFirstChild(nsnull);
// Put each child's background directly onto the content list
nsDisplayListSet scrollbarSet(aLists, aLists.Content());
while (kid) {
if (kid != mScrolledFrame) {
rv = mOuter->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, scrollbarSet,
nsIFrame::DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT);
NS_ENSURE_SUCCESS(rv, rv);
}
kid = kid->GetNextSibling();
}
return NS_OK;
}
PRBool
nsGfxScrollFrameInner::NeedsClipWidget() const
{

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

@ -80,6 +80,10 @@ public:
void PostScrollPortEvent(PRBool aOverflow, nsScrollPortEvent::orientType aType);
void PostOverflowEvents();
nsresult BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
// nsIScrollPositionListener
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
@ -192,6 +196,12 @@ public:
nsIAtom* aListName,
nsIFrame* aChildList);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) {
return mInner.BuildDisplayList(aBuilder, aDirtyRect, aLists);
}
PRBool TryLayout(ScrollReflowState* aState,
const nsHTMLReflowMetrics& aKidMetrics,
PRBool aAssumeVScroll, PRBool aAssumeHScroll,
@ -336,6 +346,12 @@ public:
nsIAtom* aListName,
nsIFrame* aChildList);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) {
return mInner.BuildDisplayList(aBuilder, aDirtyRect, aLists);
}
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,

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

@ -43,6 +43,7 @@
#include "nsHTMLCanvasFrame.h"
#include "nsICanvasElement.h"
#include "nsDisplayList.h"
nsIFrame*
NS_NewHTMLCanvasFrame(nsIPresShell* aPresShell)
@ -163,53 +164,55 @@ nsHTMLCanvasFrame::GetInnerArea() const
return r;
}
NS_IMETHODIMP
nsHTMLCanvasFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
void
nsHTMLCanvasFrame::PaintCanvas(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect, nsPoint aPt)
{
PRBool isVisible;
if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) &&
isVisible && mRect.width && mRect.height)
{
// If painting is suppressed, we need to stop image painting.
PRBool paintingSuppressed = PR_FALSE;
aPresContext->PresShell()->IsPaintingSuppressed(&paintingSuppressed);
if (paintingSuppressed) {
return NS_OK;
}
nsRect inner = GetInnerArea() + aPt;
nsRect src(0, 0, mCanvasSize.width, mCanvasSize.height);
// make sure that the rendering context has updated the
// image frame
nsCOMPtr<nsICanvasElement> canvas(do_QueryInterface(GetContent()));
NS_ENSURE_TRUE(canvas, NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(canvas->UpdateImageFrame(), NS_ERROR_FAILURE);
// XXX this should just draw the dirty area
aRenderingContext.DrawImage(mImageContainer, src, inner);
}
// from nsImageFrame
// First paint background and borders, which should be in the
// FOREGROUND or BACKGROUND paint layer if the element is
// inline-level or block-level, respectively (bug 36710). (See
// CSS2 9.5, which is the rationale for paint layers.)
const nsStyleDisplay* display = GetStyleDisplay();
nsFramePaintLayer backgroundLayer = display->IsBlockLevel()
? NS_FRAME_PAINT_LAYER_BACKGROUND
: NS_FRAME_PAINT_LAYER_FOREGROUND;
static void PaintCanvas(nsIFrame* aFrame, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aPt)
{
NS_STATIC_CAST(nsHTMLCanvasFrame*, aFrame)->PaintCanvas(*aCtx, aDirtyRect, aPt);
}
if (aWhichLayer == backgroundLayer) {
PaintSelf(aPresContext, aRenderingContext, aDirtyRect);
}
NS_IMETHODIMP
nsHTMLCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
if (!IsVisibleForPainting(aBuilder))
return NS_OK;
if ((aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND) && mImageContainer) {
nsRect inner = GetInnerArea();
nsRect src(0, 0, mCanvasSize.width, mCanvasSize.height);
// REVIEW: We don't need any special logic here for deciding which layer
// to put the background in ... it goes in aLists.BorderBackground() and
// then if we have a block parent, it will put our background in the right
// place.
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
// REVIEW: Checking mRect.IsEmpty() makes no sense to me, so I removed it.
// It can't have been protecting us against bad situations with zero-size
// images since adding a border would make the rect non-empty.
aRenderingContext.DrawImage(mImageContainer, src, inner);
}
// make sure that the rendering context has updated the
// image frame
nsCOMPtr<nsICanvasElement> canvas(do_QueryInterface(GetContent()));
NS_ENSURE_TRUE(canvas, NS_ERROR_FAILURE);
NS_ENSURE_SUCCESS(canvas->UpdateImageFrame(), NS_ERROR_FAILURE);
if (mImageContainer) {
rv = aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayGeneric(this, ::PaintCanvas, "Canvas"));
NS_ENSURE_SUCCESS(rv, rv);
}
return nsFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, nsISelectionDisplay::DISPLAY_IMAGES);
return DisplaySelectionOverlay(aBuilder, aLists,
nsISelectionDisplay::DISPLAY_IMAGES);
}
NS_IMETHODIMP

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

@ -53,11 +53,13 @@ class nsHTMLCanvasFrame : public nsSplittableFrame
public:
nsHTMLCanvasFrame();
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
void PaintCanvas(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect, nsPoint aPt);
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,

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

@ -61,89 +61,155 @@
#include "nsIFontMetrics.h"
#include "nsReflowPath.h"
#include "nsCSSFrameConstructor.h"
#include "nsDisplayList.h"
#include "nsBlockFrame.h"
#include "nsLineBox.h"
#include "nsDisplayList.h"
NS_IMETHODIMP
nsHTMLContainerFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
{
if (NS_FRAME_IS_UNFLOWABLE & mState) {
return NS_OK;
}
// Paint inline element backgrounds in the foreground layer, but
// others in the background (bug 36710). (nsInlineFrame::Paint does
// this differently.)
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
PaintSelf(aPresContext, aRenderingContext, aDirtyRect);
}
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, aFlags);
return NS_OK;
}
class nsDisplayTextDecoration : public nsDisplayItem {
public:
nsDisplayTextDecoration(nsHTMLContainerFrame* aFrame, PRUint8 aDecoration,
nscolor aColor, nsLineBox* aLine)
: mFrame(aFrame), mLine(aLine), mColor(aColor), mDecoration(aDecoration) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
virtual const char* Name() { return "TextDecoration"; }
private:
nsHTMLContainerFrame* mFrame;
nsLineBox* mLine;
nscolor mColor;
PRUint8 mDecoration;
};
void
nsHTMLContainerFrame::PaintDecorationsAndChildren(
nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRBool aIsBlock,
PRUint32 aFlags)
nsDisplayTextDecoration::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect) {
// REVIEW: From nsHTMLContainerFrame::PaintTextDecorationsAndChildren
const nsStyleFont* font = mFrame->GetStyleFont();
NS_ASSERTION(font->mFont.decorations == NS_FONT_DECORATION_NONE,
"fonts on style structs shouldn't have decorations");
// XXX This is relatively slow and shouldn't need to be used here.
nsCOMPtr<nsIDeviceContext> deviceContext;
aCtx->GetDeviceContext(*getter_AddRefs(deviceContext));
nsCOMPtr<nsIFontMetrics> normalFont;
const nsStyleVisibility* visibility = mFrame->GetStyleVisibility();
nsCOMPtr<nsIFontMetrics> fm;
deviceContext->GetMetricsFor(font->mFont, visibility->mLangGroup,
*getter_AddRefs(fm));
nsPoint pt = aBuilder->ToReferenceFrame(mFrame);
// REVIEW: From nsHTMLContainerFrame::PaintTextDecorations
nscoord ascent, offset, size;
fm->GetMaxAscent(ascent);
if (mDecoration != NS_STYLE_TEXT_DECORATION_LINE_THROUGH) {
fm->GetUnderline(offset, size);
if (mDecoration == NS_STYLE_TEXT_DECORATION_UNDERLINE) {
mFrame->PaintTextDecorationLine(*aCtx, pt, mLine, mColor, offset, ascent, size);
} else if (mDecoration == NS_STYLE_TEXT_DECORATION_OVERLINE) {
mFrame->PaintTextDecorationLine(*aCtx, pt, mLine, mColor, ascent, ascent, size);
}
} else {
fm->GetStrikeout(offset, size);
mFrame->PaintTextDecorationLine(*aCtx, pt, mLine, mColor, offset, ascent, size);
}
}
nsresult
nsHTMLContainerFrame::DisplayTextDecorations(nsDisplayListBuilder* aBuilder,
nsDisplayList* aBelowTextDecorations,
nsDisplayList* aAboveTextDecorations,
nsLineBox* aLine)
{
if (eCompatibility_NavQuirks == GetPresContext()->CompatibilityMode())
return NS_OK;
if (!IsVisibleForPainting(aBuilder))
return NS_OK;
// Do standards mode painting of 'text-decoration's: under+overline
// behind children, line-through in front. For Quirks mode, see
// nsTextFrame::PaintTextDecorations. (See bug 1777.)
nscolor underColor, overColor, strikeColor;
PRUint8 decorations = NS_STYLE_TEXT_DECORATION_NONE;
nsCOMPtr<nsIFontMetrics> fm;
PRBool isVisible;
GetTextDecorations(GetPresContext(), aLine != nsnull, decorations, underColor,
overColor, strikeColor);
if (eCompatibility_NavQuirks != aPresContext->CompatibilityMode() &&
NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer &&
NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext,
PR_TRUE, &isVisible)) &&
isVisible) {
GetTextDecorations(aPresContext, aIsBlock, decorations, underColor,
overColor, strikeColor);
if (decorations & (NS_STYLE_TEXT_DECORATION_UNDERLINE |
NS_STYLE_TEXT_DECORATION_OVERLINE |
NS_STYLE_TEXT_DECORATION_LINE_THROUGH)) {
const nsStyleFont* font = GetStyleFont();
NS_ASSERTION(font->mFont.decorations == NS_FONT_DECORATION_NONE,
"fonts on style structs shouldn't have decorations");
// XXX This is relatively slow and shouldn't need to be used here.
nsCOMPtr<nsIDeviceContext> deviceContext;
aRenderingContext.GetDeviceContext(*getter_AddRefs(deviceContext));
nsCOMPtr<nsIFontMetrics> normalFont;
const nsStyleVisibility* visibility = GetStyleVisibility();
deviceContext->GetMetricsFor(font->mFont, visibility->mLangGroup, *getter_AddRefs(fm));
}
if (decorations & NS_STYLE_TEXT_DECORATION_UNDERLINE) {
PaintTextDecorations(aRenderingContext, fm,
NS_STYLE_TEXT_DECORATION_UNDERLINE, underColor);
}
if (decorations & NS_STYLE_TEXT_DECORATION_OVERLINE) {
PaintTextDecorations(aRenderingContext, fm,
NS_STYLE_TEXT_DECORATION_OVERLINE, overColor);
}
if (decorations & NS_STYLE_TEXT_DECORATION_UNDERLINE) {
nsresult rv = aBelowTextDecorations->AppendNewToTop(new (aBuilder)
nsDisplayTextDecoration(this, NS_STYLE_TEXT_DECORATION_UNDERLINE, underColor, aLine));
NS_ENSURE_SUCCESS(rv, rv);
}
if (decorations & NS_STYLE_TEXT_DECORATION_OVERLINE) {
nsresult rv = aBelowTextDecorations->AppendNewToTop(new (aBuilder)
nsDisplayTextDecoration(this, NS_STYLE_TEXT_DECORATION_OVERLINE, overColor, aLine));
NS_ENSURE_SUCCESS(rv, rv);
}
PaintChildren(aPresContext, aRenderingContext, aDirtyRect,
aWhichLayer, aFlags);
if (decorations & NS_STYLE_TEXT_DECORATION_LINE_THROUGH) {
PaintTextDecorations(aRenderingContext, fm,
NS_STYLE_TEXT_DECORATION_LINE_THROUGH, strikeColor);
nsresult rv = aAboveTextDecorations->AppendNewToTop(new (aBuilder)
nsDisplayTextDecoration(this, NS_STYLE_TEXT_DECORATION_LINE_THROUGH, strikeColor, aLine));
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
nsresult
nsHTMLContainerFrame::DisplayTextDecorationsAndChildren(
nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
nsDisplayList aboveChildrenDecorations;
nsresult rv = DisplayTextDecorations(aBuilder, aLists.Content(),
&aboveChildrenDecorations, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
rv = BuildDisplayListForNonBlockChildren(aBuilder, aDirtyRect, aLists,
DISPLAY_CHILD_INLINE);
NS_ENSURE_SUCCESS(rv, rv);
aLists.Content()->AppendToTop(&aboveChildrenDecorations);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) {
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
return DisplayTextDecorationsAndChildren(aBuilder, aDirtyRect, aLists);
}
static PRBool
HasTextFrameDescendantOrInFlow(nsPresContext* aPresContext, nsIFrame* aFrame);
/*virtual*/ void
nsHTMLContainerFrame::PaintTextDecorationLine(
nsIRenderingContext& aRenderingContext,
nsPoint aPt,
nsLineBox* aLine,
nscolor aColor,
nscoord aOffset,
nscoord aAscent,
nscoord aSize)
{
nsMargin bp;
NS_ASSERTION(!aLine, "Should not have passed a linebox to a non-block frame");
CalcBorderPadding(bp);
PRIntn skip = GetSkipSides();
NS_FOR_CSS_SIDES(side) {
if (skip & (1 << side)) {
bp.side(side) = 0;
}
}
aRenderingContext.SetColor(aColor);
nscoord innerWidth = mRect.width - bp.left - bp.right;
aRenderingContext.FillRect(bp.left + aPt.x,
bp.top + aAscent - aOffset + aPt.y, innerWidth, aSize);
}
void
nsHTMLContainerFrame::GetTextDecorations(nsPresContext* aPresContext,
PRBool aIsBlock,
@ -252,54 +318,6 @@ HasTextFrameDescendantOrInFlow(nsPresContext* aPresContext, nsIFrame* aFrame)
return PR_FALSE;
}
/*virtual*/ void
nsHTMLContainerFrame::PaintTextDecorationLines(
nsIRenderingContext& aRenderingContext,
nscolor aColor,
nscoord aOffset,
nscoord aAscent,
nscoord aSize)
{
nsMargin bp;
CalcBorderPadding(bp);
PRIntn skip = GetSkipSides();
NS_FOR_CSS_SIDES(side) {
if (skip & (1 << side)) {
bp.side(side) = 0;
}
}
aRenderingContext.SetColor(aColor);
nscoord innerWidth = mRect.width - bp.left - bp.right;
aRenderingContext.FillRect(bp.left,
bp.top + aAscent - aOffset, innerWidth, aSize);
}
void
nsHTMLContainerFrame::PaintTextDecorations(
nsIRenderingContext& aRenderingContext,
nsIFontMetrics* aFontMetrics,
PRUint8 aDecoration,
nscolor aColor)
{
nscoord ascent, offset, size;
aFontMetrics->GetMaxAscent(ascent);
if (aDecoration &
(NS_STYLE_TEXT_DECORATION_UNDERLINE
| NS_STYLE_TEXT_DECORATION_OVERLINE)) {
aFontMetrics->GetUnderline(offset, size);
if (NS_STYLE_TEXT_DECORATION_UNDERLINE & aDecoration) {
PaintTextDecorationLines(aRenderingContext, aColor, offset, ascent, size);
}
else if (NS_STYLE_TEXT_DECORATION_OVERLINE & aDecoration) {
PaintTextDecorationLines(aRenderingContext, aColor, ascent, ascent, size);
}
}
else if (NS_STYLE_TEXT_DECORATION_LINE_THROUGH & aDecoration) {
aFontMetrics->GetStrikeout(offset, size);
PaintTextDecorationLines(aRenderingContext, aColor, offset, ascent, size);
}
}
/**
* Create a next-in-flow for aFrame. Will return the newly created
* frame in aNextInFlowResult <b>if and only if</b> a new frame is
@ -561,13 +579,9 @@ nsHTMLContainerFrame::CreateViewForFrame(nsIFrame* aFrame,
}
}
// XXX If it's fixed positioned, then create a widget so it floats
// above the scrolling area
const nsStyleDisplay* display = aFrame->GetStyleContext()->GetStyleDisplay();
if (NS_STYLE_POSITION_FIXED == display->mPosition) {
aFrame->CreateWidgetForView(view);
}
// REVIEW: Don't create a widget for fixed-pos elements anymore.
// ComputeRepaintRegionForCopy will calculate the right area to repaint
// when we scroll.
// Reparent views on any child frames (or their descendants) to this
// view. We can just call ReparentFrameViewTo on this frame because
// we know this frame has no view, so it will crawl the children. Also,

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

@ -45,6 +45,7 @@ struct nsStyleDisplay;
struct nsStylePosition;
struct nsHTMLReflowMetrics;
struct nsHTMLReflowState;
class nsLineBox;
// Some macros for container classes to do sanity checking on
// width/height/x/y values computed during reflow.
@ -58,15 +59,12 @@ struct nsHTMLReflowState;
#define CRAZY_HEIGHT(_y) (((_y) < -CRAZY_H) || ((_y) > CRAZY_H))
#endif
class nsDisplayTextDecoration;
// Base class for html container frames that provides common
// functionality.
class nsHTMLContainerFrame : public nsContainerFrame {
public:
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
/**
* Helper method to create next-in-flows if necessary. If aFrame
@ -106,40 +104,30 @@ public:
nsIFrame* aOldParentFrame,
nsIFrame* aNewParentFrame);
/**
* Displays the standard border, background and outline for the frame
* and calls DisplayTextDecorationsAndChildren. This is suitable for
* inline frames or frames that behave like inlines.
*/
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
nsresult DisplayTextDecorations(nsDisplayListBuilder* aBuilder,
nsDisplayList* aBelowTextDecorations,
nsDisplayList* aAboveTextDecorations,
nsLineBox* aLine);
protected:
virtual PRIntn GetSkipSides() const = 0;
void PaintSelf(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect) {
nsContainerFrame::PaintSelf(aPresContext, aRenderingContext,
aDirtyRect, GetSkipSides());
}
/**
* To be called *instead* of |PaintChildren| by frames that paint text
* decorations (block and inline frames). It will paint the
* decorations before and after the call to PaintChildren.
* Displays the below-children decorations, then the children, then
* the above-children decorations, with the decorations going in the
* Content() list. This is suitable for inline elements and elements
* that behave like inline elements (e.g. MathML containers).
*/
void PaintDecorationsAndChildren(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRBool aIsBlock,
PRUint32 aFlags = 0);
/**
* Helper function to paint text decorations for this frame. This
* function attempts to be general; hopefully particular frames can
* get away with overriding PaintTextDecorationLines. The function
* should be called for one text-decoration at the time. This is so
* line-through can be painted in front of children, while the other
* decorations can be drawn behind.
*/
void PaintTextDecorations(nsIRenderingContext& aRenderingContext,
nsIFontMetrics* aFontMetrics,
PRUint8 aDecoration,
nscolor aColor);
nsresult DisplayTextDecorationsAndChildren(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
/**
* Fetch the text decorations for this frame.
@ -167,7 +155,8 @@ protected:
/**
* Function that does the actual drawing of the textdecoration.
* input:
* @param aRenderingContext.
* @param aRenderingContext
* @param aLine the line, or nsnull if this is an inline frame
* @param aColor the color of the text-decoration
* @param aAscent ascent of the font from which the
* text-decoration was derived.
@ -177,12 +166,15 @@ protected:
* the baseline.
* @param aSize the thickness of the line
*/
virtual void PaintTextDecorationLines(nsIRenderingContext& aRenderingContext,
nscolor aColor,
nscoord aOffset,
nscoord aAscent,
nscoord aSize);
virtual void PaintTextDecorationLine(nsIRenderingContext& aRenderingContext,
nsPoint aPt,
nsLineBox* aLine,
nscolor aColor,
nscoord aOffset,
nscoord aAscent,
nscoord aSize);
friend class nsDisplayTextDecoration;
};
#endif /* nsHTMLContainerFrame_h___ */

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

@ -58,6 +58,7 @@
#include "nsLayoutAtoms.h"
#include "nsIPresShell.h"
#include "nsIScrollPositionListener.h"
#include "nsDisplayList.h"
// for focus
#include "nsIDOMWindowInternal.h"
@ -111,15 +112,13 @@ public:
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus);
nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer);
virtual PRBool IsContainingBlock() const { return PR_TRUE; }
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
void PaintFocus(nsIRenderingContext& aRenderingContext, nsPoint aPt);
// nsIScrollPositionListener
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
@ -347,97 +346,105 @@ CanvasFrame::RemoveFrame(nsIAtom* aListName,
return rv;
}
NS_IMETHODIMP
CanvasFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
static void
PaintCanvasFocus(nsIFrame* aFrame, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aPt)
{
// We are wrapping the root frame of a document. We
// need to check the pres shell to find out if painting is locked
// down (because we're still in the early stages of document
// and frame construction. If painting is locked down, then we
// do not paint our children.
PRBool paintingSuppressed = PR_FALSE;
aPresContext->PresShell()->IsPaintingSuppressed(&paintingSuppressed);
if (paintingSuppressed) {
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
PaintSelf(aPresContext, aRenderingContext, aDirtyRect);
}
return NS_OK;
NS_STATIC_CAST(CanvasFrame*, aFrame)->PaintFocus(*aCtx, aPt);
}
NS_IMETHODIMP
CanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
// Force a background to be shown. We may have a background propagated to us,
// in which case GetStyleBackground wouldn't have the right background
// and the code in nsFrame::DisplayBorderBackgroundOutline might not give us
// a background.
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists, PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
nsIFrame* kid = GetFirstChild(nsnull);
if (kid) {
// Put our child into its own pseudo-stack.
rv = BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists,
DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT);
NS_ENSURE_SUCCESS(rv, rv);
}
nsresult rv = nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
#ifdef DEBUG_CANVAS_FOCUS
nsCOMPtr<nsIContent> focusContent;
aPresContext->EventStateManager()->
GetFocusedContent(getter_AddRefs(focusContent));
nsCOMPtr<nsIContent> focusContent;
aPresContext->EventStateManager()->
GetFocusedContent(getter_AddRefs(focusContent));
PRBool hasFocus = PR_FALSE;
nsCOMPtr<nsISupports> container;
aPresContext->GetContainer(getter_AddRefs(container));
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
if (docShell) {
docShell->GetHasFocus(&hasFocus);
printf("%p - CanvasFrame::Paint R:%d,%d,%d,%d DR: %d,%d,%d,%d\n", this,
mRect.x, mRect.y, mRect.width, mRect.height,
aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
}
printf("%p - Focus: %s c: %p DoPaint:%s\n", docShell.get(), hasFocus?"Y":"N",
focusContent.get(), mDoPaintFocus?"Y":"N");
PRBool hasFocus = PR_FALSE;
nsCOMPtr<nsISupports> container;
aPresContext->GetContainer(getter_AddRefs(container));
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
if (docShell) {
docShell->GetHasFocus(&hasFocus);
printf("%p - CanvasFrame::Paint R:%d,%d,%d,%d DR: %d,%d,%d,%d\n", this,
mRect.x, mRect.y, mRect.width, mRect.height,
aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
}
printf("%p - Focus: %s c: %p DoPaint:%s\n", docShell.get(), hasFocus?"Y":"N",
focusContent.get(), mDoPaintFocus?"Y":"N");
#endif
if (mDoPaintFocus) {
nsRect focusRect = GetRect();
/////////////////////
// draw focus
// XXX This is only temporary
// Only paint the focus if we're visible
if (GetStyleVisibility()->IsVisible()) {
nsIFrame * parentFrame = GetParent();
nsIView* parentView = parentFrame->GetView();
if (!mDoPaintFocus)
return NS_OK;
// Only paint the focus if we're visible
if (!GetStyleVisibility()->IsVisible())
return NS_OK;
return aLists.Outlines()->AppendNewToTop(new (aBuilder)
nsDisplayGeneric(this, ::PaintCanvasFocus, "CanvasFocus"));
}
nsIScrollableView* scrollableView = parentView->ToScrollableView();
if (scrollableView) {
nscoord width, height;
scrollableView->GetContainerSize(&width, &height);
nsRect vcr = parentView->GetBounds();
focusRect.width = vcr.width;
focusRect.height = vcr.height;
nscoord x,y;
scrollableView->GetScrollPosition(x, y);
focusRect.x += x;
focusRect.y += y;
}
void
CanvasFrame::PaintFocus(nsIRenderingContext& aRenderingContext, nsPoint aPt)
{
nsRect focusRect = GetRect();
/////////////////////
// draw focus
// XXX This is only temporary
nsIFrame * parentFrame = GetParent();
nsIView* parentView = parentFrame->GetView();
nsStyleOutline outlineStyle(aPresContext);
outlineStyle.SetOutlineStyle(NS_STYLE_BORDER_STYLE_DOTTED);
outlineStyle.SetOutlineInvert();
float p2t = aPresContext->PixelsToTwips();
// XXX the CSS border for links is specified as 2px, but it
// is only drawn as 1px. Match this here.
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
nsRect borderInside(focusRect.x + onePixel,
focusRect.y + onePixel,
focusRect.width - 2 * onePixel,
focusRect.height - 2 * onePixel);
nsCSSRendering::DrawDashedSides(0, aRenderingContext,
focusRect, nsnull,
nsnull, &outlineStyle,
PR_TRUE, focusRect,
borderInside, 0,
nsnull);
}
}
nsIScrollableView* scrollableView = parentView->ToScrollableView();
if (scrollableView) {
nscoord width, height;
scrollableView->GetContainerSize(&width, &height);
nsRect vcr = parentView->GetBounds();
focusRect.width = vcr.width;
focusRect.height = vcr.height;
nscoord x,y;
scrollableView->GetScrollPosition(x, y);
focusRect.x += x;
focusRect.y += y;
}
return rv;
nsStyleOutline outlineStyle(GetPresContext());
outlineStyle.SetOutlineStyle(NS_STYLE_BORDER_STYLE_DOTTED);
outlineStyle.SetOutlineInvert();
float p2t = GetPresContext()->PixelsToTwips();
// XXX the CSS border for links is specified as 2px, but it
// is only drawn as 1px. Match this here.
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
nsRect borderInside(focusRect.x + onePixel,
focusRect.y + onePixel,
focusRect.width - 2 * onePixel,
focusRect.height - 2 * onePixel);
nsCSSRendering::DrawDashedSides(0, aRenderingContext,
focusRect, nsnull,
nsnull, &outlineStyle,
PR_TRUE, focusRect,
borderInside, 0,
nsnull);
}
NS_IMETHODIMP
@ -608,15 +615,6 @@ CanvasFrame::HandleEvent(nsPresContext* aPresContext,
return NS_OK;
}
nsIFrame*
CanvasFrame::GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer)
{
// this should act like a block, so we need to override
return GetFrameForPointUsing(aPoint, nsnull, aWhichLayer,
aWhichLayer == NS_FRAME_PAINT_LAYER_BACKGROUND);
}
nsIAtom*
CanvasFrame::GetType() const
{

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

@ -84,6 +84,9 @@ class nsIBoxLayout;
#ifdef ACCESSIBILITY
class nsIAccessible;
#endif
class nsDisplayListBuilder;
class nsDisplayListSet;
class nsDisplayList;
struct nsPeekOffsetStruct;
struct nsPoint;
@ -133,6 +136,8 @@ typedef PRUint32 nsSplittableType;
typedef PRUint32 nsFrameState;
#define NS_FRAME_IN_REFLOW 0x00000001
// This is only set during painting
#define NS_FRAME_HAS_DESCENDANT_PLACEHOLDER 0x00000001
// This bit is set when a frame is created. After it has been reflowed
// once (during the DidReflow with a finished state) the bit is
@ -223,12 +228,6 @@ typedef PRUint32 nsFrameState;
//----------------------------------------------------------------------
enum nsFramePaintLayer {
eFramePaintLayer_Underlay = 1,
eFramePaintLayer_Content = 2,
eFramePaintLayer_Overlay = 4
};
enum nsSelectionAmount {
eSelectCharacter = 0,
eSelectWord = 1,
@ -257,17 +256,6 @@ enum nsSpread {
//----------------------------------------------------------------------
// For HTML reflow we rename with the different paint layers are
// actually used for.
#define NS_FRAME_PAINT_LAYER_BACKGROUND eFramePaintLayer_Underlay
#define NS_FRAME_PAINT_LAYER_FLOATS eFramePaintLayer_Content
#define NS_FRAME_PAINT_LAYER_FOREGROUND eFramePaintLayer_Overlay
#define NS_FRAME_PAINT_LAYER_DEBUG eFramePaintLayer_Overlay
#define NS_FRAME_PAINT_LAYER_ALL \
(nsFramePaintLayer(NS_FRAME_PAINT_LAYER_BACKGROUND | \
NS_FRAME_PAINT_LAYER_FLOATS | \
NS_FRAME_PAINT_LAYER_FOREGROUND))
/**
* Reflow status returned by the reflow methods.
*
@ -676,21 +664,116 @@ public:
}
/**
* Paint is responsible for painting the frame. The aWhichLayer
* argument indicates which layer of painting should be done during
* the call.
* Builds the display lists for the content represented by this frame
* and its descendants. The background+borders of this element must
* be added first, before any other content.
*
* This should only be called by methods in nsFrame. Instead of calling this
* directly, call either BuildDisplayListForStackingContext or
* BuildDisplayListForChild.
*
* See nsDisplayList.h for more information about display lists.
*
* @param aDirtyRect content outside this rectangle can be ignored; the
* rectangle is in frame coordinates
*/
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0) = 0;
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) { return NS_OK; }
PRBool IsThemed() {
return IsThemed(GetStyleDisplay());
}
PRBool IsThemed(const nsStyleDisplay* aDisp) {
if (!aDisp->mAppearance)
return PR_FALSE;
nsPresContext* pc = GetPresContext();
nsITheme *theme = pc->GetTheme();
return theme && theme->ThemeSupportsWidget(pc, this, aDisp->mAppearance);
}
/**
* Builds a display list for the content represented by this frame,
* treating this frame as the root of a stacking context.
* @param aDirtyRect content outside this rectangle can be ignored; the
* rectangle is in frame coordinates
*/
nsresult BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
nsDisplayList* aList);
/**
* Does the frame paint its background? If not, then all or part of it will be
* painted by ancestors.
* Clips the display items of aFromSet, putting the results in aToSet.
* Only items corresponding to frames which are descendants of this frame
* are clipped. In other words, descendant elements whose CSS boxes do not
* have this frame as a container are not clipped. Also,
* border/background/outline items for this frame are not clipped,
* unless aClipBorderBackground is set to PR_TRUE. (We need this because
* a scrollframe must overflow-clip its scrolled child's background/borders.)
*/
virtual PRBool CanPaintBackground() { return PR_TRUE; }
nsresult OverflowClip(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aFromSet,
const nsDisplayListSet& aToSet,
const nsRect& aClipRect,
PRBool aClipBorderBackground = PR_FALSE,
PRBool aClipAll = PR_FALSE);
/**
* Clips the display items of aFromSet, putting the results in aToSet.
* All items are clipped.
*/
nsresult Clip(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aFromSet,
const nsDisplayListSet& aToSet,
const nsRect& aClipRect);
/**
* Out-of-flow elements are painted as if they were part of their
* containing element, for clipping, compositing and z-ordering (modulo
* special z-order rules for floats and positioned elements). Therefore
* we paint out-of-flow frames through their placeholders. During
* display list construction, a container for out-of-flow frames will invoke
* this method on itself to mark ancestors of relevant placeholders --- up to
* and including itself --- with NS_FRAME_HAS_DESCENDANT_PLACEHOLDER, to
* ensure that those frames are descended into during display list
* construction (they might otherwise be excluded if they do not
* intersect the dirty rect).
*
* After display list construction of descendants has finished, we call
* UnmarkOutOfFlowChildrenForDisplayList on each out-of-flow child. For
* performance reasons we also unmark each frame after we have finished
* building a display list for it; this allows
* UnmarkOutOfFlowChildrenForDisplayList to terminate early when it reaches
* a frame in its parent chain without the NS_FRAME_HAS_DESCENDANT_PLACEHOLDER
* bit. If CSS 'visiblity' is not being used and there are no failures during
* painting, each out-of-flow's placeholder will have been unmarked and so
* UnmarkOutOfFlowChildrenForDisplayList won't need to do any real work.
*
* @param aFirstChild the first frame to mark; we mark the entire sibling
* list
*/
void MarkOutOfFlowChildrenForDisplayList(nsIFrame* aFirstChild,
const nsRect& aDirtyRect);
void UnmarkOutOfFlowChildrenForDisplayList(nsIFrame* aFirstChild);
enum {
DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT = 0x01,
DISPLAY_CHILD_INLINE = 0x02
};
/**
* Adjusts aDirtyRect for the child's offset, checks that the dirty rect
* actually intersects the child (or its descendants), calls BuildDisplayList
* on the child if necessary, and puts things in the right lists if the child
* is positioned.
*
* @param aFlags combination of DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT
* and DISPLAY_CHILD_INLINE
*/
nsresult BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
nsIFrame* aChild,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists,
PRUint32 aFlags = 0);
/**
* Does this frame type always need a view?
@ -762,16 +845,6 @@ public:
NS_IMETHOD GetCursor(const nsPoint& aPoint,
Cursor& aCursor) = 0;
/**
* Get the frame that should receive events for a given point in the
* coordinate space of this frame, if the frame is painted in
* the given paint layer. A frame should return itself if it should
* receive the events. A successful return value indicates that a
* point was found.
*/
virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer) = 0;
/**
* Get a point (in the frame's coordinate space) given an offset into
* the content. This point should be on the baseline of text with
@ -1139,6 +1212,12 @@ public:
FinishAndStoreOverflow(&aMetrics->mOverflowArea, nsSize(aMetrics->width, aMetrics->height));
}
/**
* Determine whether borders should not be painted on certain sides of the
* frame.
*/
virtual PRIntn GetSkipSides() const { return 0; }
/** Selection related calls
*/
/**
@ -1248,18 +1327,43 @@ public:
PRBool* aIsChild) = 0;
/**
* Determines whether a frame is visible for painting
* this takes into account whether it is painting a selection or printing.
* @param aPresContext PresContext
* @param aRenderingContext PresContext
* @param aCheckVis indicates whether it should check for CSS visibility,
* PR_FALSE skips the check, PR_TRUE does the check
* @param aIsVisible return value
* Determines whether a frame is visible for painting;
* taking into account whether it is painting a selection or printing.
*/
NS_IMETHOD IsVisibleForPainting(nsPresContext * aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aCheckVis,
PRBool* aIsVisible) = 0;
PRBool IsVisibleForPainting(nsDisplayListBuilder* aBuilder);
/**
* Determines whether a frame is visible for painting or collapsed;
* taking into account whether it is painting a selection or printing,
*/
PRBool IsVisibleOrCollapsedForPainting(nsDisplayListBuilder* aBuilder);
/**
* As above, but slower because we have to recompute some stuff that
* aBuilder already has.
*/
PRBool IsVisibleForPainting();
/**
* Check whether this frame is visible in the current selection. Returns
* PR_TRUE if there is no current selection.
*/
PRBool IsVisibleInSelection(nsDisplayListBuilder* aBuilder);
/**
* Overridable function to determine whether this frame should be considered
* "in" the given non-null aSelection for visibility purposes.
*/
virtual PRBool IsVisibleInSelection(nsISelection* aSelection);
/**
* Determines whether this frame is a pseudo stacking context, looking
* only as style --- i.e., assuming that it's in-flow and not a replaced
* element.
*/
PRBool IsPseudoStackingContextFromStyle() {
const nsStyleDisplay* disp = GetStyleDisplay();
return disp->mOpacity != 1.0f || disp->IsPositioned();
}
virtual PRBool HonorPrintBackgroundSettings() { return PR_TRUE; }
/**
* Determine whether the frame is logically empty, which is roughly
@ -1453,7 +1557,6 @@ NS_PTR_TO_INT32(frame->GetProperty(nsLayoutAtoms::embeddingLevel))
#ifdef DEBUG_LAYOUT
NS_IMETHOD SetDebug(nsBoxLayoutState& aState, PRBool aDebug)=0;
NS_IMETHOD GetDebug(PRBool& aDebug)=0;
NS_IMETHOD GetDebugBoxAt(const nsPoint& aPoint, nsIBox** aBox)=0;
NS_IMETHOD DumpBox(FILE* out)=0;
#endif

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

@ -126,6 +126,8 @@ public:
// Show frame border of event target
static void ShowEventTargetFrameBorder(PRBool aEnable);
static PRBool GetShowEventTargetFrameBorder();
static void PrintDisplayList(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList);
private:
NS_IMETHOD_(nsrefcnt) AddRef(void) = 0;

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

@ -83,6 +83,7 @@
#include "nsIDOMNode.h"
#include "nsGUIEvent.h"
#include "nsLayoutUtils.h"
#include "nsDisplayList.h"
#include "imgIContainer.h"
#include "imgILoader.h"
@ -1129,16 +1130,16 @@ struct nsRecessedBorder : public nsStyleBorder {
};
void
nsImageFrame::DisplayAltFeedback(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
imgIRequest* aRequest)
nsImageFrame::DisplayAltFeedback(nsIRenderingContext& aRenderingContext,
imgIRequest* aRequest,
nsPoint aPt)
{
// Calculate the inner area
nsRect inner = GetInnerArea();
nsRect inner = GetInnerArea() + aPt;
// Display a recessed one pixel border
nscoord borderEdgeWidth;
float p2t = aPresContext->ScaledPixelsToTwips();
float p2t = GetPresContext()->ScaledPixelsToTwips();
borderEdgeWidth = NSIntPixelsToTwips(ALT_BORDER_WIDTH, p2t);
// if inner area is empty, then make it big enough for at least the icon
@ -1155,7 +1156,7 @@ nsImageFrame::DisplayAltFeedback(nsPresContext* aPresContext,
// Paint the border
nsRecessedBorder recessedBorder(borderEdgeWidth);
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this, inner,
nsCSSRendering::PaintBorder(GetPresContext(), aRenderingContext, this, inner,
inner, recessedBorder, mStyleContext, 0);
// Adjust the inner rect to account for the one pixel recessed border,
@ -1197,10 +1198,10 @@ nsImageFrame::DisplayAltFeedback(nsPresContext* aPresContext,
// if we could not draw the image, then just draw some graffiti
if (!iconUsed) {
nscolor oldColor;
aRenderingContext.DrawRect(0,0,size,size);
aRenderingContext.DrawRect(aPt.x, aPt.y,size,size);
aRenderingContext.GetColor(oldColor);
aRenderingContext.SetColor(NS_RGB(0xFF,0,0));
aRenderingContext.FillEllipse(NS_STATIC_CAST(int,size/2),NS_STATIC_CAST(int,size/2),
aRenderingContext.FillEllipse(NS_STATIC_CAST(int,size/2) + aPt.x,NS_STATIC_CAST(int,size/2) + aPt.y,
NS_STATIC_CAST(int,(size/2)-(2*p2t)),NS_STATIC_CAST(int,(size/2)-(2*p2t)));
aRenderingContext.SetColor(oldColor);
}
@ -1219,162 +1220,201 @@ nsImageFrame::DisplayAltFeedback(nsPresContext* aPresContext,
nsXPIDLString altText;
nsCSSFrameConstructor::GetAlternateTextFor(content, content->Tag(),
altText);
DisplayAltText(aPresContext, aRenderingContext, altText, inner);
DisplayAltText(GetPresContext(), aRenderingContext, altText, inner);
}
}
aRenderingContext.PopState();
}
NS_METHOD
nsImageFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
static void PaintAltFeedback(nsIFrame* aFrame, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aPt)
{
PRBool isVisible;
if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) &&
isVisible && mRect.width && mRect.height) {
// If painting is suppressed, we need to stop image painting. We
// have to cover <img> here because of input image controls.
PRBool paintingSuppressed = PR_FALSE;
aPresContext->PresShell()->IsPaintingSuppressed(&paintingSuppressed);
if (paintingSuppressed) {
return NS_OK;
}
nsImageFrame* f = NS_STATIC_CAST(nsImageFrame*, aFrame);
f->DisplayAltFeedback(*aCtx,
IMAGE_OK(f->GetContent()->IntrinsicState(), PR_TRUE)
? nsImageFrame::gIconLoad->mLoadingImage
: nsImageFrame::gIconLoad->mBrokenImage,
aPt);
}
// First paint background and borders, which should be in the
// FOREGROUND or BACKGROUND paint layer if the element is
// inline-level or block-level, respectively (bug 36710). (See
// CSS2 9.5, which is the rationale for paint layers.)
const nsStyleDisplay* display = GetStyleDisplay();
nsFramePaintLayer backgroundLayer = display->IsBlockLevel()
? NS_FRAME_PAINT_LAYER_BACKGROUND
: NS_FRAME_PAINT_LAYER_FOREGROUND;
if (aWhichLayer == backgroundLayer) {
PaintSelf(aPresContext, aRenderingContext, aDirtyRect);
}
#ifdef NS_DEBUG
static void PaintDebugImageMap(nsIFrame* aFrame, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aPt) {
nsImageFrame* f = NS_STATIC_CAST(nsImageFrame*, aFrame);
nsRect inner = f->GetInnerArea() + aPt;
nsPresContext* pc = f->GetPresContext();
if (mComputedSize.width != 0 && mComputedSize.height != 0) {
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
NS_ASSERTION(imageLoader, "Not an image loading content?");
aCtx->SetColor(NS_RGB(0, 0, 0));
aCtx->PushState();
aCtx->Translate(inner.x, inner.y);
f->GetImageMap(pc)->Draw(pc, *aCtx);
aCtx->PopState();
}
#endif
nsCOMPtr<imgIRequest> currentRequest;
if (imageLoader) {
imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
getter_AddRefs(currentRequest));
}
/**
* Note that nsDisplayImage does not receive events. However, an image element
* is replaced content so its background will be z-adjacent to the
* image itself, and hence receive events just as if the image itself
* received events.
*/
class nsDisplayImage : public nsDisplayItem {
public:
nsDisplayImage(nsImageFrame* aFrame, imgIContainer* aImage)
: mFrame(aFrame), mImage(aImage) {}
virtual nsImageFrame* GetUnderlyingFrame() { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("Image")
private:
nsImageFrame* mFrame;
nsCOMPtr<imgIContainer> mImage;
};
PRInt32 contentState = mContent->IntrinsicState();
PRBool imageOK = IMAGE_OK(contentState, PR_TRUE);
void
nsDisplayImage::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect) {
mFrame->PaintImage(*aCtx, aBuilder->ToReferenceFrame(mFrame), aDirtyRect,
mImage);
}
nsCOMPtr<imgIContainer> imgCon;
if (currentRequest) {
currentRequest->GetImage(getter_AddRefs(imgCon));
}
void
nsImageFrame::PaintImage(nsIRenderingContext& aRenderingContext, nsPoint aPt,
const nsRect& aDirtyRect, imgIContainer* aImage)
{
// Render the image into our content area (the area inside
// the borders and padding)
nsRect inner = GetInnerArea() + aPt;
nsRect paintArea(inner);
if (!imageOK || !imgCon) {
// No image yet, or image load failed. Draw the alt-text and an icon
// indicating the status
nscoord offsetY = 0;
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
DisplayAltFeedback(aPresContext, aRenderingContext,
imageOK ? gIconLoad->mLoadingImage
: gIconLoad->mBrokenImage);
}
}
else {
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer && imgCon) {
// Render the image into our content area (the area inside
// the borders and padding)
nsRect inner = GetInnerArea();
nsRect paintArea(inner);
// if the image is split account for y-offset
if (mPrevInFlow) {
offsetY = GetContinuationOffset();
}
nscoord offsetY = 0;
if (mIntrinsicSize == mComputedSize) {
// Find the actual rect to be painted to in the rendering context
paintArea.IntersectRect(paintArea, aDirtyRect);
// if the image is split account for y-offset
if (mPrevInFlow) {
offsetY = GetContinuationOffset();
}
// Rect in the image to paint
nsRect r(paintArea.x - inner.x,
paintArea.y - inner.y + offsetY,
paintArea.width,
paintArea.height);
aRenderingContext.DrawImage(aImage, r, paintArea);
} else {
// The computed size is the total size of all the continuations,
// including ourselves. Note that we're basically inverting
// mTransform here (would it too much to ask for
// nsTransform2D::Invert?), since we need to convert from
// rendering context coords to image coords...
nsTransform2D trans;
trans.SetToScale((float(mIntrinsicSize.width) / float(mComputedSize.width)),
(float(mIntrinsicSize.height) / float(mComputedSize.height)));
// XXXbz it looks like we should take
// IntersectRect(paintArea, aDirtyRect) here too, but things
// get very weird if I do that ....
// paintArea.IntersectRect(paintArea, aDirtyRect);
// dirty rect in image our coord size...
nsRect r(paintArea.x - inner.x,
paintArea.y - inner.y + offsetY,
paintArea.width,
paintArea.height);
if (mIntrinsicSize == mComputedSize) {
// Find the actual rect to be painted to in the rendering context
paintArea.IntersectRect(paintArea, aDirtyRect);
// Rect in the image to paint
nsRect r(paintArea.x - inner.x,
paintArea.y - inner.y + offsetY,
paintArea.width,
paintArea.height);
aRenderingContext.DrawImage(imgCon, r, paintArea);
} else {
// The computed size is the total size of all the continuations,
// including ourselves. Note that we're basically inverting
// mTransform here (would it too much to ask for
// nsTransform2D::Invert?), since we need to convert from
// rendering context coords to image coords...
nsTransform2D trans;
trans.SetToScale((float(mIntrinsicSize.width) / float(mComputedSize.width)),
(float(mIntrinsicSize.height) / float(mComputedSize.height)));
// XXXbz it looks like we should take
// IntersectRect(paintArea, aDirtyRect) here too, but things
// get very weird if I do that ....
// paintArea.IntersectRect(paintArea, aDirtyRect);
// dirty rect in image our coord size...
nsRect r(paintArea.x - inner.x,
paintArea.y - inner.y + offsetY,
paintArea.width,
paintArea.height);
// Transform that to image coords
trans.TransformCoord(&r.x, &r.y, &r.width, &r.height);
// Transform that to image coords
trans.TransformCoord(&r.x, &r.y, &r.width, &r.height);
#ifdef DEBUG_decode
printf("IF draw src (%d,%d,%d,%d) -> dst (%d,%d,%d,%d)\n",
r.x, r.y, r.width, r.height, paintArea.x, paintArea.y,
paintArea.width, paintArea.height);
printf("IF draw src (%d,%d,%d,%d) -> dst (%d,%d,%d,%d)\n",
r.x, r.y, r.width, r.height, paintArea.x, paintArea.y,
paintArea.width, paintArea.height);
#endif
aRenderingContext.DrawImage(imgCon, r, paintArea);
}
}
aRenderingContext.DrawImage(aImage, r, paintArea);
}
nsImageMap* map = GetImageMap(aPresContext);
if (nsnull != map) {
nsRect inner = GetInnerArea();
aRenderingContext.PushState();
aRenderingContext.SetColor(NS_RGB(0, 0, 0));
aRenderingContext.SetLineStyle(nsLineStyle_kDotted);
aRenderingContext.Translate(inner.x, inner.y);
map->Draw(aPresContext, aRenderingContext);
aRenderingContext.PopState();
}
nsPresContext* presContext = GetPresContext();
nsImageMap* map = GetImageMap(presContext);
if (nsnull != map) {
nsRect inner = GetInnerArea() + aPt;
aRenderingContext.PushState();
aRenderingContext.SetColor(NS_RGB(0, 0, 0));
aRenderingContext.SetLineStyle(nsLineStyle_kDotted);
aRenderingContext.Translate(inner.x, inner.y);
map->Draw(presContext, aRenderingContext);
aRenderingContext.PopState();
}
}
NS_IMETHODIMP
nsImageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
if (!IsVisibleForPainting(aBuilder))
return NS_OK;
// REVIEW: We don't need any special logic here for deciding which layer
// to put the background in ... it goes in aLists.BorderBackground() and
// then if we have a block parent, it will put our background in the right
// place.
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
// REVIEW: Checking mRect.IsEmpty() makes no sense to me, so I removed it.
// It can't have been protecting us against bad situations with zero-size
// images since adding a border would make the rect non-empty.
if (mComputedSize.width != 0 && mComputedSize.height != 0) {
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
NS_ASSERTION(imageLoader, "Not an image loading content?");
nsCOMPtr<imgIRequest> currentRequest;
if (imageLoader) {
imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
getter_AddRefs(currentRequest));
}
PRInt32 contentState = mContent->IntrinsicState();
PRBool imageOK = IMAGE_OK(contentState, PR_TRUE);
nsCOMPtr<imgIContainer> imgCon;
if (currentRequest) {
currentRequest->GetImage(getter_AddRefs(imgCon));
}
if (!imageOK || !imgCon) {
// No image yet, or image load failed. Draw the alt-text and an icon
// indicating the status
rv = aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayGeneric(this, PaintAltFeedback, "AltFeedback"));
NS_ENSURE_SUCCESS(rv, rv);
}
else {
rv = aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayImage(this, imgCon));
NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG
if ((NS_FRAME_PAINT_LAYER_DEBUG == aWhichLayer) &&
GetShowFrameBorders()) {
nsImageMap* map = GetImageMap(aPresContext);
if (nsnull != map) {
nsRect inner = GetInnerArea();
aRenderingContext.SetColor(NS_RGB(0, 0, 0));
aRenderingContext.PushState();
aRenderingContext.Translate(inner.x, inner.y);
map->Draw(aPresContext, aRenderingContext);
aRenderingContext.PopState();
}
}
#endif
if (GetShowFrameBorders() && GetImageMap(GetPresContext())) {
rv = aLists.Outlines()->AppendNewToTop(new (aBuilder)
nsDisplayGeneric(this, PaintDebugImageMap, "DebugImageMap"));
NS_ENSURE_SUCCESS(rv, rv);
}
#endif
}
}
PRInt16 displaySelection = 0;
nsresult result;
result = aPresContext->PresShell()->GetSelectionFlags(&displaySelection);
// XXX what on EARTH is this code for?
PRInt16 displaySelection = 0;
nsresult result;
nsPresContext* presContext = GetPresContext();
result = presContext->PresShell()->GetSelectionFlags(&displaySelection);
if (NS_FAILED(result))
return result;
if (!(displaySelection & nsISelectionDisplay::DISPLAY_IMAGES))
@ -1386,7 +1426,7 @@ nsImageFrame::Paint(nsPresContext* aPresContext,
if (displaySelection == nsISelectionDisplay::DISPLAY_ALL)
{
nsCOMPtr<nsISelectionController> selCon;
result = GetSelectionController(aPresContext, getter_AddRefs(selCon));
result = GetSelectionController(presContext, getter_AddRefs(selCon));
if (NS_SUCCEEDED(result) && selCon)
{
nsCOMPtr<nsISelection> selection;
@ -1426,7 +1466,8 @@ nsImageFrame::Paint(nsPresContext* aPresContext,
}
#endif
return nsFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, nsISelectionDisplay::DISPLAY_IMAGES);
return DisplaySelectionOverlay(aBuilder, aLists,
nsISelectionDisplay::DISPLAY_IMAGES);
}
NS_IMETHODIMP
@ -1730,14 +1771,14 @@ nsImageFrame::List(FILE* out, PRInt32 aIndent) const
fprintf(out, " [parent=%p]", mParent);
#endif
if (HasView()) {
fprintf(out, " [view=%p]", GetView());
fprintf(out, " [view=%p]", (void*)GetView());
}
fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width,
mRect.height);
if (0 != mState) {
fprintf(out, " [state=%08x]", mState);
}
fprintf(out, " [content=%p]", mContent);
fprintf(out, " [content=%p]", (void*)mContent);
// output the img src url
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);

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

@ -57,6 +57,7 @@ class nsILoadGroup;
struct nsHTMLReflowState;
struct nsHTMLReflowMetrics;
struct nsSize;
class nsDisplayImage;
class nsImageFrame;
@ -94,11 +95,9 @@ public:
nsIFrame* aParent,
nsStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
@ -149,6 +148,14 @@ public:
static PRBool ShouldCreateImageFrameFor(nsIContent* aContent,
nsStyleContext* aStyleContext);
void DisplayAltFeedback(nsIRenderingContext& aRenderingContext,
imgIRequest* aRequest,
nsPoint aPt);
nsRect GetInnerArea() const;
nsImageMap* GetImageMap(nsPresContext* aPresContext);
protected:
// nsISupports
NS_IMETHOD_(nsrefcnt) AddRef(void);
@ -160,8 +167,6 @@ protected:
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize);
nsImageMap* GetImageMap(nsPresContext* aPresContext);
void TriggerLink(nsPresContext* aPresContext,
nsIURI* aURI,
const nsString& aTargetSpec,
@ -185,12 +190,9 @@ protected:
const nsString& aAltText,
const nsRect& aRect);
void DisplayAltFeedback(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
imgIRequest* aRequest);
nsRect GetInnerArea() const;
void PaintImage(nsIRenderingContext& aRenderingContext, nsPoint aPt,
const nsRect& aDirtyRect, imgIContainer* aImage);
protected:
friend class nsImageListener;
nsresult OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
@ -301,7 +303,11 @@ private:
PRPackedBool mPrefForceInlineAltText;
PRPackedBool mPrefShowPlaceholders;
};
public:
static IconLoad* gIconLoad; // singleton pattern: one LoadIcons instance is used
friend class nsDisplayImage;
};
#endif /* nsImageFrame_h___ */

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

@ -264,34 +264,21 @@ nsInlineFrame::RemoveFrame(nsIAtom* aListName,
}
NS_IMETHODIMP
nsInlineFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
nsInlineFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
if (NS_FRAME_IS_UNFLOWABLE & mState) {
return NS_OK;
}
// Paint inline element backgrounds in the foreground layer (bug 36710).
if (aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND) {
PaintSelf(aPresContext, aRenderingContext, aDirtyRect);
}
nsresult rv = nsHTMLContainerFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
NS_ENSURE_SUCCESS(rv, rv);
// The sole purpose of this is to trigger display of the selection
// window for Named Anchors, which don't have any children and
// normally don't have any size, but in Editor we use CSS to display
// an image to represent this "hidden" element.
if (!mFrames.FirstChild()) {
nsFrame::Paint(aPresContext, aRenderingContext, aDirtyRect,
aWhichLayer, aFlags);
rv = DisplaySelectionOverlay(aBuilder, aLists);
}
PaintDecorationsAndChildren(aPresContext, aRenderingContext,
aDirtyRect, aWhichLayer, PR_FALSE,
aFlags);
return NS_OK;
return rv;
}
//////////////////////////////////////////////////////////////////////
@ -1091,6 +1078,17 @@ nsPositionedInlineFrame::RemoveFrame(nsIAtom* aListName,
return rv;
}
NS_IMETHODIMP
nsPositionedInlineFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
MarkOutOfFlowChildrenForDisplayList(mAbsoluteContainer.GetFirstChild(), aDirtyRect);
nsresult rv = nsHTMLContainerFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
UnmarkOutOfFlowChildrenForDisplayList(mAbsoluteContainer.GetFirstChild());
return rv;
}
nsIAtom*
nsPositionedInlineFrame::GetAdditionalChildListName(PRInt32 aIndex) const
{

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

@ -81,11 +81,9 @@ public:
nsIFrame* aFrameList);
NS_IMETHOD RemoveFrame(nsIAtom* aListName,
nsIFrame* aOldFrame);
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild);
#ifdef ACCESSIBILITY
@ -212,6 +210,10 @@ public:
NS_IMETHOD RemoveFrame(nsIAtom* aListName,
nsIFrame* aOldFrame);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
virtual nsIFrame* GetFirstChild(nsIAtom* aListName) const;

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

@ -46,20 +46,6 @@ nsLeafFrame::~nsLeafFrame()
{
}
NS_IMETHODIMP
nsLeafFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
{
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
PaintSelf(aPresContext, aRenderingContext, aDirtyRect);
}
DO_GLOBAL_REFLOW_COUNT_DSP("nsLeafFrame", &aRenderingContext);
return NS_OK;
}
NS_IMETHODIMP
nsLeafFrame::Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aMetrics,

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

@ -49,11 +49,11 @@ class nsLeafFrame : public nsFrame {
public:
// nsIFrame replacements
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) {
return DisplayBorderBackgroundOutline(aBuilder, aLists);
}
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,

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

@ -118,6 +118,7 @@
#include "nsPIDOMWindow.h"
#include "nsContentUtils.h"
#include "nsIStringBundle.h"
#include "nsDisplayList.h"
#include "nsAttrName.h"
// headers for plugin scriptability
@ -933,258 +934,286 @@ nsObjectFrame::DidReflow(nsPresContext* aPresContext,
return rv;
}
NS_IMETHODIMP
nsObjectFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
static void PaintPrintPlugin(nsIFrame* aFrame, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aPt)
{
if (!GetStyleVisibility()->IsVisibleOrCollapsed())
nsIRenderingContext::AutoPushTranslation translate(aCtx, aPt.x, aPt.y);
NS_STATIC_CAST(nsObjectFrame*, aFrame)->PrintPlugin(*aCtx, aDirtyRect);
}
static void PaintPlugin(nsIFrame* aFrame, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aPt)
{
nsIRenderingContext::AutoPushTranslation translate(aCtx, aPt.x, aPt.y);
NS_STATIC_CAST(nsObjectFrame*, aFrame)->PaintPlugin(*aCtx, aDirtyRect);
}
NS_IMETHODIMP
nsObjectFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
// XXX why are we painting collapsed object frames?
if (!IsVisibleOrCollapsedForPainting(aBuilder))
return NS_OK;
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
nsPresContext::nsPresContextType type = GetPresContext()->Type();
// If we are painting in Print Preview do nothing....
if (aPresContext->Type() == nsPresContext::eContext_PrintPreview) {
if (type == nsPresContext::eContext_PrintPreview)
return NS_OK;
}
// determine if we are printing
if (aPresContext->Type() == nsPresContext::eContext_Print) {
// UNIX Plugins can't PP at this time, so draw an empty box
// we only want to print on the content layer pass
if (eFramePaintLayer_Content != aWhichLayer)
return NS_OK;
if (type == nsPresContext::eContext_Print)
return aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayGeneric(this, PaintPrintPlugin, "PrintPlugin"));
return aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayGeneric(this, ::PaintPlugin, "Plugin"));
}
// if we are printing, we need to get the correct nsIPluginInstance
// for THIS content node in order to call ->Print() on the right plugin
void
nsObjectFrame::PrintPlugin(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect)
{
// if we are printing, we need to get the correct nsIPluginInstance
// for THIS content node in order to call ->Print() on the right plugin
// first, we need to get the document
nsIDocument* doc = mContent->GetCurrentDoc();
NS_ENSURE_TRUE(doc, NS_ERROR_NULL_POINTER);
// first, we need to get the document
nsIDocument* doc = mContent->GetCurrentDoc();
if (!doc)
return;
// now we need to get the shell for the screen
// XXX assuming that the shell at zero will always be the screen one
nsIPresShell *shell = doc->GetShellAt(0);
NS_ENSURE_TRUE(shell, NS_ERROR_NULL_POINTER);
// now we need to get the shell for the screen
// XXX assuming that the shell at zero will always be the screen one
nsIPresShell *shell = doc->GetShellAt(0);
if (!shell)
return;
// then the shell can give us the screen frame for this content node
nsIFrame* frame = shell->GetPrimaryFrameFor(mContent);
NS_ENSURE_TRUE(frame, NS_ERROR_NULL_POINTER);
// then the shell can give us the screen frame for this content node
nsIFrame* frame = shell->GetPrimaryFrameFor(mContent);
if (!frame)
return;
// make sure this is REALLY an nsIObjectFrame
// we may need to go through the children to get it
nsIObjectFrame* objectFrame = nsnull;
CallQueryInterface(frame,&objectFrame);
if (!objectFrame)
objectFrame = GetNextObjectFrame(aPresContext,frame);
NS_ENSURE_TRUE(objectFrame,NS_ERROR_FAILURE);
nsPresContext* presContext = GetPresContext();
// make sure this is REALLY an nsIObjectFrame
// we may need to go through the children to get it
nsIObjectFrame* objectFrame = nsnull;
CallQueryInterface(frame,&objectFrame);
if (!objectFrame)
objectFrame = GetNextObjectFrame(presContext,frame);
if (!objectFrame)
return;
// finally we can get our plugin instance
nsCOMPtr<nsIPluginInstance> pi;
if (NS_FAILED(objectFrame->GetPluginInstance(*getter_AddRefs(pi))) || !pi)
return NS_ERROR_FAILURE;
// finally we can get our plugin instance
nsCOMPtr<nsIPluginInstance> pi;
if (NS_FAILED(objectFrame->GetPluginInstance(*getter_AddRefs(pi))) || !pi)
return;
// now we need to setup the correct location for printing
nsresult rv;
nsPluginWindow window;
window.window = nsnull;
// now we need to setup the correct location for printing
nsresult rv;
nsPluginWindow window;
window.window = nsnull;
// prepare embedded mode printing struct
nsPluginPrint npprint;
npprint.mode = nsPluginMode_Embedded;
// prepare embedded mode printing struct
nsPluginPrint npprint;
npprint.mode = nsPluginMode_Embedded;
// we need to find out if we are windowless or not
PRBool windowless = PR_FALSE;
pi->GetValue(nsPluginInstanceVariable_WindowlessBool, (void *)&windowless);
window.type = windowless ? nsPluginWindowType_Drawable : nsPluginWindowType_Window;
// we need to find out if we are windowless or not
PRBool windowless = PR_FALSE;
pi->GetValue(nsPluginInstanceVariable_WindowlessBool, (void *)&windowless);
window.type = windowless ? nsPluginWindowType_Drawable : nsPluginWindowType_Window;
// Get the offset of the DC
nsTransform2D* rcTransform;
aRenderingContext.GetCurrentTransform(rcTransform);
nsPoint origin;
rcTransform->GetTranslationCoord(&origin.x, &origin.y);
// Get the conversion factor between pixels and twips
float t2p = aPresContext->TwipsToPixels();
// set it all up
// XXX is windowless different?
window.x = origin.x;
window.y = origin.y;
window.width = NSToCoordRound(mRect.width * t2p);
window.height= NSToCoordRound(mRect.height * t2p);
window.clipRect.bottom = 0; window.clipRect.top = 0;
window.clipRect.left = 0; window.clipRect.right = 0;
// Get the offset of the DC
nsTransform2D* rcTransform;
aRenderingContext.GetCurrentTransform(rcTransform);
nsPoint origin;
rcTransform->GetTranslationCoord(&origin.x, &origin.y);
// Get the conversion factor between pixels and twips
float t2p = presContext->TwipsToPixels();
// set it all up
// XXX is windowless different?
window.x = origin.x;
window.y = origin.y;
window.width = NSToCoordRound(mRect.width * t2p);
window.height= NSToCoordRound(mRect.height * t2p);
window.clipRect.bottom = 0; window.clipRect.top = 0;
window.clipRect.left = 0; window.clipRect.right = 0;
// XXX platform specific printing code
#if defined(XP_UNIX) && !defined(XP_MACOSX)
/* UNIX does things completely differently:
* We call the plugin and it sends generated PostScript data into a
* file handle we provide. If the plugin returns with success we embed
* this PostScript code fragment into the PostScript job we send to the
* printer.
*/
* We call the plugin and it sends generated PostScript data into a
* file handle we provide. If the plugin returns with success we embed
* this PostScript code fragment into the PostScript job we send to the
* printer.
*/
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG, ("nsObjectFrame::Paint() start for X11 platforms\n"));
FILE *plugintmpfile = tmpfile();
if (!plugintmpfile) {
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG, ("error: could not open tmp. file, errno=%d\n", errno));
return NS_ERROR_FAILURE;
}
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG, ("nsObjectFrame::Paint() start for X11 platforms\n"));
FILE *plugintmpfile = tmpfile();
if (!plugintmpfile) {
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG, ("error: could not open tmp. file, errno=%d\n", errno));
return;
}
/* Send off print info to plugin */
NPPrintCallbackStruct npPrintInfo;
npPrintInfo.type = NP_PRINT;
npPrintInfo.fp = plugintmpfile;
npprint.print.embedPrint.platformPrint = (void *)&npPrintInfo;
/* aDirtyRect contains the right information for ps print */
window.x = aDirtyRect.x;
window.y = aDirtyRect.y;
window.width = aDirtyRect.width;
window.height = aDirtyRect.height;
npprint.print.embedPrint.window = window;
rv = pi->Print(&npprint);
if (NS_FAILED(rv)) {
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG, ("error: plugin returned failure %lx\n", (long)rv));
fclose(plugintmpfile);
return rv;
}
/* Send data to printer */
rv = aRenderingContext.RenderEPS(aDirtyRect, plugintmpfile);
NPPrintCallbackStruct npPrintInfo;
npPrintInfo.type = NP_PRINT;
npPrintInfo.fp = plugintmpfile;
npprint.print.embedPrint.platformPrint = (void *)&npPrintInfo;
/* aDirtyRect contains the right information for ps print */
window.x = aDirtyRect.x;
window.y = aDirtyRect.y;
window.width = aDirtyRect.width;
window.height = aDirtyRect.height;
npprint.print.embedPrint.window = window;
rv = pi->Print(&npprint);
if (NS_FAILED(rv)) {
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG, ("error: plugin returned failure %lx\n", (long)rv));
fclose(plugintmpfile);
return;
}
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG, ("plugin printing done, return code is %lx\n", (long)rv));
/* Send data to printer */
rv = aRenderingContext.RenderEPS(aDirtyRect, plugintmpfile);
fclose(plugintmpfile);
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG, ("plugin printing done, return code is %lx\n", (long)rv));
#else // Windows and non-UNIX, non-Mac(Classic) cases
// we need the native printer device context to pass to plugin
// On Windows, this will be the HDC
void* dc;
dc = aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC);
// we need the native printer device context to pass to plugin
// On Windows, this will be the HDC
void* dc;
dc = aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC);
npprint.print.embedPrint.platformPrint = dc;
npprint.print.embedPrint.window = window;
// send off print info to plugin
npprint.print.embedPrint.platformPrint = dc;
npprint.print.embedPrint.window = window;
// send off print info to plugin
rv = pi->Print(&npprint);
#endif
// XXX Nav 4.x always sent a SetWindow call after print. Should we do the same?
nsDidReflowStatus status = NS_FRAME_REFLOW_FINISHED; // should we use a special status?
frame->DidReflow(shell->GetPresContext(),
nsnull, status); // DidReflow will take care of it
// XXX Nav 4.x always sent a SetWindow call after print. Should we do the same?
nsDidReflowStatus status = NS_FRAME_REFLOW_FINISHED; // should we use a special status?
frame->DidReflow(presContext,
nsnull, status); // DidReflow will take care of it
}
return rv; // done with printing
}
// Screen painting code
#ifdef XP_MACOSX
void
nsObjectFrame::PaintPlugin(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect)
{
// Screen painting code
#if defined(XP_MAC) || defined(XP_MACOSX)
// delegate all painting to the plugin instance.
if ((NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) && mInstanceOwner)
if (mInstanceOwner)
mInstanceOwner->Paint(aDirtyRect);
#elif defined (XP_WIN) || defined(XP_OS2)
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
nsCOMPtr<nsIPluginInstance> inst;
GetPluginInstance(*getter_AddRefs(inst));
if (inst) {
// Look if it's windowless
nsPluginWindow * window;
mInstanceOwner->GetWindow(window);
nsCOMPtr<nsIPluginInstance> inst;
GetPluginInstance(*getter_AddRefs(inst));
if (inst) {
// Look if it's windowless
nsPluginWindow * window;
mInstanceOwner->GetWindow(window);
if (window->type == nsPluginWindowType_Drawable) {
// check if we need to call SetWindow with updated parameters
PRBool doupdatewindow = PR_FALSE;
if (window->type == nsPluginWindowType_Drawable) {
// check if we need to call SetWindow with updated parameters
PRBool doupdatewindow = PR_FALSE;
// check if we need to update hdc
void* hdc;
hdc = aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC);
if (NS_REINTERPRET_CAST(PRUint32, window->window) != (PRUint32)(HDC)hdc) {
window->window = NS_REINTERPRET_CAST(nsPluginPort*, hdc);
doupdatewindow = PR_TRUE;
}
// check if we need to update hdc
void* hdc;
hdc = aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC);
if (NS_REINTERPRET_CAST(PRUint32, window->window) != (PRUint32)(HDC)hdc) {
window->window = NS_REINTERPRET_CAST(nsPluginPort*, hdc);
doupdatewindow = PR_TRUE;
}
/*
* Layout now has an optimized way of painting. Now we always get
* a new drawing surface, sized to be just what's needed. Windowless
* plugins need a transform applied to their origin so they paint
* in the right place. Since |SetWindow| is no longer being used
* to tell the plugin where it is, we dispatch a NPWindow through
* |HandleEvent| to tell the plugin when its window moved
*/
/*
* Layout now has an optimized way of painting. Now we always get
* a new drawing surface, sized to be just what's needed. Windowless
* plugins need a transform applied to their origin so they paint
* in the right place. Since |SetWindow| is no longer being used
* to tell the plugin where it is, we dispatch a NPWindow through
* |HandleEvent| to tell the plugin when its window moved
*/
// Get the offset of the DC
nsTransform2D* rcTransform;
aRenderingContext.GetCurrentTransform(rcTransform);
nsPoint origin;
rcTransform->GetTranslationCoord(&origin.x, &origin.y);
// Get the offset of the DC
nsTransform2D* rcTransform;
aRenderingContext.GetCurrentTransform(rcTransform);
nsPoint origin;
rcTransform->GetTranslationCoord(&origin.x, &origin.y);
if ((window->x != origin.x) || (window->y != origin.y)) {
window->x = origin.x;
window->y = origin.y;
doupdatewindow = PR_TRUE;
}
if ((window->x != origin.x) || (window->y != origin.y)) {
window->x = origin.x;
window->y = origin.y;
doupdatewindow = PR_TRUE;
}
// if our location or visible area has changed, we need to tell the plugin
if (doupdatewindow) {
// if our location or visible area has changed, we need to tell the plugin
if (doupdatewindow) {
#ifdef XP_WIN // Windowless plugins on windows need a special event to update their location, see bug 135737
// first, lets find out how big the window is, in pixels
nsIViewManager* vm = aPresContext->GetViewManager();
if (vm) {
nsIView* view;
vm->GetRootView(view);
if (view) {
nsIWidget* win = view->GetWidget();
if (win) {
nsRect visibleRect;
win->GetBounds(visibleRect);
// next, get our plugin's rect so we can intersect it with the visible rect so we
// can tell the plugin where and how much to paint
NS_ASSERTION(window->type == nsPluginWindowType_Drawable,
"What happened to our window type?");
origin = GetWindowOriginInPixels(PR_TRUE);
nsRect winlessRect = nsRect(origin, nsSize(window->width, window->height));
winlessRect.IntersectRect(winlessRect, visibleRect);
// first, lets find out how big the window is, in pixels
nsIViewManager* vm = GetPresContext()->GetViewManager();
if (vm) {
nsIView* view;
vm->GetRootView(view);
if (view) {
nsIWidget* win = view->GetWidget();
if (win) {
nsRect visibleRect;
win->GetBounds(visibleRect);
// next, get our plugin's rect so we can intersect it with the visible rect so we
// can tell the plugin where and how much to paint
NS_ASSERTION(window->type == nsPluginWindowType_Drawable,
"What happened to our window type?");
origin = GetWindowOriginInPixels(PR_TRUE);
nsRect winlessRect = nsRect(origin, nsSize(window->width, window->height));
winlessRect.IntersectRect(winlessRect, visibleRect);
// now check our cached window and only update plugin if something has changed
if (mWindowlessRect != winlessRect) {
mWindowlessRect = winlessRect;
// now check our cached window and only update plugin if something has changed
if (mWindowlessRect != winlessRect) {
mWindowlessRect = winlessRect;
WINDOWPOS winpos;
memset(&winpos, 0, sizeof(winpos));
winpos.x = mWindowlessRect.x;
winpos.y = mWindowlessRect.y;
winpos.cx = mWindowlessRect.width;
winpos.cy = mWindowlessRect.height;
WINDOWPOS winpos;
memset(&winpos, 0, sizeof(winpos));
winpos.x = mWindowlessRect.x;
winpos.y = mWindowlessRect.y;
winpos.cx = mWindowlessRect.width;
winpos.cy = mWindowlessRect.height;
// finally, update the plugin by sending it a WM_WINDOWPOSCHANGED event
nsPluginEvent pluginEvent;
pluginEvent.event = WM_WINDOWPOSCHANGED;
pluginEvent.wParam = 0;
pluginEvent.lParam = (uint32)&winpos;
PRBool eventHandled = PR_FALSE;
// finally, update the plugin by sending it a WM_WINDOWPOSCHANGED event
nsPluginEvent pluginEvent;
pluginEvent.event = WM_WINDOWPOSCHANGED;
pluginEvent.wParam = 0;
pluginEvent.lParam = (uint32)&winpos;
PRBool eventHandled = PR_FALSE;
inst->HandleEvent(&pluginEvent, &eventHandled);
}
}
inst->HandleEvent(&pluginEvent, &eventHandled);
}
}
}
}
#endif
inst->SetWindow(window);
}
mInstanceOwner->Paint(aDirtyRect, (PRUint32)(HDC)hdc);
inst->SetWindow(window);
}
// This expects a dirty rect relative to the plugin's rect
// XXX I wonder if this breaks if we give the frame a border so the
// frame origin and plugin origin are not the same
mInstanceOwner->Paint(aDirtyRect, (PRUint32)(HDC)hdc);
}
}
#endif
DO_GLOBAL_REFLOW_COUNT_DSP("nsObjectFrame", &aRenderingContext);
return NS_OK;
#endif /* !XP_MAC */
}
NS_IMETHODIMP

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

@ -71,11 +71,14 @@ public:
NS_IMETHOD DidReflow(nsPresContext* aPresContext,
const nsHTMLReflowState* aReflowState,
nsDidReflowStatus aStatus);
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
void PrintPlugin(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
void PaintPlugin(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
nsGUIEvent* aEvent,

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

@ -45,6 +45,7 @@
#include "nsIDeviceContext.h"
#include "nsReadableUtils.h"
#include "nsSimplePageSequence.h"
#include "nsDisplayList.h"
#include "nsIView.h"
@ -163,14 +164,10 @@ nsPageContentFrame::IsContainingBlock() const
//------------------------------------------------------------------------------
NS_IMETHODIMP
nsPageContentFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
nsPageContentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
aRenderingContext.PushState();
nsRect rect;
if (mClipRect.width != -1 || mClipRect.height != -1) {
rect = mClipRect;
@ -180,24 +177,9 @@ nsPageContentFrame::Paint(nsPresContext* aPresContext,
rect.y = 0;
}
aRenderingContext.SetClipRect(rect, nsClipCombine_kReplace);
nsDisplayListCollection set;
nsresult rv = nsContainerFrame::BuildDisplayList(aBuilder, aDirtyRect, set);
NS_ENSURE_SUCCESS(rv, rv);
nsresult rv = nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
#if defined(DEBUG_rods) || defined(DEBUG_dcone)
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
nsRect r = mRect;
r.x = 0;
r.y = 0;
aRenderingContext.SetColor(NS_RGB(0, 0, 0));
aRenderingContext.DrawRect(r);
}
#endif
aRenderingContext.PopState();
return rv;
return Clip(aBuilder, set, aLists, rect);
}

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

@ -54,11 +54,9 @@ public:
const nsHTMLReflowState& aMaxSize,
nsReflowStatus& aStatus);
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
virtual PRBool IsContainingBlock() const;

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

@ -47,6 +47,7 @@
#include "nsIDeviceContext.h"
#include "nsReadableUtils.h"
#include "nsPageContentFrame.h"
#include "nsDisplayList.h"
#include "nsLayoutUtils.h" // for function BinarySearchForPosition
#include "nsIView.h" // view flags for clipping
@ -514,133 +515,69 @@ nsPageFrame::DrawHeaderFooter(nsPresContext* aPresContext,
}
}
static void PaintPrintPreviewBackground(nsIFrame* aFrame, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aPt)
{
NS_STATIC_CAST(nsPageFrame*, aFrame)->PaintPrintPreviewBackground(*aCtx, aPt);
}
static void PaintPageBackground(nsIFrame* aFrame, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aPt)
{
NS_STATIC_CAST(nsPageFrame*, aFrame)->DrawBackground(*aCtx, aDirtyRect, aPt);
}
static void PaintHeaderFooter(nsIFrame* aFrame, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aPt)
{
NS_STATIC_CAST(nsPageFrame*, aFrame)->PaintHeaderFooter(*aCtx, aPt);
}
//------------------------------------------------------------------------------
NS_IMETHODIMP
nsPageFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
nsPageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
aRenderingContext.PushState();
aRenderingContext.SetColor(NS_RGB(255,255,255));
nsRect rect;
PRBool specialClipIsSet = mClipRect.width != -1 || mClipRect.height != -1;
if (specialClipIsSet) {
#ifdef DEBUG_PRINTING
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
printf("*** ClipRect: %5d,%5d,%5d,%5d\n", mClipRect.x, mClipRect.y, mClipRect.width, mClipRect.height);
}
#endif
aRenderingContext.SetClipRect(mClipRect, nsClipCombine_kReplace);
rect = mClipRect;
} else {
rect = mRect;
nsDisplayListCollection set;
if (GetPresContext()->Type() == nsPresContext::eContext_PrintPreview) {
nsresult rv = set.BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayGeneric(this, ::PaintPrintPreviewBackground, "PrintPreviewBackground"));
NS_ENSURE_SUCCESS(rv, rv);
}
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
if (aPresContext->Type() == nsPresContext::eContext_PrintPreview) {
// fill page with White
aRenderingContext.SetColor(NS_RGB(255,255,255));
rect.x = 0;
rect.y = 0;
rect.width -= mPD->mShadowSize.width;
rect.height -= mPD->mShadowSize.height;
aRenderingContext.FillRect(rect);
// draw line around outside of page
aRenderingContext.SetColor(NS_RGB(0,0,0));
aRenderingContext.DrawRect(rect);
if (mPD->mShadowSize.width > 0 && mPD->mShadowSize.height > 0) {
aRenderingContext.SetColor(NS_RGB(51,51,51));
nsRect r(0,0, mRect.width, mRect.height);
nsRect shadowRect;
shadowRect.x = r.x + r.width - mPD->mShadowSize.width;
shadowRect.y = r.y + mPD->mShadowSize.height;
shadowRect.width = mPD->mShadowSize.width;
shadowRect.height = r.height - mPD->mShadowSize.height;
aRenderingContext.FillRect(shadowRect);
shadowRect.x = r.x + mPD->mShadowSize.width;
shadowRect.y = r.y + r.height - mPD->mShadowSize.height;
shadowRect.width = r.width - mPD->mShadowSize.width;
shadowRect.height = mPD->mShadowSize.height;
aRenderingContext.FillRect(shadowRect);
}
}
}
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
DrawBackground(aPresContext,aRenderingContext,aDirtyRect);
}
nsresult rv = nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
nsresult rv = set.BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayGeneric(this, ::PaintPageBackground, "PageBackground"));
NS_ENSURE_SUCCESS(rv, rv);
// REVIEW: There was a "aRenderingContext.SetColor(NS_RGB(255,255,255));"
// here which was overridden on every code path, so I removed it.
rv = nsContainerFrame::BuildDisplayList(aBuilder, aDirtyRect, set);
NS_ENSURE_SUCCESS(rv, rv);
#if defined(DEBUG_rods) || defined(DEBUG_dcone)
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
PR_PL(("PF::Paint -> %p SupHF: %s Rect: [%5d,%5d,%5d,%5d] SC:%s\n", this,
mSupressHF?"Yes":"No", mRect.x, mRect.y, mRect.width, mRect.height, specialClipIsSet?"Yes":"No"));
PR_PL(("PF::Paint -> %p SupHF: %s Rect: [%5d,%5d,%5d,%5d] SC:%s\n", this,
mSupressHF?"Yes":"No", mRect.x, mRect.y, mRect.width, mRect.height, specialClipIsSet?"Yes":"No"));
}
PR_PL(("PF::Paint -> %p SupHF: %s Rect: [%5d,%5d,%5d,%5d] SC:%s\n", this,
mSupressHF?"Yes":"No", mRect.x, mRect.y, mRect.width, mRect.height, specialClipIsSet?"Yes":"No"));
PR_PL(("PF::Paint -> %p SupHF: %s Rect: [%5d,%5d,%5d,%5d] SC:%s\n", this,
mSupressHF?"Yes":"No", mRect.x, mRect.y, mRect.width, mRect.height, specialClipIsSet?"Yes":"No"));
#endif
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer && !mSupressHF) {
// For PrintPreview the
if (!mPD->mPrintSettings) {
if (aPresContext->Type() == nsPresContext::eContext_PrintPreview) {
mPD->mPrintSettings = aPresContext->GetPrintSettings();
}
}
NS_ASSERTION(mPD->mPrintSettings, "Must have a good PrintSettings here!");
// get the current margin
mPD->mPrintSettings->GetMarginInTwips(mMargin);
rect.SetRect(0, 0, mRect.width - mPD->mShadowSize.width, mRect.height - mPD->mShadowSize.height);
aRenderingContext.SetFont(*mPD->mHeadFootFont, nsnull);
aRenderingContext.SetColor(NS_RGB(0,0,0));
// Get the FontMetrics to determine width.height of strings
nsCOMPtr<nsIFontMetrics> fontMet;
aPresContext->DeviceContext()->GetMetricsFor(*mPD->mHeadFootFont, nsnull,
*getter_AddRefs(fontMet));
nscoord ascent = 0;
nscoord visibleHeight = 0;
if (fontMet) {
fontMet->GetHeight(visibleHeight);
fontMet->GetMaxAscent(ascent);
}
// print document headers and footers
PRUnichar * headers[3];
mPD->mPrintSettings->GetHeaderStrLeft(&headers[0]); // creates memory
mPD->mPrintSettings->GetHeaderStrCenter(&headers[1]); // creates memory
mPD->mPrintSettings->GetHeaderStrRight(&headers[2]); // creates memory
DrawHeaderFooter(aPresContext, aRenderingContext, this, eHeader, nsIPrintSettings::kJustLeft,
nsAutoString(headers[0]), nsAutoString(headers[1]), nsAutoString(headers[2]),
rect, ascent, visibleHeight);
PRInt32 i;
for (i=0;i<3;i++) nsMemory::Free(headers[i]);
PRUnichar * footers[3];
mPD->mPrintSettings->GetFooterStrLeft(&footers[0]); // creates memory
mPD->mPrintSettings->GetFooterStrCenter(&footers[1]); // creates memory
mPD->mPrintSettings->GetFooterStrRight(&footers[2]); // creates memory
DrawHeaderFooter(aPresContext, aRenderingContext, this, eFooter, nsIPrintSettings::kJustRight,
nsAutoString(footers[0]), nsAutoString(footers[1]), nsAutoString(footers[2]),
rect, ascent, visibleHeight);
for (i=0;i<3;i++) nsMemory::Free(footers[i]);
if (!mSupressHF) {
rv = set.Content()->AppendNewToTop(new (aBuilder)
nsDisplayGeneric(this, ::PaintHeaderFooter, "HeaderFooter"));
NS_ENSURE_SUCCESS(rv, rv);
}
aRenderingContext.PopState();
if (mClipRect.width != -1 || mClipRect.height != -1) {
#ifdef DEBUG_PRINTING
printf("*** ClipRect: %5d,%5d,%5d,%5d\n", mClipRect.x, mClipRect.y, mClipRect.width, mClipRect.height);
#endif
return Clip(aBuilder, set, aLists, mClipRect);
}
return rv;
set.MoveTo(aLists);
return NS_OK;
}
//------------------------------------------------------------------------------
@ -652,11 +589,100 @@ nsPageFrame::SetPageNumInfo(PRInt32 aPageNumber, PRInt32 aTotalPages)
}
void
nsPageFrame::PaintPrintPreviewBackground(nsIRenderingContext& aRenderingContext,
nsPoint aPt)
{
// fill page with White
aRenderingContext.SetColor(NS_RGB(255,255,255));
// REVIEW: this used to have rect's width and height be the
// mClipRect if specialClipIsSet ... but that seems completely bogus
// and inconsistent with the painting of the shadow below
nsRect rect(aPt, GetSize());
rect.width -= mPD->mShadowSize.width;
rect.height -= mPD->mShadowSize.height;
aRenderingContext.FillRect(rect);
// draw line around outside of page
aRenderingContext.SetColor(NS_RGB(0,0,0));
aRenderingContext.DrawRect(rect);
if (mPD->mShadowSize.width > 0 && mPD->mShadowSize.height > 0) {
aRenderingContext.SetColor(NS_RGB(51,51,51));
nsRect r(aPt.x,aPt.y, mRect.width, mRect.height);
nsRect shadowRect;
shadowRect.x = r.x + r.width - mPD->mShadowSize.width;
shadowRect.y = r.y + mPD->mShadowSize.height;
shadowRect.width = mPD->mShadowSize.width;
shadowRect.height = r.height - mPD->mShadowSize.height;
aRenderingContext.FillRect(shadowRect);
shadowRect.x = r.x + mPD->mShadowSize.width;
shadowRect.y = r.y + r.height - mPD->mShadowSize.height;
shadowRect.width = r.width - mPD->mShadowSize.width;
shadowRect.height = mPD->mShadowSize.height;
aRenderingContext.FillRect(shadowRect);
}
}
void
nsPageFrame::PaintHeaderFooter(nsIRenderingContext& aRenderingContext,
nsPoint aPt)
{
nsPresContext* pc = GetPresContext();
if (!mPD->mPrintSettings) {
if (pc->Type() == nsPresContext::eContext_PrintPreview) {
mPD->mPrintSettings = pc->GetPrintSettings();
}
}
NS_ASSERTION(mPD->mPrintSettings, "Must have a good PrintSettings here!");
// get the current margin
mPD->mPrintSettings->GetMarginInTwips(mMargin);
nsRect rect(aPt.x, aPt.y, mRect.width - mPD->mShadowSize.width,
mRect.height - mPD->mShadowSize.height);
aRenderingContext.SetFont(*mPD->mHeadFootFont, nsnull);
aRenderingContext.SetColor(NS_RGB(0,0,0));
// Get the FontMetrics to determine width.height of strings
nsCOMPtr<nsIFontMetrics> fontMet;
pc->DeviceContext()->GetMetricsFor(*mPD->mHeadFootFont, nsnull,
*getter_AddRefs(fontMet));
nscoord ascent = 0;
nscoord visibleHeight = 0;
if (fontMet) {
fontMet->GetHeight(visibleHeight);
fontMet->GetMaxAscent(ascent);
}
// print document headers and footers
PRUnichar * headers[3];
mPD->mPrintSettings->GetHeaderStrLeft(&headers[0]); // creates memory
mPD->mPrintSettings->GetHeaderStrCenter(&headers[1]); // creates memory
mPD->mPrintSettings->GetHeaderStrRight(&headers[2]); // creates memory
DrawHeaderFooter(pc, aRenderingContext, this, eHeader, nsIPrintSettings::kJustLeft,
nsAutoString(headers[0]), nsAutoString(headers[1]), nsAutoString(headers[2]),
rect, ascent, visibleHeight);
PRInt32 i;
for (i=0;i<3;i++) nsMemory::Free(headers[i]);
PRUnichar * footers[3];
mPD->mPrintSettings->GetFooterStrLeft(&footers[0]); // creates memory
mPD->mPrintSettings->GetFooterStrCenter(&footers[1]); // creates memory
mPD->mPrintSettings->GetFooterStrRight(&footers[2]); // creates memory
DrawHeaderFooter(pc, aRenderingContext, this, eFooter, nsIPrintSettings::kJustRight,
nsAutoString(footers[0]), nsAutoString(footers[1]), nsAutoString(footers[2]),
rect, ascent, visibleHeight);
for (i=0;i<3;i++) nsMemory::Free(footers[i]);
}
//------------------------------------------------------------------------------
void
nsPageFrame::DrawBackground(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect)
nsPageFrame::DrawBackground(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsPoint aPt)
{
nsSimplePageSequenceFrame* seqFrame = NS_STATIC_CAST(nsSimplePageSequenceFrame*, mParent);
if (seqFrame != nsnull) {
@ -666,8 +692,8 @@ nsPageFrame::DrawBackground(nsPresContext* aPresContext,
const nsStyleBorder* border = GetStyleBorder();
const nsStylePadding* padding = GetStylePadding();
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
aDirtyRect, pageContentFrame->GetRect(), *border, *padding,
nsCSSRendering::PaintBackground(GetPresContext(), aRenderingContext, this,
aDirtyRect, pageContentFrame->GetRect() + aPt, *border, *padding,
PR_TRUE);
}
}

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

@ -59,11 +59,9 @@ public:
const nsHTMLReflowState& aMaxSize,
nsReflowStatus& aStatus);
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
virtual PRBool IsContainingBlock() const;
@ -94,6 +92,14 @@ public:
static void SetCreateWidget(PRBool aDoCreateWidget) { mDoCreateWidget = aDoCreateWidget; }
static PRBool GetCreateWidget() { return mDoCreateWidget; }
void PaintPrintPreviewBackground(nsIRenderingContext& aRenderingContext,
nsPoint aPt);
void PaintHeaderFooter(nsIRenderingContext& aRenderingContext,
nsPoint aPt);
void DrawBackground(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsPoint aPt);
protected:
nsPageFrame();
virtual ~nsPageFrame();
@ -145,11 +151,6 @@ protected:
// XXX Part of Temporary fix for Bug 127263
static PRBool mDoCreateWidget;
private:
void DrawBackground(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
};

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

@ -41,6 +41,7 @@
#include "nsIRenderingContext.h"
#include "nsLayoutAtoms.h"
#include "nsFrameManager.h"
#include "nsDisplayList.h"
nsIFrame*
NS_NewPlaceholderFrame(nsIPresShell* aPresShell)
@ -97,26 +98,31 @@ nsPlaceholderFrame::GetType() const
}
#ifdef DEBUG
NS_IMETHODIMP
nsPlaceholderFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
static void
PaintDebugPlaceholder(nsIFrame* aFrame, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect, nsPoint aPt)
{
if ((NS_FRAME_PAINT_LAYER_DEBUG == aWhichLayer) && GetShowFrameBorders()) {
float p2t;
p2t = aPresContext->PixelsToTwips();
aRenderingContext.SetColor(NS_RGB(0, 255, 255));
nscoord x = NSIntPixelsToTwips(-5, p2t);
aRenderingContext.FillRect(x, 0, NSIntPixelsToTwips(13, p2t),
NSIntPixelsToTwips(3, p2t));
nscoord y = NSIntPixelsToTwips(-10, p2t);
aRenderingContext.FillRect(0, y, NSIntPixelsToTwips(3, p2t),
NSIntPixelsToTwips(10, p2t));
}
DO_GLOBAL_REFLOW_COUNT_DSP("nsPlaceholderFrame", &aRenderingContext);
return NS_OK;
float p2t;
p2t = aFrame->GetPresContext()->PixelsToTwips();
aCtx->SetColor(NS_RGB(0, 255, 255));
nscoord x = NSIntPixelsToTwips(-5, p2t);
aCtx->FillRect(aPt.x + x, aPt.y,
NSIntPixelsToTwips(13, p2t), NSIntPixelsToTwips(3, p2t));
nscoord y = NSIntPixelsToTwips(-10, p2t);
aCtx->FillRect(aPt.x, aPt.y + y,
NSIntPixelsToTwips(3, p2t), NSIntPixelsToTwips(10, p2t));
}
NS_IMETHODIMP
nsPlaceholderFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
if (!GetShowFrameBorders())
return NS_OK;
return aLists.Outlines()->AppendNewToTop(new (aBuilder)
nsDisplayGeneric(this, PaintDebugPlaceholder, "DebugPlaceholder"));
}
NS_IMETHODIMP

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

@ -69,11 +69,9 @@ public:
// nsIFrame overrides
#ifdef DEBUG
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
#endif

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

@ -51,6 +51,7 @@
#include "nsLayoutAtoms.h"
#include "nsCSSFrameConstructor.h"
#include "nsContentUtils.h"
#include "nsDisplayList.h"
// DateTime Includes
#include "nsDateTimeFormatCID.h"
@ -963,6 +964,20 @@ nsSimplePageSequenceFrame::SetClipRect(nsPresContext* aPresContext, nsRect* aRe
}
//------------------------------------------------------------------------------
NS_IMETHODIMP
nsSimplePageSequenceFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
// Treat each page as a psuedo-stack so everything goes in the Content() list.
return
BuildDisplayListForNonBlockChildren(aBuilder, aDirtyRect, aLists,
DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT);
}
nsIAtom*
nsSimplePageSequenceFrame::GetType() const
{

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

@ -82,12 +82,16 @@ public:
// nsISupports
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
// nsIFrameReflow
// nsIFrame
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aMaxSize,
nsReflowStatus& aStatus);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
// nsIPageSequenceFrame
NS_IMETHOD SetOffsets(nscoord aStartOffset, nscoord aEndOffset);
NS_IMETHOD SetPageNo(PRInt32 aPageNo) { return NS_OK;}

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

@ -75,6 +75,7 @@
#include "nsCompatibility.h"
#include "nsCSSColorUtils.h"
#include "nsLayoutUtils.h"
#include "nsDisplayList.h"
#include "nsFrame.h"
#include "nsTextTransformer.h"
#include "nsITextContent.h"
@ -252,11 +253,11 @@ public:
nsTextFrame();
// nsIFrame
NS_IMETHOD Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
void PaintText(nsIRenderingContext& aRenderingContext, nsPoint aPt);
NS_IMETHOD Destroy(nsPresContext* aPresContext);
@ -327,10 +328,7 @@ public:
PRInt32* outFrameContentOffset,
nsIFrame* *outChildFrame);
NS_IMETHOD IsVisibleForPainting(nsPresContext * aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aCheckVis,
PRBool* aIsVisible);
virtual PRBool IsVisibleInSelection(nsISelection* aSelection);
virtual PRBool IsEmpty();
virtual PRBool IsSelfEmpty() { return IsEmpty(); }
@ -466,11 +464,11 @@ public:
PRUnichar* aBuffer, PRInt32 aLength, PRBool aIsEndOfFrame,
nscoord aWidth);
PRBool IsTextInSelection(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext);
// REVIEW: There is absolute no reason why IsTextInSelection should depend
// on a rendering context, and I've refactored the code so it doesn't.
PRBool IsTextInSelection();
nsresult GetTextInfoForPainting(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsresult GetTextInfoForPainting(nsPresContext* aPresContext,
nsIPresShell** aPresShell,
nsISelectionController** aSelectionController,
PRBool& aDisplayingSelection,
@ -1448,7 +1446,7 @@ class DrawSelectionIterator
{
public:
DrawSelectionIterator(const SelectionDetails *aSelDetails, PRUnichar *aText,
PRUint32 aTextLength, nsTextPaintStyle &aTextStyle,
PRUint32 aTextLength, nsTextPaintStyle *aTextStyle,
SelectionType aCareSelections);
~DrawSelectionIterator();
PRBool First();
@ -1459,7 +1457,6 @@ public:
PRUnichar * CurrentTextUnicharPtr();
char * CurrentTextCStrPtr();
PRUint32 CurrentLength();
nsTextPaintStyle & CurrentStyle();
PRBool IsBeforeOrAfter();
/**
@ -1484,7 +1481,7 @@ private:
PRUint32 mLength;
PRUint32 mCurrentIdx;
PRUint32 mCurrentLength;
nsTextPaintStyle &mOldStyle; //base new styles on this one???
nsTextPaintStyle* mOldStyle;//base new styles on this one???
const SelectionDetails *mDetails;
PRBool mDone;
PRUint8 * mTypes;
@ -1496,7 +1493,7 @@ private:
DrawSelectionIterator::DrawSelectionIterator(const SelectionDetails *aSelDetails,
PRUnichar *aText,
PRUint32 aTextLength,
nsTextPaintStyle &aTextStyle,
nsTextPaintStyle* aTextStyle,
SelectionType aCareSelections)
:mOldStyle(aTextStyle)
{
@ -1662,12 +1659,6 @@ DrawSelectionIterator::CurrentLength()
return mCurrentLength;
}
nsTextPaintStyle &
DrawSelectionIterator::CurrentStyle()
{
return mOldStyle;
}
PRBool
DrawSelectionIterator::GetSelectionColors(nscolor *aForeColor,
nscolor *aBackColor,
@ -1676,23 +1667,23 @@ DrawSelectionIterator::GetSelectionColors(nscolor *aForeColor,
if (mTypes) {
// Normal selection
if (mTypes[mCurrentIdx] & nsTextPaintStyle::eNormalSelection) {
mOldStyle.GetSelectionColors(aForeColor, aBackColor,
aBackIsTransparent);
mOldStyle->GetSelectionColors(aForeColor, aBackColor,
aBackIsTransparent);
return PR_TRUE;
}
// IME selections
if (mTypes[mCurrentIdx] & nsTextPaintStyle::eIMESelections) {
mOldStyle.GetIMESelectionColors(mTypes[mCurrentIdx],
aForeColor, aBackColor,
aBackIsTransparent);
mOldStyle->GetIMESelectionColors(mTypes[mCurrentIdx],
aForeColor, aBackColor,
aBackIsTransparent);
return PR_TRUE;
}
}
// Non-supported Selection or Non-selection text
*aBackIsTransparent = PR_FALSE;
*aForeColor = mOldStyle.GetTextColor();
*aForeColor = mOldStyle->GetTextColor();
return PR_FALSE;
}
@ -1875,81 +1866,98 @@ nsTextFrame::CharacterDataChanged(nsPresContext* aPresContext,
return NS_OK;
}
NS_IMETHODIMP
nsTextFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
{
if (NS_FRAME_PAINT_LAYER_FOREGROUND != aWhichLayer) {
return NS_OK;
}
if ((0 != (mState & TEXT_BLINK_ON)) && nsBlinkTimer::GetBlinkIsOff()) {
return NS_OK;
}
nsStyleContext* sc = mStyleContext;
PRBool isVisible;
if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && isVisible) {
nsCOMPtr<nsIContent> content;
PRInt32 offset, length;
GetContentAndOffsetsForSelection(aPresContext,
getter_AddRefs(content),
&offset, &length);
PRInt16 selectionValue;
if (NS_FAILED(GetSelectionStatus(aPresContext, selectionValue)))
selectionValue = nsISelectionController::SELECTION_NORMAL;
nsTextPaintStyle ts(aPresContext,
aRenderingContext,
mStyleContext,
content,
selectionValue);
if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing)
|| ts.mJustifying) {
PaintTextSlowly(aPresContext, aRenderingContext, sc, ts, 0, 0);
}
else {
// Get the text fragment
nsCOMPtr<nsITextContent> tc = do_QueryInterface(mContent);
const nsTextFragment* frag = nsnull;
if (tc) {
frag = tc->Text();
if (!frag) {
return NS_ERROR_FAILURE;
}
}
// When we fix nsTextFrame to handle bearing (character glyphs that
// extend outside the frame) by giving it overflow area, we'll need to fix
// this to use the overflow area as its bounds.
class nsDisplayText : public nsDisplayItem {
public:
nsDisplayText(nsTextFrame* aFrame) : mFrame(aFrame) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt) { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("Text")
private:
nsTextFrame* mFrame;
};
// Choose rendering pathway based on rendering context performance
// hint, whether it needs to be transformed, and whether it's
// multi-byte
PRBool hasMultiByteChars = (0 != (mState & TEXT_HAS_MULTIBYTE));
PRUint32 hints = 0;
aRenderingContext.GetHints(hints);
void
nsDisplayText::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect) {
mFrame->PaintText(*aCtx, aBuilder->ToReferenceFrame(mFrame));
}
NS_IMETHODIMP
nsTextFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
if (!IsVisibleForPainting(aBuilder))
return NS_OK;
if ((0 != (mState & TEXT_BLINK_ON)) && nsBlinkTimer::GetBlinkIsOff())
return NS_OK;
return aLists.Content()->AppendNewToTop(new (aBuilder) nsDisplayText(this));
}
void
nsTextFrame::PaintText(nsIRenderingContext& aRenderingContext, nsPoint aPt)
{
nsStyleContext* sc = mStyleContext;
nsPresContext* presContext = GetPresContext();
nsCOMPtr<nsIContent> content;
PRInt32 offset, length;
GetContentAndOffsetsForSelection(presContext,
getter_AddRefs(content),
&offset, &length);
PRInt16 selectionValue;
if (NS_FAILED(GetSelectionStatus(presContext, selectionValue)))
selectionValue = nsISelectionController::SELECTION_NORMAL;
nsTextPaintStyle ts(presContext, aRenderingContext, mStyleContext, content,
selectionValue);
if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing)
|| ts.mJustifying) {
PaintTextSlowly(presContext, aRenderingContext, sc, ts, aPt.x, aPt.y);
}
else {
// Get the text fragment
nsCOMPtr<nsITextContent> tc = do_QueryInterface(mContent);
const nsTextFragment* frag = nsnull;
if (tc) {
frag = tc->Text();
if (!frag) {
return;
}
}
// Choose rendering pathway based on rendering context performance
// hint, whether it needs to be transformed, and whether it's
// multi-byte
PRBool hasMultiByteChars = (0 != (mState & TEXT_HAS_MULTIBYTE));
PRUint32 hints = 0;
aRenderingContext.GetHints(hints);
#ifdef IBMBIDI
PRBool bidiEnabled = aPresContext->BidiEnabled();
PRBool bidiEnabled = presContext->BidiEnabled();
#else
const PRBool bidiEnabled = PR_FALSE;
const PRBool bidiEnabled = PR_FALSE;
#endif // IBMBIDI
// * BiDi text or text with multi-byte characters must always be
// rendered as Unicode.
// * Non-transformed, 1-byte text should always be rendered as
// ASCII.
// * Other transformed or 2-byte text should be rendered according
// to the preference of the hint from the rendering context.
if (bidiEnabled || hasMultiByteChars ||
((0 == (hints & NS_RENDERING_HINT_FAST_8BIT_TEXT)) &&
(frag->Is2b() || (0 != (mState & TEXT_WAS_TRANSFORMED))))) {
PaintUnicodeText(aPresContext, aRenderingContext, sc, ts, 0, 0);
}
else {
PaintAsciiText(aPresContext, aRenderingContext, sc, ts, 0, 0);
}
// * BiDi text or text with multi-byte characters must always be
// rendered as Unicode.
// * Non-transformed, 1-byte text should always be rendered as
// ASCII.
// * Other transformed or 2-byte text should be rendered according
// to the preference of the hint from the rendering context.
if (bidiEnabled || hasMultiByteChars ||
((0 == (hints & NS_RENDERING_HINT_FAST_8BIT_TEXT)) &&
(frag->Is2b() || (0 != (mState & TEXT_WAS_TRANSFORMED))))) {
PaintUnicodeText(presContext, aRenderingContext, sc, ts, aPt.x, aPt.y);
}
else {
PaintAsciiText(presContext, aRenderingContext, sc, ts, aPt.x, aPt.y);
}
}
DO_GLOBAL_REFLOW_COUNT_DSP("nsTextFrame", &aRenderingContext);
return NS_OK;
}
PRBool
@ -2529,8 +2537,7 @@ nsTextFrame::GetContentAndOffsetsForSelection(nsPresContext *aPresContext, nsICo
}
//---------------------------------------------------------
nsresult nsTextFrame::GetTextInfoForPainting(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsresult nsTextFrame::GetTextInfoForPainting(nsPresContext* aPresContext,
nsIPresShell** aPresShell,
nsISelectionController** aSelectionController,
PRBool& aDisplayingSelection,
@ -2616,8 +2623,7 @@ nsTextFrame::GetSelectionStatus(nsPresContext* aPresContext,
}
PRBool
nsTextFrame::IsTextInSelection(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext)
nsTextFrame::IsTextInSelection()
{
nsCOMPtr<nsISelectionController> selCon;
nsCOMPtr<nsIPresShell> shell;
@ -2626,8 +2632,8 @@ nsTextFrame::IsTextInSelection(nsPresContext* aPresContext,
PRBool isSelected;
PRBool hideStandardSelection;
PRInt16 selectionValue;
if (NS_FAILED(GetTextInfoForPainting(aPresContext,
aRenderingContext,
nsPresContext* presContext = GetPresContext();
if (NS_FAILED(GetTextInfoForPainting(presContext,
getter_AddRefs(shell),
getter_AddRefs(selCon),
displaySelection,
@ -2645,25 +2651,13 @@ nsTextFrame::IsTextInSelection(nsPresContext* aPresContext,
return PR_FALSE;
}
nsCOMPtr<nsIContent> content;
PRInt32 offset, length;
nsresult getContent = NS_OK;
getContent = GetContentAndOffsetsForSelection(aPresContext,
getter_AddRefs(content),
&offset, &length);
nsTextPaintStyle ts(aPresContext,
aRenderingContext,
mStyleContext,
content,
selectionValue);
// Transform text from content into renderable form
// XXX If the text fragment is already Unicode and the text wasn't
// transformed when we formatted it, then there's no need to do all
// this and we should just render the text fragment directly. See
// PaintAsciiText()...
nsTextTransformer tx(aPresContext);
nsTextTransformer tx(presContext);
PRInt32 textLength;
// no need to worry about justification, that's always on the slow path
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
@ -2684,10 +2678,17 @@ nsTextFrame::IsTextInSelection(nsPresContext* aPresContext,
if (!frameSelection)
frameSelection = shell->FrameSelection();
if (NS_SUCCEEDED(getContent) && content) {
frameSelection->LookUpSelection(content, mContentOffset,
mContentLength, &details,
PR_FALSE);
nsCOMPtr<nsIContent> content;
PRInt32 offset;
PRInt32 length;
nsresult rv = GetContentAndOffsetsForSelection(presContext,
getter_AddRefs(content),
&offset, &length);
if (NS_SUCCEEDED(rv) && content) {
rv = frameSelection->LookUpSelection(content, mContentOffset,
mContentLength, &details,
PR_FALSE);
}
//where are the selection points "really"
@ -2699,10 +2700,7 @@ nsTextFrame::IsTextInSelection(nsPresContext* aPresContext,
}
//while we have substrings...
//PRBool drawn = PR_FALSE;
DrawSelectionIterator iter(details,
text,
(PRUint32)textLength,
ts,
DrawSelectionIterator iter(details, text, (PRUint32)textLength, nsnull,
nsTextPaintStyle::eNormalSelection);
if (!iter.IsDone() && iter.First()) {
isSelected = PR_TRUE;
@ -2720,37 +2718,15 @@ nsTextFrame::IsTextInSelection(nsPresContext* aPresContext,
return isSelected;
}
NS_IMETHODIMP
nsTextFrame::IsVisibleForPainting(nsPresContext * aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aCheckVis,
PRBool* aIsVisible)
PRBool
nsTextFrame::IsVisibleInSelection(nsISelection* aSelection)
{
if (aCheckVis) {
if (!GetStyleVisibility()->IsVisible()) {
*aIsVisible = PR_FALSE;
return NS_OK;
}
}
// Start by assuming we are visible and need to be painted
PRBool isVisible = PR_TRUE;
if (aPresContext->IsPaginated()) {
if (aPresContext->IsRenderingOnlySelection()) {
// Check the quick way first
PRBool isSelected = (mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
if (isSelected) {
isVisible = IsTextInSelection(aPresContext, aRenderingContext);
} else {
isVisible = PR_FALSE;
}
}
}
*aIsVisible = isVisible;
return NS_OK;
// Check the quick way first
PRBool isSelected = (mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
if (!isSelected)
return PR_FALSE;
return IsTextInSelection();
}
void
@ -2772,7 +2748,6 @@ nsTextFrame::PaintUnicodeText(nsPresContext* aPresContext,
#endif
if (NS_FAILED(GetTextInfoForPainting(aPresContext,
aRenderingContext,
getter_AddRefs(shell),
getter_AddRefs(selCon),
displaySelection,
@ -2939,10 +2914,7 @@ nsTextFrame::PaintUnicodeText(nsPresContext* aPresContext,
//while we have substrings...
//PRBool drawn = PR_FALSE;
DrawSelectionIterator iter(details,
text,
(PRUint32)textLength,
aTextStyle,
DrawSelectionIterator iter(details, text, (PRUint32)textLength, &aTextStyle,
nsTextPaintStyle::eAllSelections);
if (!iter.IsDone() && iter.First())
{
@ -2958,7 +2930,6 @@ nsTextFrame::PaintUnicodeText(nsPresContext* aPresContext,
{
PRUnichar *currenttext = iter.CurrentTextUnicharPtr();
PRUint32 currentlength= iter.CurrentLength();
//nsTextStyle &currentStyle = iter.CurrentStyle();
nscolor currentFGColor, currentBKColor;
PRBool isCurrentBKColorTransparent;
@ -3513,7 +3484,6 @@ nsTextFrame::PaintTextSlowly(nsPresContext* aPresContext,
PRBool hideStandardSelection;
PRInt16 selectionValue;
if (NS_FAILED(GetTextInfoForPainting(aPresContext,
aRenderingContext,
getter_AddRefs(shell),
getter_AddRefs(selCon),
displaySelection,
@ -3630,10 +3600,7 @@ nsTextFrame::PaintTextSlowly(nsPresContext* aPresContext,
sdptr = sdptr->mNext;
}
DrawSelectionIterator iter(details,
text,
(PRUint32)textLength,
aTextStyle,
DrawSelectionIterator iter(details, text, (PRUint32)textLength, &aTextStyle,
nsTextPaintStyle::eAllSelections);
if (!iter.IsDone() && iter.First())
{
@ -3652,7 +3619,6 @@ nsTextFrame::PaintTextSlowly(nsPresContext* aPresContext,
{
PRUnichar *currenttext = iter.CurrentTextUnicharPtr();
PRUint32 currentlength= iter.CurrentLength();
//nsTextStyle &currentStyle = iter.CurrentStyle();
nscolor currentFGColor, currentBKColor;
PRBool isCurrentBKColorTransparent;
PRBool isSelection = iter.GetSelectionColors(&currentFGColor,
@ -3741,7 +3707,6 @@ nsTextFrame::PaintAsciiText(nsPresContext* aPresContext,
PRBool hideStandardSelection;
PRInt16 selectionValue;
if (NS_FAILED(GetTextInfoForPainting(aPresContext,
aRenderingContext,
getter_AddRefs(shell),
getter_AddRefs(selCon),
displaySelection,
@ -3884,10 +3849,8 @@ nsTextFrame::PaintAsciiText(nsPresContext* aPresContext,
if (!hideStandardSelection || displaySelection) {
//ITS OK TO CAST HERE THE RESULT WE USE WILLNOT DO BAD CONVERSION
DrawSelectionIterator iter(details,
(PRUnichar *)text,
(PRUint32)textLength,
aTextStyle,
DrawSelectionIterator iter(details, (PRUnichar *)text,
(PRUint32)textLength, &aTextStyle,
nsTextPaintStyle::eAllSelections);
// See if this rendering backend supports getting cluster
@ -3907,7 +3870,6 @@ nsTextFrame::PaintAsciiText(nsPresContext* aPresContext,
{
char *currenttext = iter.CurrentTextCStrPtr();
PRUint32 currentlength= iter.CurrentLength();
//nsTextStyle &currentStyle = iter.CurrentStyle();
nscolor currentFGColor, currentBKColor;
PRBool isCurrentBKColorTransparent;

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

@ -79,13 +79,22 @@ ViewportFrame::SetInitialChildList(nsPresContext* aPresContext,
return rv;
}
nsIFrame*
ViewportFrame::GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer)
NS_IMETHODIMP
ViewportFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
// this should act like a block, so we need to override
return GetFrameForPointUsing(aPoint, nsnull, aWhichLayer,
aWhichLayer == NS_FRAME_PAINT_LAYER_BACKGROUND);
// We don't need any special painting or event handling. We just need to
// mark our visible out-of-flow frames (i.e., the fixed position frames) so
// that display list construction is guaranteed to recurse into their
// ancestors.
MarkOutOfFlowChildrenForDisplayList(mFixedContainer.GetFirstChild(), aDirtyRect);
// Put the regular child in a pseudo-stack.
nsresult rv =
BuildDisplayListForNonBlockChildren(aBuilder, aDirtyRect, aLists,
DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT);
UnmarkOutOfFlowChildrenForDisplayList(mFixedContainer.GetFirstChild());
return rv;
}
NS_IMETHODIMP

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

@ -71,9 +71,6 @@ public:
nsIAtom* aListName,
nsIFrame* aChildList);
virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD AppendFrames(nsIAtom* aListName,
nsIFrame* aFrameList);
@ -88,13 +85,15 @@ public:
virtual nsIFrame* GetFirstChild(nsIAtom* aListName) const;
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
virtual PRBool CanPaintBackground() { return PR_FALSE; }
/**
* Get the "type" of the frame
*

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

@ -56,6 +56,7 @@ REQUIRES = xpcom \
content \
gfx \
widget \
view \
webshell \
locale \
intl \

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

@ -67,6 +67,7 @@
#include "nsIWindowWatcher.h"
#include "nsIStringBundle.h"
#include "nsDoubleHashtable.h"
#include "nsDisplayList.h"
#include "nsMathMLOperators.h"
#include "nsMathMLChar.h"
@ -1937,13 +1938,116 @@ nsMathMLChar::ComposeChildren(nsPresContext* aPresContext,
return NS_OK;
}
class nsDisplayMathMLSelectionRect : public nsDisplayItem {
public:
nsDisplayMathMLSelectionRect(nsIFrame* aFrame, const nsRect& aRect)
: mFrame(aFrame), mRect(aRect) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("MathMLSelectionRect")
private:
nsIFrame* mFrame;
nsRect mRect;
};
void nsDisplayMathMLSelectionRect::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
{
// get color to use for selection from the look&feel object
nscolor bgColor = NS_RGB(0, 0, 0);
mFrame->GetPresContext()->LookAndFeel()->
GetColor(nsILookAndFeel::eColor_TextSelectBackground, bgColor);
aCtx->SetColor(bgColor);
aCtx->FillRect(mRect + aBuilder->ToReferenceFrame(mFrame));
}
class nsDisplayMathMLCharBackground : public nsDisplayItem {
public:
nsDisplayMathMLCharBackground(nsIFrame* aFrame, const nsRect& aRect,
nsStyleContext* aStyleContext)
: mFrame(aFrame), mStyleContext(aStyleContext), mRect(aRect) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("MathMLCharBackground")
private:
nsIFrame* mFrame;
nsStyleContext* mStyleContext;
nsRect mRect;
};
void nsDisplayMathMLCharBackground::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
{
const nsStyleBorder* border = mStyleContext->GetStyleBorder();
const nsStylePadding* padding = mStyleContext->GetStylePadding();
const nsStyleBackground* backg = mStyleContext->GetStyleBackground();
nsCSSRendering::PaintBackgroundWithSC(mFrame->GetPresContext(), *aCtx, mFrame,
aDirtyRect,
mRect + aBuilder->ToReferenceFrame(mFrame),
*backg, *border, *padding,
PR_TRUE);
}
class nsDisplayMathMLCharForeground : public nsDisplayItem {
public:
nsDisplayMathMLCharForeground(nsIFrame* aFrame, nsMathMLChar* aChar, PRBool aIsSelected)
: mFrame(aFrame), mChar(aChar), mIsSelected(aIsSelected) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("MathMLCharForeground")
private:
nsIFrame* mFrame;
nsMathMLChar* mChar;
PRPackedBool mIsSelected;
};
void nsDisplayMathMLCharForeground::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
{
mChar->PaintForeground(mFrame->GetPresContext(), *aCtx,
aBuilder->ToReferenceFrame(mFrame), mIsSelected);
}
#ifdef NS_DEBUG
class nsDisplayMathMLCharDebug : public nsDisplayItem {
public:
nsDisplayMathMLCharDebug(nsIFrame* aFrame, const nsRect& aRect)
: mFrame(aFrame), mRect(aRect) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("MathMLCharDebug")
private:
nsIFrame* mFrame;
nsRect mRect;
};
void nsDisplayMathMLCharDebug::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
{
// for visual debug
PRIntn skipSides = 0;
nsPresContext* presContext = mFrame->GetPresContext();
const nsStyleBorder* border = mFrame->GetStyleBorder();
nsStyleContext* styleContext = mFrame->GetStyleContext();
nsRect rect = mRect + aBuilder->ToReferenceFrame(mFrame);
nsCSSRendering::PaintBorder(presContext, *aCtx, mFrame,
aDirtyRect, rect, *border, styleContext, skipSides);
nsCSSRendering::PaintOutline(presContext, *aCtx, mFrame,
aDirtyRect, rect, *border,
*mFrame->GetStyleOutline(), styleContext, 0);
}
#endif
nsresult
nsMathMLChar::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
nsIFrame* aForFrame,
const nsRect* aSelectedRect)
nsMathMLChar::Display(nsDisplayListBuilder* aBuilder,
nsIFrame* aForFrame,
const nsDisplayListSet& aLists,
const nsRect* aSelectedRect)
{
nsresult rv = NS_OK;
nsStyleContext* parentContext = mStyleContext->GetParent();
@ -1961,101 +2065,112 @@ nsMathMLChar::Paint(nsPresContext* aPresContext,
// if the leaf style context that we use for stretchy chars has a background
// color we use it -- this feature is mostly used for testing and debugging
// purposes. Normally, users will set the background on the container frame.
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
// paint the selection background -- beware MathML frames overlap a lot
if (aSelectedRect && !aSelectedRect->IsEmpty()) {
// get color to use for selection from the look&feel object
nscolor bgColor = NS_RGB(0, 0, 0);
aPresContext->LookAndFeel()->
GetColor(nsILookAndFeel::eColor_TextSelectBackground, bgColor);
aRenderingContext.SetColor(bgColor);
aRenderingContext.FillRect(*aSelectedRect);
// paint the selection background -- beware MathML frames overlap a lot
if (aSelectedRect && !aSelectedRect->IsEmpty()) {
rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayMathMLSelectionRect(aForFrame, *aSelectedRect));
NS_ENSURE_SUCCESS(rv, rv);
}
else if (mRect.width && mRect.height) {
const nsStyleBackground* backg = styleContext->GetStyleBackground();
if (styleContext != parentContext &&
0 == (backg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT)) {
rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
nsDisplayMathMLCharBackground(aForFrame, mRect, styleContext));
NS_ENSURE_SUCCESS(rv, rv);
}
else if (mRect.width && mRect.height) {
const nsStyleBorder* border = styleContext->GetStyleBorder();
const nsStylePadding* padding = styleContext->GetStylePadding();
const nsStyleBackground* backg = styleContext->GetStyleBackground();
nsRect rect(mRect); //0, 0, mRect.width, mRect.height);
if (styleContext != parentContext &&
0 == (backg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT))
nsCSSRendering::PaintBackgroundWithSC(aPresContext, aRenderingContext, aForFrame,
aDirtyRect, rect, *backg, *border, *padding,
PR_TRUE);
//else
// our container frame will take care of painting its background
// nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame,
// aDirtyRect, rect, *border, *padding, PR_TRUE);
//else
// our container frame will take care of painting its background
// nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, aForFrame,
// aDirtyRect, rect, *border, *padding, PR_TRUE);
#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
// for visual debug
PRIntn skipSides = 0; //aForFrame->GetSkipSides();
const nsStyleOutline* outline = styleContext->GetStyleOutline();
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, aForFrame,
aDirtyRect, rect, *border, styleContext, skipSides);
nsCSSRendering::PaintOutline(aPresContext, aRenderingContext, aForFrame,
aDirtyRect, rect, *border, *outline, styleContext, 0);
// for visual debug
rv = aLists.BorderBackground()->AppendToTop(new (aBuilder)
nsDisplayMathMLCharDebug(aForFrame, mRect));
NS_ENSURE_SUCCESS(rv, rv);
#endif
}
}
return aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayMathMLCharForeground(aForFrame, this,
aSelectedRect && !aSelectedRect->IsEmpty()));
}
void
nsMathMLChar::PaintForeground(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsPoint aPt,
PRBool aIsSelected)
{
nsStyleContext* parentContext = mStyleContext->GetParent();
nsStyleContext* styleContext = mStyleContext;
if (NS_STRETCH_DIRECTION_UNSUPPORTED == mDirection) {
// normal drawing if there is nothing special about this char
// Set default context to the parent context
styleContext = parentContext;
}
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
// Set color ...
nscolor fgColor = styleContext->GetStyleColor()->mColor;
if (aSelectedRect && !aSelectedRect->IsEmpty()) {
// get color to use for selection from the look&feel object
aPresContext->LookAndFeel()->
GetColor(nsILookAndFeel::eColor_TextSelectForeground, fgColor);
// Set color ...
nscolor fgColor = styleContext->GetStyleColor()->mColor;
if (aIsSelected) {
// get color to use for selection from the look&feel object
aPresContext->LookAndFeel()->
GetColor(nsILookAndFeel::eColor_TextSelectForeground, fgColor);
}
aRenderingContext.SetColor(fgColor);
nsAutoString fontName;
nsFont theFont(styleContext->GetStyleFont()->mFont);
if (NS_STRETCH_DIRECTION_UNSUPPORTED == mDirection) {
// normal drawing if there is nothing special about this char ...
// Set the default font and grab some metrics to adjust the placements ...
PRUint32 len = PRUint32(mData.Length());
if (1 == len) {
SetBaseFamily(mData[0], theFont);
}
aRenderingContext.SetColor(fgColor);
nsAutoString fontName;
nsFont theFont(styleContext->GetStyleFont()->mFont);
if (NS_STRETCH_DIRECTION_UNSUPPORTED == mDirection) {
// normal drawing if there is nothing special about this char ...
// Set the default font and grab some metrics to adjust the placements ...
PRUint32 len = PRUint32(mData.Length());
if (1 == len) {
SetBaseFamily(mData[0], theFont);
}
aRenderingContext.SetFont(theFont, nsnull);
aRenderingContext.SetFont(theFont, nsnull);
//printf("Painting %04X like a normal char\n", mData[0]);
//aRenderingContext.SetColor(NS_RGB(255,0,0));
aRenderingContext.DrawString(mData.get(), len, mRect.x, mRect.y + mBoundingMetrics.ascent);
}
else {
// Set the stretchy font and grab some metrics to adjust the placements ...
mGlyphTable->GetPrimaryFontName(fontName);
SetFirstFamily(theFont, fontName);
aRenderingContext.SetFont(theFont, nsnull);
// if there is a glyph of appropriate size, paint that glyph
if (mGlyph) {
aRenderingContext.DrawString(mData.get(), len, mRect.x + aPt.x,
mRect.y + aPt.y + mBoundingMetrics.ascent);
}
else {
// Set the stretchy font and grab some metrics to adjust the placements ...
mGlyphTable->GetPrimaryFontName(fontName);
SetFirstFamily(theFont, fontName);
aRenderingContext.SetFont(theFont, nsnull);
// if there is a glyph of appropriate size, paint that glyph
if (mGlyph) {
//printf("Painting %04X with a glyph of appropriate size\n", mData[0]);
//aRenderingContext.SetColor(NS_RGB(0,0,255));
mGlyphTable->DrawGlyph(aRenderingContext, theFont, mGlyph,
mRect.x, mRect.y + mBoundingMetrics.ascent);
}
else { // paint by parts
// see if this is a composite char and let children paint themselves
if (!mParent && mSibling) { // only a "root" having child chars can enter here
for (nsMathMLChar* child = mSibling; child; child = child->mSibling) {
mGlyphTable->DrawGlyph(aRenderingContext, theFont, mGlyph,
mRect.x + aPt.x,
mRect.y + aPt.y + mBoundingMetrics.ascent);
}
else { // paint by parts
// see if this is a composite char and let children paint themselves
if (!mParent && mSibling) { // only a "root" having child chars can enter here
for (nsMathMLChar* child = mSibling; child; child = child->mSibling) {
//if (!mStyleContext->Equals(child->mStyleContext))
// printf("char contexts are out of sync\n");
child->Paint(aPresContext, aRenderingContext,
aDirtyRect, aWhichLayer, aForFrame, aSelectedRect);
}
return NS_OK; // that's all folks
child->PaintForeground(aPresContext, aRenderingContext, aPt,
aIsSelected);
}
return; // that's all folks
}
//aRenderingContext.SetColor(NS_RGB(0,255,0));
if (NS_STRETCH_DIRECTION_VERTICAL == mDirection)
rv = PaintVertically(aPresContext, aRenderingContext, theFont, styleContext,
mGlyphTable, this, mRect);
else if (NS_STRETCH_DIRECTION_HORIZONTAL == mDirection)
rv = PaintHorizontally(aPresContext, aRenderingContext, theFont, styleContext,
mGlyphTable, this, mRect);
}
nsRect r = mRect + aPt;
if (NS_STRETCH_DIRECTION_VERTICAL == mDirection)
PaintVertically(aPresContext, aRenderingContext, theFont, styleContext,
mGlyphTable, this, r);
else if (NS_STRETCH_DIRECTION_HORIZONTAL == mDirection)
PaintHorizontally(aPresContext, aRenderingContext, theFont, styleContext,
mGlyphTable, this, r);
}
}
return rv;
}
/* =================================================================================

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

@ -99,12 +99,15 @@ public:
}
nsresult
Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
nsIFrame* aForFrame,
const nsRect* aSelectedRect = nsnull);
Display(nsDisplayListBuilder* aBuilder,
nsIFrame* aForFrame,
const nsDisplayListSet& aLists,
const nsRect* aSelectedRect = nsnull);
void PaintForeground(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsPoint aPt,
PRBool aIsSelected);
// This is the method called to ask the char to stretch itself.
// @param aContainerSize - IN - suggested size for the stretched char

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

@ -63,6 +63,7 @@
#include "nsMathMLContainerFrame.h"
#include "nsAutoPtr.h"
#include "nsStyleSet.h"
#include "nsDisplayList.h"
#include "nsCSSFrameConstructor.h"
NS_DEFINE_CID(kInlineFrameCID, NS_INLINE_FRAME_CID);
@ -125,32 +126,36 @@ nsMathMLContainerFrame::ReflowError(nsIRenderingContext& aRenderingContext,
return NS_OK;
}
nsresult
nsMathMLContainerFrame::PaintError(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
class nsDisplayMathMLError : public nsDisplayItem {
public:
nsDisplayMathMLError(nsIFrame* aFrame)
: mFrame(aFrame) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("MathMLError")
private:
nsIFrame* mFrame;
};
void nsDisplayMathMLError::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
{
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
NS_ASSERTION(NS_MATHML_HAS_ERROR(mPresentationData.flags),
"There is nothing wrong with this frame!");
// Set color and font ...
aRenderingContext.SetFont(GetStyleFont()->mFont, nsnull);
// Set color and font ...
aCtx->SetFont(mFrame->GetStyleFont()->mFont, nsnull);
aRenderingContext.SetColor(NS_RGB(255,0,0));
aRenderingContext.FillRect(0, 0, mRect.width, mRect.height);
aRenderingContext.SetColor(NS_RGB(255,255,255));
nsPoint pt = aBuilder->ToReferenceFrame(mFrame);
aCtx->SetColor(NS_RGB(255,0,0));
aCtx->FillRect(nsRect(pt, mFrame->GetSize()));
aCtx->SetColor(NS_RGB(255,255,255));
nscoord ascent;
nsCOMPtr<nsIFontMetrics> fm;
aRenderingContext.GetFontMetrics(*getter_AddRefs(fm));
fm->GetMaxAscent(ascent);
nscoord ascent;
nsCOMPtr<nsIFontMetrics> fm;
aCtx->GetFontMetrics(*getter_AddRefs(fm));
fm->GetMaxAscent(ascent);
nsAutoString errorMsg; errorMsg.AssignLiteral("invalid-markup");
aRenderingContext.DrawString(errorMsg.get(),
PRUint32(errorMsg.Length()),
0, ascent);
}
return NS_OK;
nsAutoString errorMsg; errorMsg.AssignLiteral("invalid-markup");
aCtx->DrawString(errorMsg.get(), PRUint32(errorMsg.Length()), pt.x, pt.y+ascent);
}
/* /////////////
@ -702,28 +707,23 @@ nsMathMLContainerFrame::PropagateScriptStyleFor(nsIFrame* aFrame,
NS_IMETHODIMP
nsMathMLContainerFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
nsMathMLContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
if (NS_FRAME_IS_UNFLOWABLE & mState) {
return NS_OK;
}
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
// report an error if something wrong was found in this frame
if (NS_MATHML_HAS_ERROR(mPresentationData.flags)) {
return PaintError(aRenderingContext, aDirtyRect, aWhichLayer);
// XXX this has no visibility check ... dunno if that's right or not
// REVIEW: That is an existing issue
rv = aLists.Content()->AppendNewToTop(new (aBuilder) nsDisplayMathMLError(this));
NS_ENSURE_SUCCESS(rv, rv);
}
// Paint inline element backgrounds in the foreground layer (bug 36710).
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
PaintSelf(aPresContext, aRenderingContext, aDirtyRect);
}
PaintDecorationsAndChildren(aPresContext, aRenderingContext, aDirtyRect,
aWhichLayer, PR_FALSE, aFlags);
rv = DisplayTextDecorationsAndChildren(aBuilder, aDirtyRect, aLists);
NS_ENSURE_SUCCESS(rv, rv);
#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
// for visual debug
@ -732,21 +732,9 @@ nsMathMLContainerFrame::Paint(nsPresContext* aPresContext,
// your mBoundingMetrics and mReference point, and set
// mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS
// in the Init() of your sub-class
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer &&
NS_MATHML_PAINT_BOUNDING_METRICS(mPresentationData.flags))
{
aRenderingContext.SetColor(NS_RGB(0,0,255));
nscoord x = mReference.x + mBoundingMetrics.leftBearing;
nscoord y = mReference.y - mBoundingMetrics.ascent;
nscoord w = mBoundingMetrics.rightBearing - mBoundingMetrics.leftBearing;
nscoord h = mBoundingMetrics.ascent + mBoundingMetrics.descent;
aRenderingContext.DrawRect(x,y,w,h);
}
rv = DisplayBoundingMetrics(aBuilder, this, mReference, mBoundingMetrics, aLists);
#endif
return NS_OK;
return rv;
}
// This method is called in a top-down manner, as we descend the frame tree

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

@ -163,12 +163,9 @@ public:
return nsHTMLContainerFrame::DidReflow(aPresContext, aReflowState, aStatus);
}
NS_IMETHOD
Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
// Notification when an attribute is changed. The MathML module uses the
// following paradigm:
@ -213,10 +210,6 @@ public:
virtual nsresult
ReflowError(nsIRenderingContext& aRenderingContext,
nsHTMLReflowMetrics& aDesiredSize);
virtual nsresult
PaintError(nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
// helper method to reflow a child frame. We are inline frames, and we don't
// know our positions until reflow is finished. That's why we ask the

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

@ -57,7 +57,9 @@
#include "nsAutoPtr.h"
#include "nsStyleSet.h"
#include "nsStyleUtil.h"
#include "nsDisplayList.h"
#include "nsAttrName.h"
static NS_DEFINE_CID(kCSSStyleSheetCID, NS_CSS_STYLESHEET_CID);
@ -724,3 +726,74 @@ nsMathMLFrame::MapAttributesIntoCSS(nsPresContext* aPresContext,
return ruleCount;
}
#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
class nsDisplayMathMLBoundingMetrics : public nsDisplayItem {
public:
nsDisplayMathMLBoundingMetrics(nsIFrame* aFrame, const nsRect& aRect)
: mFrame(aFrame), mRect(aRect) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("MathMLBoundingMetrics")
private:
nsIFrame* mFrame;
nsRect mRect;
};
void nsDisplayMathMLBoundingMetrics::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
{
aCtx->SetColor(NS_RGB(0,0,255));
aCtx->DrawRect(mRect + aBuilder->ToReferenceFrame(mFrame));
}
nsresult
nsMathMLFrame::DisplayBoundingMetrics(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, const nsPoint& aPt,
const nsBoundingMetrics& aMetrics,
const nsDisplayListSet& aLists) {
if (!NS_MATHML_PAINT_BOUNDING_METRICS(mPresentationData.flags))
return NS_OK;
nscoord x = aPt.x + aMetrics.leftBearing;
nscoord y = aPt.y - aMetrics.ascent;
nscoord w = aMetrics.rightBearing - aMetrics.leftBearing;
nscoord h = aMetrics.ascent + aMetrics.descent;
return aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayMathMLBoundingMetrics(this, nsRect(x,y,w,h)));
}
#endif
class nsDisplayMathMLBar : public nsDisplayItem {
public:
nsDisplayMathMLBar(nsIFrame* aFrame, const nsRect& aRect)
: mFrame(aFrame), mRect(aRect) {}
virtual nsIFrame* GetUnderlyingFrame() { return mFrame; }
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
const nsRect& aDirtyRect);
NS_DISPLAY_DECL_NAME("MathMLBar")
private:
nsIFrame* mFrame;
nsRect mRect;
};
void nsDisplayMathMLBar::Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
{
// paint the bar with the current text color
aCtx->SetColor(mFrame->GetStyleColor()->mColor);
aCtx->FillRect(mRect + aBuilder->ToReferenceFrame(mFrame));
}
nsresult
nsMathMLFrame::DisplayBar(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, const nsRect& aRect,
const nsDisplayListSet& aLists) {
if (!aFrame->GetStyleVisibility()->IsVisible() || aRect.IsEmpty())
return NS_OK;
return aLists.Content()->AppendNewToTop(new (aBuilder)
nsDisplayMathMLBar(aFrame, aRect));
}

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

@ -424,6 +424,21 @@ public:
nsIFrame* aFrame);
protected:
#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
nsresult DisplayBoundingMetrics(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, const nsPoint& aPt,
const nsBoundingMetrics& aMetrics,
const nsDisplayListSet& aLists);
#endif
/**
* Display a solid rectangle in the frame's text color. Used for drawing
* fraction separators and root/sqrt overbars.
*/
nsresult DisplayBar(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, const nsRect& aRect,
const nsDisplayListSet& aLists);
// information about the presentation policy of the frame
nsPresentationData mPresentationData;

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

@ -61,6 +61,7 @@
#include "nsMathMLmactionFrame.h"
#include "nsAutoPtr.h"
#include "nsStyleSet.h"
#include "nsDisplayList.h"
//
// <maction> -- bind actions to a subexpression - implementation
@ -252,49 +253,29 @@ nsMathMLmactionFrame::SetInitialChildList(nsPresContext* aPresContext,
return rv;
}
// Return the selected frame ...
nsIFrame*
nsMathMLmactionFrame::GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer)
{
nsIFrame* childFrame = GetSelectedFrame();
if (childFrame)
return childFrame->GetFrameForPoint(aPoint - childFrame->GetOffsetTo(this),
aWhichLayer);
return nsFrame::GetFrameForPoint(aPoint, aWhichLayer);
}
// Only paint the selected child...
NS_IMETHODIMP
nsMathMLmactionFrame::Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags)
nsMathMLmactionFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
PaintSelf(aPresContext, aRenderingContext, aDirtyRect);
}
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
nsIFrame* childFrame = GetSelectedFrame();
if (childFrame)
PaintChild(aPresContext, aRenderingContext, aDirtyRect, childFrame, aWhichLayer);
if (childFrame) {
// Put the child's background directly onto the content list
nsDisplayListSet set(aLists, aLists.Content());
// The children should be in content order
rv = BuildDisplayListForChild(aBuilder, childFrame, aDirtyRect, set);
NS_ENSURE_SUCCESS(rv, rv);
}
#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
// visual debug
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer &&
NS_MATHML_PAINT_BOUNDING_METRICS(mPresentationData.flags)) {
aRenderingContext.SetColor(NS_RGB(0,0,255));
nscoord x = mReference.x + mBoundingMetrics.leftBearing;
nscoord y = mReference.y - mBoundingMetrics.ascent;
nscoord w = mBoundingMetrics.rightBearing - mBoundingMetrics.leftBearing;
nscoord h = mBoundingMetrics.ascent + mBoundingMetrics.descent;
aRenderingContext.DrawRect(x,y,w,h);
}
rv = DisplayBoundingMetrics(aBuilder, this, mReference, mBoundingMetrics, aLists);
#endif
return NS_OK;
return rv;
}
// Only reflow the selected child ...

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

@ -75,15 +75,9 @@ public:
virtual nsresult
ChildListChanged(PRInt32 aModType);
virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD
Paint(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer,
PRUint32 aFlags = 0);
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
NS_IMETHOD
Place(nsIRenderingContext& aRenderingContext,

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше