PRUint16 nsSVGPathGeometryFrame::GetHittestMask() { PRUint16 mask = 0; switch(GetStyleVisibility()->mPointerEvents) { case NS_STYLE_POINTER_EVENTS_NONE: break; case NS_STYLE_POINTER_EVENTS_VISIBLEPAINTED: case NS_STYLE_POINTER_EVENTS_AUTO: if (GetStyleVisibility()->IsVisible()) { if (GetStyleSVG()->mFill.mType != eStyleSVGPaintType_None) mask |= HITTEST_MASK_FILL; if (GetStyleSVG()->mStroke.mType != eStyleSVGPaintType_None) mask |= HITTEST_MASK_STROKE; } break; case NS_STYLE_POINTER_EVENTS_VISIBLEFILL: if (GetStyleVisibility()->IsVisible()) { mask |= HITTEST_MASK_FILL | HITTEST_MASK_FORCE_TEST; } break; case NS_STYLE_POINTER_EVENTS_VISIBLESTROKE: if (GetStyleVisibility()->IsVisible()) { mask |= HITTEST_MASK_STROKE | HITTEST_MASK_FORCE_TEST; } break; case NS_STYLE_POINTER_EVENTS_VISIBLE: if (GetStyleVisibility()->IsVisible()) { mask |= HITTEST_MASK_FILL | HITTEST_MASK_STROKE | HITTEST_MASK_FORCE_TEST; } break; case NS_STYLE_POINTER_EVENTS_PAINTED: if (GetStyleSVG()->mFill.mType != eStyleSVGPaintType_None) mask |= HITTEST_MASK_FILL; if (GetStyleSVG()->mStroke.mType != eStyleSVGPaintType_None) mask |= HITTEST_MASK_STROKE; break; case NS_STYLE_POINTER_EVENTS_FILL: mask |= HITTEST_MASK_FILL | HITTEST_MASK_FORCE_TEST; break; case NS_STYLE_POINTER_EVENTS_STROKE: mask |= HITTEST_MASK_STROKE | HITTEST_MASK_FORCE_TEST; break; case NS_STYLE_POINTER_EVENTS_ALL: mask |= HITTEST_MASK_FILL | HITTEST_MASK_STROKE | HITTEST_MASK_FORCE_TEST; break; default: NS_ERROR("not reached"); break; } return mask; }
PRUint16 nsSVGGeometryFrame::GetHitTestFlags() { PRUint16 flags = 0; switch(GetStyleVisibility()->mPointerEvents) { case NS_STYLE_POINTER_EVENTS_NONE: break; case NS_STYLE_POINTER_EVENTS_AUTO: case NS_STYLE_POINTER_EVENTS_VISIBLEPAINTED: if (GetStyleVisibility()->IsVisible()) { if (GetStyleSVG()->mFill.mType != eStyleSVGPaintType_None) flags |= SVG_HIT_TEST_FILL; if (GetStyleSVG()->mStroke.mType != eStyleSVGPaintType_None) flags |= SVG_HIT_TEST_STROKE; if (GetStyleSVG()->mStrokeOpacity > 0) flags |= SVG_HIT_TEST_CHECK_MRECT; } break; case NS_STYLE_POINTER_EVENTS_VISIBLEFILL: if (GetStyleVisibility()->IsVisible()) { flags |= SVG_HIT_TEST_FILL; } break; case NS_STYLE_POINTER_EVENTS_VISIBLESTROKE: if (GetStyleVisibility()->IsVisible()) { flags |= SVG_HIT_TEST_STROKE; } break; case NS_STYLE_POINTER_EVENTS_VISIBLE: if (GetStyleVisibility()->IsVisible()) { flags |= SVG_HIT_TEST_FILL | SVG_HIT_TEST_STROKE; } break; case NS_STYLE_POINTER_EVENTS_PAINTED: if (GetStyleSVG()->mFill.mType != eStyleSVGPaintType_None) flags |= SVG_HIT_TEST_FILL; if (GetStyleSVG()->mStroke.mType != eStyleSVGPaintType_None) flags |= SVG_HIT_TEST_STROKE; if (GetStyleSVG()->mStrokeOpacity) flags |= SVG_HIT_TEST_CHECK_MRECT; break; case NS_STYLE_POINTER_EVENTS_FILL: flags |= SVG_HIT_TEST_FILL; break; case NS_STYLE_POINTER_EVENTS_STROKE: flags |= SVG_HIT_TEST_STROKE; break; case NS_STYLE_POINTER_EVENTS_ALL: flags |= SVG_HIT_TEST_FILL | SVG_HIT_TEST_STROKE; break; default: NS_ERROR("not reached"); break; } return flags; }
nsRect nsTextBoxFrame::CalcTextRect(nsIRenderingContext &aRenderingContext, const nsPoint &aTextOrigin) { nsRect textRect(aTextOrigin, GetSize()); nsMargin borderPadding; GetBorderAndPadding(borderPadding); textRect.Deflate(borderPadding); // determine (cropped) title and underline position nsPresContext* presContext = PresContext(); LayoutTitle(presContext, aRenderingContext, textRect); // make the rect as small as our (cropped) text. nscoord outerWidth = textRect.width; textRect.width = mTitleWidth; // Align our text within the overall rect by checking our text-align property. const nsStyleVisibility* vis = GetStyleVisibility(); const nsStyleText* textStyle = GetStyleText(); if (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_CENTER) textRect.x += (outerWidth - textRect.width)/2; else if (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_RIGHT || (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_DEFAULT && vis->mDirection == NS_STYLE_DIRECTION_RTL) || (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_END && vis->mDirection == NS_STYLE_DIRECTION_LTR)) { textRect.x += (outerWidth - textRect.width); } return textRect; }
/* returns a Direction struct containing the horizontal and vertical direction */ nsResizerFrame::Direction nsResizerFrame::GetDirection() { static const nsIContent::AttrValuesArray strings[] = {&nsGkAtoms::topleft, &nsGkAtoms::top, &nsGkAtoms::topright, &nsGkAtoms::left, &nsGkAtoms::right, &nsGkAtoms::bottomleft, &nsGkAtoms::bottom, &nsGkAtoms::bottomright, &nsGkAtoms::bottomend, nsnull}; static const Direction directions[] = {{-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 1} }; if (!GetContent()) return directions[0]; // default: topleft PRInt32 index = GetContent()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::dir, strings, eCaseMatters); if(index < 0) return directions[0]; // default: topleft else if (index >= 8 && GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) { // Directions 8 and higher are RTL-aware directions and should reverse the // horizontal component if RTL. Direction direction = directions[index]; direction.mHorizontal *= -1; return direction; } return directions[index]; }
NS_METHOD nsTableColFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsTableColFrame", aReflowState.reason); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); aDesiredSize.width=0; aDesiredSize.height=0; const nsStyleVisibility* colVis = GetStyleVisibility(); PRBool collapseCol = (NS_STYLE_VISIBILITY_COLLAPSE == colVis->mVisible); if (collapseCol) { nsTableFrame* tableFrame = nsnull; nsTableFrame::GetTableFrame(this, tableFrame); if (tableFrame) { tableFrame->SetNeedToCollapseColumns(PR_TRUE); } } if (aDesiredSize.mComputeMEW) { aDesiredSize.mMaxElementWidth=0; } aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; }
void nsMeterFrame::ReflowBarFrame(nsIFrame* aBarFrame, nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { bool vertical = GetStyleDisplay()->mOrient == NS_STYLE_ORIENT_VERTICAL; nsHTMLReflowState reflowState(aPresContext, aReflowState, aBarFrame, nsSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE)); nscoord size = vertical ? aReflowState.ComputedHeight() : aReflowState.ComputedWidth(); nscoord xoffset = aReflowState.mComputedBorderPadding.left; nscoord yoffset = aReflowState.mComputedBorderPadding.top; // NOTE: Introduce a new function getPosition in the content part ? double position, max, min, value; nsCOMPtr<nsIDOMHTMLMeterElement> meterElement = do_QueryInterface(mContent); meterElement->GetMax(&max); meterElement->GetMin(&min); meterElement->GetValue(&value); position = max - min; position = position != 0 ? (value - min) / position : 1; size = NSToCoordRound(size * position); if (!vertical && GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) { xoffset += aReflowState.ComputedWidth() - size; } // The bar position is *always* constrained. if (vertical) { // We want the bar to begin at the bottom. yoffset += aReflowState.ComputedHeight() - size; size -= reflowState.mComputedMargin.TopBottom() + reflowState.mComputedBorderPadding.TopBottom(); size = std::max(size, 0); reflowState.SetComputedHeight(size); } else { size -= reflowState.mComputedMargin.LeftRight() + reflowState.mComputedBorderPadding.LeftRight(); size = std::max(size, 0); reflowState.SetComputedWidth(size); } xoffset += reflowState.mComputedMargin.left; yoffset += reflowState.mComputedMargin.top; nsHTMLReflowMetrics barDesiredSize; ReflowChild(aBarFrame, aPresContext, barDesiredSize, reflowState, xoffset, yoffset, 0, aStatus); FinishReflowChild(aBarFrame, aPresContext, &reflowState, barDesiredSize, xoffset, yoffset, 0); }
void nsHTMLContainerFrame::PaintDecorationsAndChildren( nsPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer, PRBool aIsBlock, PRUint32 aFlags) { // 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; 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); } } PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, aFlags); if (decorations & NS_STYLE_TEXT_DECORATION_LINE_THROUGH) { PaintTextDecorations(aRenderingContext, fm, NS_STYLE_TEXT_DECORATION_LINE_THROUGH, strikeColor); } }
PRIntn nsInlineFrame::GetSkipSides() const { PRIntn skip = 0; if (!IsLeftMost()) { nsInlineFrame* prev = (nsInlineFrame*) GetPrevContinuation(); if ((GetStateBits() & NS_INLINE_FRAME_BIDI_VISUAL_STATE_IS_SET) || (prev && (prev->mRect.height || prev->mRect.width))) { // Prev continuation is not empty therefore we don't render our left // border edge. skip |= 1 << NS_SIDE_LEFT; } else { // If the prev continuation is empty, then go ahead and let our left // edge border render. } } if (!IsRightMost()) { nsInlineFrame* next = (nsInlineFrame*) GetNextContinuation(); if ((GetStateBits() & NS_INLINE_FRAME_BIDI_VISUAL_STATE_IS_SET) || (next && (next->mRect.height || next->mRect.width))) { // Next continuation is not empty therefore we don't render our right // border edge. skip |= 1 << NS_SIDE_RIGHT; } else { // If the next continuation is empty, then go ahead and let our right // edge border render. } } if (GetStateBits() & NS_FRAME_IS_SPECIAL) { // All but the last part of an {ib} split should skip the "end" side (as // determined by this frame's direction) and all but the first part of such // a split should skip the "start" side. But figuring out which part of // the split we are involves getting our first continuation, which might be // expensive. So don't bother if we already have the relevant bits set. PRBool ltr = (NS_STYLE_DIRECTION_LTR == GetStyleVisibility()->mDirection); PRIntn startBit = (1 << (ltr ? NS_SIDE_LEFT : NS_SIDE_RIGHT)); PRIntn endBit = (1 << (ltr ? NS_SIDE_RIGHT : NS_SIDE_LEFT)); if (((startBit | endBit) & skip) != (startBit | endBit)) { // We're missing one of the skip bits, so check whether we need to set it. // Only get the first continuation once, as an optimization. nsIFrame* firstContinuation = GetFirstContinuation(); if (nsLayoutUtils::FrameIsNonLastInIBSplit(firstContinuation)) { skip |= endBit; } if (nsLayoutUtils::FrameIsNonFirstInIBSplit(firstContinuation)) { skip |= startBit; } } } return skip; }
/* virtual */ PRBool nsInlineFrame::IsSelfEmpty() { #if 0 // I used to think inline frames worked this way, but it seems they // don't. At least not in our codebase. if (GetPresContext()->CompatibilityMode() == eCompatibility_FullStandards) { return PR_FALSE; } #endif const nsStyleMargin* margin = GetStyleMargin(); const nsStyleBorder* border = GetStyleBorder(); const nsStylePadding* padding = GetStylePadding(); // XXX Top and bottom removed, since they shouldn't affect things, but this // doesn't really match with nsLineLayout.cpp's setting of // ZeroEffectiveSpanBox, anymore, so what should this really be? PRBool haveRight = border->GetActualBorderWidth(NS_SIDE_RIGHT) != 0 || !IsPaddingZero(padding->mPadding.GetRightUnit(), padding->mPadding.GetRight()) || !IsMarginZero(margin->mMargin.GetRightUnit(), margin->mMargin.GetRight()); PRBool haveLeft = border->GetActualBorderWidth(NS_SIDE_LEFT) != 0 || !IsPaddingZero(padding->mPadding.GetLeftUnit(), padding->mPadding.GetLeft()) || !IsMarginZero(margin->mMargin.GetLeftUnit(), margin->mMargin.GetLeft()); if (haveLeft || haveRight) { if (GetStateBits() & NS_FRAME_IS_SPECIAL) { PRBool haveStart, haveEnd; if (NS_STYLE_DIRECTION_LTR == GetStyleVisibility()->mDirection) { haveStart = haveLeft; haveEnd = haveRight; } else { haveStart = haveRight; haveEnd = haveLeft; } // For special frames, ignore things we know we'll skip in GetSkipSides. // XXXbz should we be doing this for non-special frames too, in a more // general way? // Get the first continuation eagerly, as a performance optimization, to // avoid having to get it twice.. nsIFrame* firstCont = GetFirstContinuation(); return (!haveStart || nsLayoutUtils::FrameIsInLastPartOfIBSplit(firstCont)) && (!haveEnd || nsLayoutUtils::FrameIsInFirstPartOfIBSplit(firstCont)); } return PR_FALSE; } return PR_TRUE; }
NS_IMETHODIMP nsDeckFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { // if a tab is hidden all its children are too. if (!GetStyleVisibility()->mVisible) return NS_OK; // REVIEW: The old code skipped painting of background/borders/outline for this // frame and painting of debug boxes ... I've put it back. return nsBoxFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists); }
void nsProgressFrame::ReflowBarFrame(nsIFrame* aBarFrame, nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { nsHTMLReflowState reflowState(aPresContext, aReflowState, aBarFrame, nsSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE)); nscoord width = aReflowState.ComputedWidth(); nscoord xoffset = aReflowState.mComputedBorderPadding.left; nscoord yoffset = aReflowState.mComputedBorderPadding.top; double position; nsCOMPtr<nsIDOMHTMLProgressElement> progressElement = do_QueryInterface(mContent); progressElement->GetPosition(&position); // Force the bar's width to match the current progress. // When indeterminate, the progress' width will be 100%. if (position >= 0.0) { width *= position; } if (GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) { xoffset += aReflowState.ComputedWidth() - width; } // The bar width is fixed in these cases: // - the progress position is determined: the bar width is fixed according // to it's value. // - the progress position is indeterminate and the bar appearance should be // shown as native: the bar width is forced to 100%. // Otherwise (when the progress is indeterminate and the bar appearance isn't // native), the bar width isn't fixed and can be set by the author. if (position != -1 || ShouldUseNativeStyle()) { width -= reflowState.mComputedMargin.LeftRight() + reflowState.mComputedBorderPadding.LeftRight(); width = NS_MAX(width, 0); reflowState.SetComputedWidth(width); } xoffset += reflowState.mComputedMargin.left; yoffset += reflowState.mComputedMargin.top; nsHTMLReflowMetrics barDesiredSize; ReflowChild(aBarFrame, aPresContext, barDesiredSize, reflowState, xoffset, yoffset, 0, aStatus); FinishReflowChild(aBarFrame, aPresContext, &reflowState, barDesiredSize, xoffset, yoffset, 0); }
void nsComboboxControlFrame::AbsolutelyPositionDropDown() { // Position the dropdown list. It is positioned below the display frame if there is enough // room on the screen to display the entire list. Otherwise it is placed above the display // frame. // Note: As first glance, it appears that you could simply get the absolute bounding box for the // dropdown list by first getting its view, then getting the view's nsIWidget, then asking the nsIWidget // for it's AbsoluteBounds. The problem with this approach, is that the dropdown lists y location can // change based on whether the dropdown is placed below or above the display frame. // The approach, taken here is to get use the absolute position of the display frame and use it's location // to determine if the dropdown will go offscreen. // Use the height calculated for the area frame so it includes both // the display and button heights. nscoord dropdownYOffset = GetRect().height; nsPresContext* presContext = PresContext(); // XXX: Enable this code to debug popping up above the display frame, rather than below it nsSize dropdownSize = mDropdownFrame->GetSize(); nscoord screenHeightInPixels = 0; if (NS_SUCCEEDED(nsFormControlFrame::GetScreenHeight(presContext, screenHeightInPixels))) { // Get the height of the dropdown list in pixels. nscoord absoluteDropDownHeight = presContext->AppUnitsToDevPixels(dropdownSize.height); // Check to see if the drop-down list will go offscreen if (GetScreenRect().YMost() + absoluteDropDownHeight > screenHeightInPixels) { // move the dropdown list up dropdownYOffset = - (dropdownSize.height); } } nsPoint dropdownPosition; const nsStyleVisibility* vis = GetStyleVisibility(); if (vis->mDirection == NS_STYLE_DIRECTION_RTL) { // Align the right edge of the drop-down with the right edge of the control. dropdownPosition.x = GetRect().width - dropdownSize.width; } else { dropdownPosition.x = 0; } dropdownPosition.y = dropdownYOffset; mDropdownFrame->SetPosition(dropdownPosition); }
NS_METHOD nsTableColFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsTableColFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); aDesiredSize.width=0; aDesiredSize.height=0; const nsStyleVisibility* colVis = GetStyleVisibility(); bool collapseCol = (NS_STYLE_VISIBILITY_COLLAPSE == colVis->mVisible); if (collapseCol) { nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this); tableFrame->SetNeedToCollapse(true); } aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; }
NS_IMETHODIMP nsSVGPathGeometryFrame::PaintSVG(nsSVGRenderState *aContext, const nsIntRect *aDirtyRect) { if (!GetStyleVisibility()->IsVisible()) return NS_OK; /* render */ Render(aContext); if (static_cast<nsSVGPathGeometryElement*>(mContent)->IsMarkable()) { MarkerProperties properties = GetMarkerProperties(this); if (properties.MarkersExist()) { float strokeWidth = GetStrokeWidth(); nsTArray<nsSVGMark> marks; static_cast<nsSVGPathGeometryElement*> (mContent)->GetMarkPoints(&marks); PRUint32 num = marks.Length(); if (num) { nsSVGMarkerFrame *frame = properties.GetMarkerStartFrame(); if (frame) frame->PaintMark(aContext, this, &marks[0], strokeWidth); frame = properties.GetMarkerMidFrame(); if (frame) { for (PRUint32 i = 1; i < num - 1; i++) frame->PaintMark(aContext, this, &marks[i], strokeWidth); } frame = properties.GetMarkerEndFrame(); if (frame) frame->PaintMark(aContext, this, &marks[num-1], strokeWidth); } } } return NS_OK; }
NS_METHOD nsTableColGroupFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsTableColGroupFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); NS_ASSERTION(nsnull!=mContent, "bad state -- null content for frame"); nsresult rv=NS_OK; const nsStyleVisibility* groupVis = GetStyleVisibility(); bool collapseGroup = (NS_STYLE_VISIBILITY_COLLAPSE == groupVis->mVisible); if (collapseGroup) { nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this); tableFrame->SetNeedToCollapse(true); } // for every content child that (is a column thingy and does not already have a frame) // create a frame and adjust it's style for (nsIFrame *kidFrame = mFrames.FirstChild(); kidFrame; kidFrame = kidFrame->GetNextSibling()) { // Give the child frame a chance to reflow, even though we know it'll have 0 size nsHTMLReflowMetrics kidSize; nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, nsSize(0,0)); nsReflowStatus status; ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, 0, 0, 0, status); FinishReflowChild(kidFrame, aPresContext, nsnull, kidSize, 0, 0, 0); } aDesiredSize.width=0; aDesiredSize.height=0; aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return rv; }
NS_IMETHODIMP nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { nsresult rv; if (GetPrevInFlow()) { DisplayOverflowContainers(aBuilder, aDirtyRect, 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. // We don't have any border or outline, and our background draws over // the overflow area, so just add nsDisplayCanvasBackground instead of // calling DisplayBorderBackgroundOutline. if (IsVisibleForPainting(aBuilder)) { nsStyleContext* bgSC; const nsStyleBackground* bg = nullptr; bool isThemed = IsThemed(); if (!isThemed && nsCSSRendering::FindBackground(PresContext(), this, &bgSC)) { bg = bgSC->GetStyleBackground(); } aLists.BorderBackground()->AppendNewToTop( new (aBuilder) nsDisplayCanvasBackgroundColor(aBuilder, this)); if (isThemed) { return aLists.BorderBackground()->AppendNewToTop( new (aBuilder) nsDisplayCanvasBackgroundImage(aBuilder, this, 0, isThemed, nullptr)); } if (!bg) { return NS_OK; } // Create separate items for each background layer. NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) { if (bg->mLayers[i].mImage.IsEmpty()) { continue; } rv = aLists.BorderBackground()->AppendNewToTop( new (aBuilder) nsDisplayCanvasBackgroundImage(aBuilder, this, i, isThemed, bg)); NS_ENSURE_SUCCESS(rv, rv); } } nsIFrame* kid; for (kid = GetFirstPrincipalChild(); kid; kid = kid->GetNextSibling()) { // Put our child into its own pseudo-stack. rv = BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists); NS_ENSURE_SUCCESS(rv, rv); } #ifdef DEBUG_CANVAS_FOCUS nsCOMPtr<nsIContent> focusContent; aPresContext->EventStateManager()-> GetFocusedContent(getter_AddRefs(focusContent)); bool hasFocus = false; nsCOMPtr<nsISupports> container; aPresContext->GetContainer(getter_AddRefs(container)); nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container)); if (docShell) { docShell->GetHasFocus(&hasFocus); printf("%p - nsCanvasFrame::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) return NS_OK; // Only paint the focus if we're visible if (!GetStyleVisibility()->IsVisible()) return NS_OK; return aLists.Outlines()->AppendNewToTop(new (aBuilder) nsDisplayCanvasFocus(aBuilder, this)); }
NS_IMETHODIMP nsComboboxControlFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { // Constraints we try to satisfy: // 1) Default width of button is the vertical scrollbar size // 2) If the width of button is bigger than our width, set width of // button to 0. // 3) Default height of button is height of display area // 4) Width of display area is whatever is left over from our width after // allocating width for the button. // 5) Height of display area is GetHeightOfARow() on the // mListControlFrame. if (!mDisplayFrame || !mButtonFrame || !mDropdownFrame) { NS_ERROR("Why did the frame constructor allow this to happen? Fix it!!"); return NS_ERROR_UNEXPECTED; } // Make sure the displayed text is the same as the selected option, bug 297389. PRInt32 selectedIndex; nsAutoString selectedOptionText; if (!mDroppedDown) { selectedIndex = mListControlFrame->GetSelectedIndex(); } else { // In dropped down mode the "selected index" is the hovered menu item, // we want the last selected item which is |mDisplayedIndex| in this case. selectedIndex = mDisplayedIndex; } if (selectedIndex != -1) { mListControlFrame->GetOptionText(selectedIndex, selectedOptionText); } if (mDisplayedOptionText != selectedOptionText) { RedisplayText(selectedIndex); } // First reflow our dropdown so that we know how tall we should be. ReflowDropdown(aPresContext, aReflowState); // Get the width of the vertical scrollbar. That will be the width of the // dropdown button. nscoord buttonWidth; const nsStyleDisplay *disp = GetStyleDisplay(); if (IsThemed(disp) && !aPresContext->GetTheme()->ThemeNeedsComboboxDropmarker()) { buttonWidth = 0; } else { nsIScrollableFrame* scrollable = do_QueryFrame(mListControlFrame); NS_ASSERTION(scrollable, "List must be a scrollable frame"); buttonWidth = scrollable->GetDesiredScrollbarSizes(PresContext(), aReflowState.rendContext).LeftRight(); if (buttonWidth > aReflowState.ComputedWidth()) { buttonWidth = 0; } } mDisplayWidth = aReflowState.ComputedWidth() - buttonWidth; nsresult rv = nsBlockFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); NS_ENSURE_SUCCESS(rv, rv); // Now set the correct width and height on our button. The width we need to // set always, the height only if we had an auto height. nsRect buttonRect = mButtonFrame->GetRect(); // If we have a non-intrinsic computed height, our kids should have sized // themselves properly on their own. if (aReflowState.ComputedHeight() == NS_INTRINSICSIZE) { // The display frame is going to be the right height and width at this // point. Use its height as the button height. nsRect displayRect = mDisplayFrame->GetRect(); buttonRect.height = displayRect.height; buttonRect.y = displayRect.y; } #ifdef DEBUG else { nscoord buttonHeight = mButtonFrame->GetSize().height; nscoord displayHeight = mDisplayFrame->GetSize().height; // The button and display area should be equal heights, unless the computed // height on the combobox is too small to fit their borders and padding. NS_ASSERTION(buttonHeight == displayHeight || (aReflowState.ComputedHeight() < buttonHeight && buttonHeight == mButtonFrame->GetUsedBorderAndPadding().TopBottom()) || (aReflowState.ComputedHeight() < displayHeight && displayHeight == mDisplayFrame->GetUsedBorderAndPadding().TopBottom()), "Different heights?"); } #endif if (GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) { // Make sure the right edge of the button frame stays where it is now buttonRect.x -= buttonWidth - buttonRect.width; } buttonRect.width = buttonWidth; mButtonFrame->SetRect(buttonRect); return rv; }
NS_IMETHODIMP nsTableCellFrame::Paint(nsPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer, PRUint32 aFlags) { NS_ENSURE_TRUE(aPresContext, NS_ERROR_NULL_POINTER); PRBool isVisible; if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && !isVisible) { return NS_OK; } PRBool paintChildren = PR_TRUE; if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { const nsStyleBorder* myBorder = nsnull; const nsStylePadding* myPadding = nsnull; const nsStyleTableBorder* cellTableStyle = nsnull; const nsStyleVisibility* vis = GetStyleVisibility(); if (vis->IsVisible()) { myBorder = GetStyleBorder(); myPadding = GetStylePadding(); cellTableStyle = GetStyleTableBorder(); // draw the border & background only when there is content or showing empty cells if (NS_STYLE_TABLE_EMPTY_CELLS_HIDE != cellTableStyle->mEmptyCells || !GetContentEmpty()) { PaintUnderlay(*aPresContext, aRenderingContext, aDirtyRect, aFlags, *myBorder, *myPadding, *cellTableStyle); } // Paint outline nsRect rect(0, 0, mRect.width, mRect.height); const nsStyleOutline* myOutline = GetStyleOutline(); nsCSSRendering::PaintOutline(aPresContext, aRenderingContext, this, aDirtyRect, rect, *myBorder, *myOutline, mStyleContext, 0); const nsStyleBackground* myColor = GetStyleBackground(); DecorateForSelection(aPresContext, aRenderingContext,myColor); //ignore return value } paintChildren = !(aFlags & NS_PAINT_FLAG_TABLE_CELL_BG_PASS); //flags were for us; remove them for our children aFlags &= ~ (NS_PAINT_FLAG_TABLE_CELL_BG_PASS | NS_PAINT_FLAG_TABLE_BG_PAINT); } #ifdef DEBUG // for debug... if ((NS_FRAME_PAINT_LAYER_DEBUG == aWhichLayer) && GetShowFrameBorders()) { aRenderingContext.SetColor(NS_RGB(0, 0, 128)); aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height); } #endif // paint the children unless we've been told not to if (paintChildren) { const nsStyleDisplay* disp = GetStyleDisplay(); // if the cell originates in a row and/or col that is collapsed, the // bottom and/or right portion of the cell is painted by translating // the rendering context. nsPoint offset; GetCollapseOffset(offset); PRBool pushed = PR_FALSE; if ((0 != offset.x) || (0 != offset.y)) { aRenderingContext.PushState(); pushed = PR_TRUE; aRenderingContext.Translate(offset.x, offset.y); aRenderingContext.SetClipRect(nsRect(-offset.x, -offset.y, mRect.width, mRect.height), nsClipCombine_kIntersect); } else { // XXXldb HIDDEN should really create a scrollframe, // but use |IsTableClip| here since it doesn't. if (disp->IsTableClip() || (HasPctOverHeight() && eCompatibility_NavQuirks == aPresContext->CompatibilityMode())) { aRenderingContext.PushState(); pushed = PR_TRUE; SetOverflowClipRect(aRenderingContext); } } PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, aFlags); if (pushed) { aRenderingContext.PopState(); } } DO_GLOBAL_REFLOW_COUNT_DSP_J("nsTableCellFrame", &aRenderingContext, 0); return NS_OK; /*nsFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);*/ }
void nsTextBoxFrame::DrawText(nsIRenderingContext& aRenderingContext, const nsRect& aTextRect, const nscolor* aOverrideColor) { nsPresContext* presContext = PresContext(); // paint the title nscolor overColor; nscolor underColor; nscolor strikeColor; nsStyleContext* context = mStyleContext; PRUint8 decorations = NS_STYLE_TEXT_DECORATION_NONE; // Begin with no decorations PRUint8 decorMask = NS_STYLE_TEXT_DECORATION_UNDERLINE | NS_STYLE_TEXT_DECORATION_OVERLINE | NS_STYLE_TEXT_DECORATION_LINE_THROUGH; // A mask of all possible decorations. PRBool hasDecorations = context->HasTextDecorations(); do { // find decoration colors const nsStyleTextReset* styleText = context->GetStyleTextReset(); if (decorMask & styleText->mTextDecoration) { // a decoration defined here nscolor color = aOverrideColor ? *aOverrideColor : context->GetStyleColor()->mColor; if (NS_STYLE_TEXT_DECORATION_UNDERLINE & decorMask & styleText->mTextDecoration) { underColor = color; decorMask &= ~NS_STYLE_TEXT_DECORATION_UNDERLINE; decorations |= NS_STYLE_TEXT_DECORATION_UNDERLINE; } if (NS_STYLE_TEXT_DECORATION_OVERLINE & decorMask & styleText->mTextDecoration) { overColor = color; decorMask &= ~NS_STYLE_TEXT_DECORATION_OVERLINE; decorations |= NS_STYLE_TEXT_DECORATION_OVERLINE; } if (NS_STYLE_TEXT_DECORATION_LINE_THROUGH & decorMask & styleText->mTextDecoration) { strikeColor = color; decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_THROUGH; decorations |= NS_STYLE_TEXT_DECORATION_LINE_THROUGH; } } if (0 != decorMask) { context = context->GetParent(); if (context) { hasDecorations = context->HasTextDecorations(); } } } while (context && hasDecorations && (0 != decorMask)); nsCOMPtr<nsIFontMetrics> fontMet; nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet)); nscoord offset; nscoord size; nscoord ascent; fontMet->GetMaxAscent(ascent); nscoord baseline = presContext->RoundAppUnitsToNearestDevPixels(aTextRect.y + ascent); nsRefPtr<gfxContext> ctx = aRenderingContext.ThebesContext(); gfxPoint pt(presContext->AppUnitsToGfxUnits(aTextRect.x), presContext->AppUnitsToGfxUnits(aTextRect.y)); gfxFloat width = presContext->AppUnitsToGfxUnits(aTextRect.width); gfxFloat ascentPixel = presContext->AppUnitsToGfxUnits(ascent); // Underlines are drawn before overlines, and both before the text // itself, per http://www.w3.org/TR/CSS21/zindex.html point 7.2.1.4.1.1. // (We don't apply this rule to the access-key underline because we only // find out where that is as a side effect of drawing the text, in the // general case -- see below.) if (decorations & (NS_FONT_DECORATION_OVERLINE | NS_FONT_DECORATION_UNDERLINE)) { fontMet->GetUnderline(offset, size); gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset); gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size); if (decorations & NS_FONT_DECORATION_UNDERLINE) { nsCSSRendering::PaintDecorationLine(ctx, underColor, pt, gfxSize(width, sizePixel), ascentPixel, offsetPixel, NS_STYLE_TEXT_DECORATION_UNDERLINE, nsCSSRendering::DECORATION_STYLE_SOLID); } if (decorations & NS_FONT_DECORATION_OVERLINE) { nsCSSRendering::PaintDecorationLine(ctx, overColor, pt, gfxSize(width, sizePixel), ascentPixel, ascentPixel, NS_STYLE_TEXT_DECORATION_OVERLINE, nsCSSRendering::DECORATION_STYLE_SOLID); } } aRenderingContext.SetFont(fontMet); CalculateUnderline(aRenderingContext); aRenderingContext.SetColor(aOverrideColor ? *aOverrideColor : GetStyleColor()->mColor); #ifdef IBMBIDI nsresult rv = NS_ERROR_FAILURE; if (mState & NS_FRAME_IS_BIDI) { presContext->SetBidiEnabled(); nsBidiPresUtils* bidiUtils = presContext->GetBidiUtils(); if (bidiUtils) { const nsStyleVisibility* vis = GetStyleVisibility(); nsBidiDirection direction = (NS_STYLE_DIRECTION_RTL == vis->mDirection) ? NSBIDI_RTL : NSBIDI_LTR; if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) { // We let the RenderText function calculate the mnemonic's // underline position for us. nsBidiPositionResolve posResolve; posResolve.logicalIndex = mAccessKeyInfo->mAccesskeyIndex; rv = bidiUtils->RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), direction, presContext, aRenderingContext, aTextRect.x, baseline, &posResolve, 1); mAccessKeyInfo->mBeforeWidth = posResolve.visualLeftTwips; mAccessKeyInfo->mAccessWidth = posResolve.visualWidth; } else { rv = bidiUtils->RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), direction, presContext, aRenderingContext, aTextRect.x, baseline); } } } if (NS_FAILED(rv) ) #endif // IBMBIDI { aRenderingContext.SetTextRunRTL(PR_FALSE); if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) { // In the simple (non-BiDi) case, we calculate the mnemonic's // underline position by getting the text metric. // XXX are attribute values always two byte? if (mAccessKeyInfo->mAccesskeyIndex > 0) aRenderingContext.GetWidth(mCroppedTitle.get(), mAccessKeyInfo->mAccesskeyIndex, mAccessKeyInfo->mBeforeWidth); else mAccessKeyInfo->mBeforeWidth = 0; } aRenderingContext.DrawString(mCroppedTitle, aTextRect.x, baseline); } if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) { aRenderingContext.FillRect(aTextRect.x + mAccessKeyInfo->mBeforeWidth, aTextRect.y + mAccessKeyInfo->mAccessOffset, mAccessKeyInfo->mAccessWidth, mAccessKeyInfo->mAccessUnderlineSize); } // Strikeout is drawn on top of the text, per // http://www.w3.org/TR/CSS21/zindex.html point 7.2.1.4.1.1. if (decorations & NS_FONT_DECORATION_LINE_THROUGH) { fontMet->GetStrikeout(offset, size); gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset); gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size); nsCSSRendering::PaintDecorationLine(ctx, strikeColor, pt, gfxSize(width, sizePixel), ascentPixel, offsetPixel, NS_STYLE_TEXT_DECORATION_LINE_THROUGH, nsCSSRendering::DECORATION_STYLE_SOLID); } }
bool nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus, const ReflowConfig& aConfig, bool aUnboundedLastColumn, nsCollapsingMargin* aBottomMarginCarriedOut, ColumnBalanceData& aColData) { aColData.Reset(); bool allFit = true; bool RTL = GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL; bool shrinkingHeightOnly = !NS_SUBTREE_DIRTY(this) && mLastBalanceHeight > aConfig.mColMaxHeight; #ifdef DEBUG_roc printf("*** Doing column reflow pass: mLastBalanceHeight=%d, mColMaxHeight=%d, RTL=%d\n, mBalanceColCount=%d, mColWidth=%d, mColGap=%d\n", mLastBalanceHeight, aConfig.mColMaxHeight, RTL, aConfig.mBalanceColCount, aConfig.mColWidth, aConfig.mColGap); #endif DrainOverflowColumns(); if (mLastBalanceHeight != aConfig.mColMaxHeight) { mLastBalanceHeight = aConfig.mColMaxHeight; // XXX Seems like this could fire if incremental reflow pushed the column set // down so we reflow incrementally with a different available height. // We need a way to do an incremental reflow and be sure availableHeight // changes are taken account of! Right now I think block frames with absolute // children might exit early. //NS_ASSERTION(aKidReason != eReflowReason_Incremental, // "incremental reflow should not have changed the balance height"); } // get our border and padding const nsMargin &borderPadding = aReflowState.mComputedBorderPadding; nsRect contentRect(0, 0, 0, 0); nsOverflowAreas overflowRects; nsIFrame* child = mFrames.FirstChild(); nsPoint childOrigin = nsPoint(borderPadding.left, borderPadding.top); // For RTL, figure out where the last column's left edge should be. Since the // columns might not fill the frame exactly, we need to account for the // slop. Otherwise we'll waste time moving the columns by some tiny // amount unnecessarily. nscoord targetX = borderPadding.left; if (RTL) { nscoord availWidth = aReflowState.availableWidth; if (aReflowState.ComputedWidth() != NS_INTRINSICSIZE) { availWidth = aReflowState.ComputedWidth(); } if (availWidth != NS_INTRINSICSIZE) { childOrigin.x += availWidth - aConfig.mColWidth; targetX += aConfig.mExpectedWidthLeftOver; #ifdef DEBUG_roc printf("*** childOrigin.x = %d\n", childOrigin.x); #endif } } int columnCount = 0; int contentBottom = 0; bool reflowNext = false; while (child) { // Try to skip reflowing the child. We can't skip if the child is dirty. We also can't // skip if the next column is dirty, because the next column's first line(s) // might be pullable back to this column. We can't skip if it's the last child // because we need to obtain the bottom margin. We can't skip // if this is the last column and we're supposed to assign unbounded // height to it, because that could change the available height from // the last time we reflowed it and we should try to pull all the // content from its next sibling. (Note that it might be the last // column, but not be the last child because the desired number of columns // has changed.) bool skipIncremental = !aReflowState.ShouldReflowAllKids() && !NS_SUBTREE_DIRTY(child) && child->GetNextSibling() && !(aUnboundedLastColumn && columnCount == aConfig.mBalanceColCount - 1) && !NS_SUBTREE_DIRTY(child->GetNextSibling()); // If we need to pull up content from the prev-in-flow then this is not just // a height shrink. The prev in flow will have set the dirty bit. // Check the overflow rect YMost instead of just the child's content height. The child // may have overflowing content that cares about the available height boundary. // (It may also have overflowing content that doesn't care about the available height // boundary, but if so, too bad, this optimization is defeated.) // We want scrollable overflow here since this is a calculation that // affects layout. bool skipResizeHeightShrink = shrinkingHeightOnly && child->GetScrollableOverflowRect().YMost() <= aConfig.mColMaxHeight; nscoord childContentBottom = 0; if (!reflowNext && (skipIncremental || skipResizeHeightShrink)) { // This child does not need to be reflowed, but we may need to move it MoveChildTo(this, child, childOrigin); // If this is the last frame then make sure we get the right status nsIFrame* kidNext = child->GetNextSibling(); if (kidNext) { aStatus = (kidNext->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) ? NS_FRAME_OVERFLOW_INCOMPLETE : NS_FRAME_NOT_COMPLETE; } else { aStatus = mLastFrameStatus; } childContentBottom = nsLayoutUtils::CalculateContentBottom(child); #ifdef DEBUG_roc printf("*** Skipping child #%d %p (incremental %d, resize height shrink %d): status = %d\n", columnCount, (void*)child, skipIncremental, skipResizeHeightShrink, aStatus); #endif } else { nsSize availSize(aConfig.mColWidth, aConfig.mColMaxHeight); if (aUnboundedLastColumn && columnCount == aConfig.mBalanceColCount - 1) { availSize.height = GetAvailableContentHeight(aReflowState); } if (reflowNext) child->AddStateBits(NS_FRAME_IS_DIRTY); nsHTMLReflowState kidReflowState(PresContext(), aReflowState, child, availSize, availSize.width, aReflowState.ComputedHeight()); kidReflowState.mFlags.mIsTopOfPage = PR_TRUE; kidReflowState.mFlags.mTableIsSplittable = PR_FALSE; #ifdef DEBUG_roc printf("*** Reflowing child #%d %p: availHeight=%d\n", columnCount, (void*)child,availSize.height); #endif // Note if the column's next in flow is not being changed by this incremental reflow. // This may allow the current column to avoid trying to pull lines from the next column. if (child->GetNextSibling() && !(GetStateBits() & NS_FRAME_IS_DIRTY) && !(child->GetNextSibling()->GetStateBits() & NS_FRAME_IS_DIRTY)) { kidReflowState.mFlags.mNextInFlowUntouched = PR_TRUE; } nsHTMLReflowMetrics kidDesiredSize(aDesiredSize.mFlags); // XXX it would be cool to consult the float manager for the // previous block to figure out the region of floats from the // previous column that extend into this column, and subtract // that region from the new float manager. So you could stick a // really big float in the first column and text in following // columns would flow around it. // Reflow the frame ReflowChild(child, PresContext(), kidDesiredSize, kidReflowState, childOrigin.x + kidReflowState.mComputedMargin.left, childOrigin.y + kidReflowState.mComputedMargin.top, 0, aStatus); reflowNext = (aStatus & NS_FRAME_REFLOW_NEXTINFLOW) != 0; #ifdef DEBUG_roc printf("*** Reflowed child #%d %p: status = %d, desiredSize=%d,%d\n", columnCount, (void*)child, aStatus, kidDesiredSize.width, kidDesiredSize.height); #endif NS_FRAME_TRACE_REFLOW_OUT("Column::Reflow", aStatus); *aBottomMarginCarriedOut = kidDesiredSize.mCarriedOutBottomMargin; FinishReflowChild(child, PresContext(), &kidReflowState, kidDesiredSize, childOrigin.x, childOrigin.y, 0); childContentBottom = nsLayoutUtils::CalculateContentBottom(child); if (childContentBottom > aConfig.mColMaxHeight) { allFit = PR_FALSE; } if (childContentBottom > availSize.height) { aColData.mMaxOverflowingHeight = NS_MAX(childContentBottom, aColData.mMaxOverflowingHeight); } } contentRect.UnionRect(contentRect, child->GetRect()); ConsiderChildOverflow(overflowRects, child); contentBottom = NS_MAX(contentBottom, childContentBottom); aColData.mLastHeight = childContentBottom; aColData.mSumHeight += childContentBottom; // Build a continuation column if necessary nsIFrame* kidNextInFlow = child->GetNextInFlow(); if (NS_FRAME_IS_FULLY_COMPLETE(aStatus) && !NS_FRAME_IS_TRUNCATED(aStatus)) { NS_ASSERTION(!kidNextInFlow, "next in flow should have been deleted"); child = nsnull; break; } else { ++columnCount; // Make sure that the column has a next-in-flow. If not, we must // create one to hold the overflowing stuff, even if we're just // going to put it on our overflow list and let *our* // next in flow handle it. if (!kidNextInFlow) { NS_ASSERTION(aStatus & NS_FRAME_REFLOW_NEXTINFLOW, "We have to create a continuation, but the block doesn't want us to reflow it?"); // We need to create a continuing column nsresult rv = CreateNextInFlow(PresContext(), child, kidNextInFlow); if (NS_FAILED(rv)) { NS_NOTREACHED("Couldn't create continuation"); child = nsnull; break; } } // Make sure we reflow a next-in-flow when it switches between being // normal or overflow container if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) { if (!(kidNextInFlow->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)) { aStatus |= NS_FRAME_REFLOW_NEXTINFLOW; reflowNext = PR_TRUE; kidNextInFlow->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER); } } else if (kidNextInFlow->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) { aStatus |= NS_FRAME_REFLOW_NEXTINFLOW; reflowNext = PR_TRUE; kidNextInFlow->RemoveStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER); } if (columnCount >= aConfig.mBalanceColCount) { // No more columns allowed here. Stop. aStatus |= NS_FRAME_REFLOW_NEXTINFLOW; kidNextInFlow->AddStateBits(NS_FRAME_IS_DIRTY); // Move any of our leftover columns to our overflow list. Our // next-in-flow will eventually pick them up. const nsFrameList& continuationColumns = mFrames.RemoveFramesAfter(child); if (continuationColumns.NotEmpty()) { SetOverflowFrames(PresContext(), continuationColumns); } child = nsnull; break; } } if (PresContext()->HasPendingInterrupt()) { // Stop the loop now while |child| still points to the frame that bailed // out. We could keep going here and condition a bunch of the code in // this loop on whether there's an interrupt, or even just keep going and // trying to reflow the blocks (even though we know they'll interrupt // right after their first line), but stopping now is conceptually the // simplest (and probably fastest) thing. break; } // Advance to the next column child = child->GetNextSibling(); if (child) { if (!RTL) { childOrigin.x += aConfig.mColWidth + aConfig.mColGap; } else { childOrigin.x -= aConfig.mColWidth + aConfig.mColGap; } #ifdef DEBUG_roc printf("*** NEXT CHILD ORIGIN.x = %d\n", childOrigin.x); #endif } } if (PresContext()->CheckForInterrupt(this) && (GetStateBits() & NS_FRAME_IS_DIRTY)) { // Mark all our kids starting with |child| dirty // Note that this is a CheckForInterrupt call, not a HasPendingInterrupt, // because we might have interrupted while reflowing |child|, and since // we're about to add a dirty bit to |child| we need to make sure that // |this| is scheduled to have dirty bits marked on it and its ancestors. // Otherwise, when we go to mark dirty bits on |child|'s ancestors we'll // bail out immediately, since it'll already have a dirty bit. for (; child; child = child->GetNextSibling()) { child->AddStateBits(NS_FRAME_IS_DIRTY); } } // If we're doing RTL, we need to make sure our last column is at the left-hand side of the frame. if (RTL && childOrigin.x != targetX) { overflowRects.Clear(); contentRect = nsRect(0, 0, 0, 0); PRInt32 deltaX = targetX - childOrigin.x; #ifdef DEBUG_roc printf("*** CHILDORIGIN.x = %d, targetX = %d, DELTAX = %d\n", childOrigin.x, targetX, deltaX); #endif for (child = mFrames.FirstChild(); child; child = child->GetNextSibling()) { MoveChildTo(this, child, child->GetPosition() + nsPoint(deltaX, 0)); ConsiderChildOverflow(overflowRects, child); contentRect.UnionRect(contentRect, child->GetRect()); } } aColData.mMaxHeight = contentBottom; contentRect.height = NS_MAX(contentRect.height, contentBottom); mLastFrameStatus = aStatus; // contentRect included the borderPadding.left,borderPadding.top of the child rects contentRect -= nsPoint(borderPadding.left, borderPadding.top); nsSize contentSize = nsSize(contentRect.XMost(), contentRect.YMost()); // Apply computed and min/max values if (aReflowState.ComputedHeight() != NS_INTRINSICSIZE) { contentSize.height = aReflowState.ComputedHeight(); } else { if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxHeight) { contentSize.height = NS_MIN(aReflowState.mComputedMaxHeight, contentSize.height); } if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinHeight) { contentSize.height = NS_MAX(aReflowState.mComputedMinHeight, contentSize.height); } } if (aReflowState.ComputedWidth() != NS_INTRINSICSIZE) { contentSize.width = aReflowState.ComputedWidth(); } else { if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) { contentSize.width = NS_MIN(aReflowState.mComputedMaxWidth, contentSize.width); } if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinWidth) { contentSize.width = NS_MAX(aReflowState.mComputedMinWidth, contentSize.width); } } aDesiredSize.height = borderPadding.top + contentSize.height + borderPadding.bottom; aDesiredSize.width = contentSize.width + borderPadding.left + borderPadding.right; aDesiredSize.mOverflowAreas = overflowRects; aDesiredSize.UnionOverflowAreasWithDesiredBounds(); #ifdef DEBUG_roc printf("*** DONE PASS feasible=%d\n", allFit && NS_FRAME_IS_FULLY_COMPLETE(aStatus) && !NS_FRAME_IS_TRUNCATED(aStatus)); #endif return allFit && NS_FRAME_IS_FULLY_COMPLETE(aStatus) && !NS_FRAME_IS_TRUNCATED(aStatus); }
NS_IMETHODIMP nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { if (!IsVisibleForPainting(aBuilder)) return NS_OK; if (aBuilder->IsForEventDelivery() && GetStyleVisibility()->mPointerEvents == NS_STYLE_POINTER_EVENTS_NONE) return NS_OK; nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists); NS_ENSURE_SUCCESS(rv, rv); if (!mInnerView) return NS_OK; nsIView* subdocView = mInnerView->GetFirstChild(); if (!subdocView) return NS_OK; nsCOMPtr<nsIPresShell> presShell; nsIFrame* f = static_cast<nsIFrame*>(subdocView->GetClientData()); if (f) { presShell = f->PresContext()->PresShell(); } else { // If we don't have a frame we use this roundabout way to get the pres shell. if (!mFrameLoader) return NS_OK; nsCOMPtr<nsIDocShell> docShell; mFrameLoader->GetDocShell(getter_AddRefs(docShell)); if (!docShell) return NS_OK; docShell->GetPresShell(getter_AddRefs(presShell)); if (!presShell) return NS_OK; } PRBool suppressed = PR_TRUE; presShell->IsPaintingSuppressed(&suppressed); nsDisplayList childItems; nsRect dirty; if (f) { dirty = aDirtyRect - f->GetOffsetTo(this); aBuilder->EnterPresShell(f, dirty); } // Get the bounds of subdocView relative to the reference frame. nsRect shellBounds = subdocView->GetBounds() + mInnerView->GetPosition() + GetOffsetTo(aBuilder->ReferenceFrame()); if (!aBuilder->IsForEventDelivery()) { // Add the canvas background color. nsCOMPtr<nsIPresShell_MOZILLA_1_9_2> presShell192 = do_QueryInterface(presShell); if (presShell192) { rv = presShell192->AddCanvasBackgroundColorItem2( *aBuilder, childItems, f ? f : this, &shellBounds, NS_RGBA(0,0,0,0), PR_TRUE); } } if (f && NS_SUCCEEDED(rv)) { rv = f->BuildDisplayListForStackingContext(aBuilder, dirty, &childItems); } if (NS_SUCCEEDED(rv)) { // Clip children to the child root frame's rectangle rv = aLists.Content()->AppendNewToTop( new (aBuilder) nsDisplayClip(this, this, &childItems, shellBounds)); } // delete childItems in case of OOM childItems.DeleteAll(); if (f) { aBuilder->LeavePresShell(f, dirty); } return rv; }
NS_IMETHODIMP nsResizerFrame::HandleEvent(nsPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus) { NS_ENSURE_ARG_POINTER(aEventStatus); if (nsEventStatus_eConsumeNoDefault == *aEventStatus) { return NS_OK; } nsWeakFrame weakFrame(this); PRBool doDefault = PR_TRUE; switch (aEvent->message) { case NS_MOUSE_BUTTON_DOWN: { if (aEvent->eventStructType == NS_MOUSE_EVENT && static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton) { nsCOMPtr<nsIBaseWindow> window; nsIPresShell* presShell = aPresContext->GetPresShell(); nsIContent* contentToResize = GetContentToResize(presShell, getter_AddRefs(window)); if (contentToResize) { nsIFrame* frameToResize = contentToResize->GetPrimaryFrame(); if (!frameToResize) break; mMouseDownRect = frameToResize->GetScreenRect(); } else { // ask the widget implementation to begin a resize drag if it can Direction direction = GetDirection(); nsresult rv = aEvent->widget->BeginResizeDrag(aEvent, direction.mHorizontal, direction.mVertical); if (rv == NS_ERROR_NOT_IMPLEMENTED && window) { // if there's no native resize support, we need to do window // resizing ourselves window->GetPositionAndSize(&mMouseDownRect.x, &mMouseDownRect.y, &mMouseDownRect.width, &mMouseDownRect.height); } else { // for native drags, don't set the fields below doDefault = PR_FALSE; break; } } // we're tracking mTrackingMouseMove = PR_TRUE; // remember current mouse coordinates mMouseDownPoint = aEvent->refPoint + aEvent->widget->WidgetToScreenOffset(); nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED); doDefault = PR_FALSE; } } break; case NS_MOUSE_BUTTON_UP: { if (mTrackingMouseMove && aEvent->eventStructType == NS_MOUSE_EVENT && static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton) { // we're done tracking. mTrackingMouseMove = PR_FALSE; nsIPresShell::SetCapturingContent(nsnull, 0); doDefault = PR_FALSE; } } break; case NS_MOUSE_MOVE: { if (mTrackingMouseMove) { nsCOMPtr<nsIBaseWindow> window; nsIPresShell* presShell = aPresContext->GetPresShell(); nsCOMPtr<nsIContent> contentToResize = GetContentToResize(presShell, getter_AddRefs(window)); // check if the returned content really is a menupopup nsMenuPopupFrame* menuPopupFrame = nsnull; if (contentToResize) { nsIFrame* frameToResize = contentToResize->GetPrimaryFrame(); if (frameToResize && frameToResize->GetType() == nsGkAtoms::menuPopupFrame) { menuPopupFrame = static_cast<nsMenuPopupFrame *>(frameToResize); } } // both MouseMove and direction are negative when pointing to the // top and left, and positive when pointing to the bottom and right // retrieve the offset of the mousemove event relative to the mousedown. // The difference is how much the resize needs to be nsIntPoint screenPoint(aEvent->refPoint + aEvent->widget->WidgetToScreenOffset()); nsIntPoint mouseMove(screenPoint - mMouseDownPoint); // what direction should we go in? For content resizing, always use // 'bottomend'. For other windows, check the dir attribute. Direction direction; if (window || menuPopupFrame) { direction = GetDirection(); if (menuPopupFrame) { menuPopupFrame->CanAdjustEdges( (direction.mHorizontal == -1) ? NS_SIDE_LEFT : NS_SIDE_RIGHT, (direction.mVertical == -1) ? NS_SIDE_TOP : NS_SIDE_BOTTOM, mouseMove); } } else if (contentToResize) { direction.mHorizontal = GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL ? -1 : 1; direction.mVertical = 1; } else { break; // don't do anything if there's nothing to resize } nsIntRect rect = mMouseDownRect; AdjustDimensions(&rect.x, &rect.width, mouseMove.x, direction.mHorizontal); AdjustDimensions(&rect.y, &rect.height, mouseMove.y, direction.mVertical); // Don't allow resizing a window or a popup past the edge of the screen, // so adjust the rectangle to fit within the available screen area. if (window) { nsCOMPtr<nsIScreen> screen; nsCOMPtr<nsIScreenManager> sm(do_GetService("@mozilla.org/gfx/screenmanager;1")); if (sm) { nsIntRect frameRect = GetScreenRect(); sm->ScreenForRect(frameRect.x, frameRect.y, 1, 1, getter_AddRefs(screen)); if (screen) { nsIntRect screenRect; screen->GetRect(&screenRect.x, &screenRect.y, &screenRect.width, &screenRect.height); rect.IntersectRect(rect, screenRect); } } } else if (menuPopupFrame) { nsPoint framePoint = menuPopupFrame->GetScreenRectInAppUnits().TopLeft(); nsIFrame* rootFrame = aPresContext->PresShell()->FrameManager()->GetRootFrame(); nsRect rootScreenRect = rootFrame->GetScreenRectInAppUnits(); nsRect screenRect = menuPopupFrame->GetConstraintRect(framePoint, rootScreenRect); // round using ToInsidePixels as it's better to be a pixel too small // than be too large. If the popup is too large it could get flipped // to the opposite side of the anchor point while resizing. nsIntRect screenRectPixels = screenRect.ToInsidePixels(aPresContext->AppUnitsPerDevPixel()); rect.IntersectRect(rect, screenRectPixels); } if (contentToResize) { nsIntRect cssRect = rect.ToAppUnits(aPresContext->AppUnitsPerDevPixel()) .ToInsidePixels(nsPresContext::AppUnitsPerCSSPixel()); nsAutoString widthstr, heightstr; widthstr.AppendInt(cssRect.width); heightstr.AppendInt(cssRect.height); // for XUL elements, just set the width and height attributes. For // other elements, set style.width and style.height if (contentToResize->IsXUL()) { nsIntRect oldRect; nsWeakFrame weakFrame(menuPopupFrame); if (menuPopupFrame) { nsCOMPtr<nsIWidget> widget; menuPopupFrame->GetWidget(getter_AddRefs(widget)); if (widget) widget->GetScreenBounds(oldRect); } contentToResize->SetAttr(kNameSpaceID_None, nsGkAtoms::width, widthstr, PR_TRUE); contentToResize->SetAttr(kNameSpaceID_None, nsGkAtoms::height, heightstr, PR_TRUE); if (weakFrame.IsAlive() && (oldRect.x != rect.x || oldRect.y != rect.y)) { // XXX This might go very wrong, since menu popups may add // offsets (e.g. from margins) to this position, so the popup's // widget won't end up at the desired position. menuPopupFrame->MoveTo(rect.x, rect.y, PR_TRUE); } } else { nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyleContent = do_QueryInterface(contentToResize); if (inlineStyleContent) { widthstr += NS_LITERAL_STRING("px"); heightstr += NS_LITERAL_STRING("px"); nsCOMPtr<nsIDOMCSSStyleDeclaration> decl; inlineStyleContent->GetStyle(getter_AddRefs(decl)); decl->SetProperty(NS_LITERAL_STRING("width"), widthstr, EmptyString()); decl->SetProperty(NS_LITERAL_STRING("height"), heightstr, EmptyString()); } } } else { window->SetPositionAndSize(rect.x, rect.y, rect.width, rect.height, PR_TRUE); // do the repaint. } doDefault = PR_FALSE; } } break; case NS_MOUSE_CLICK: if (NS_IS_MOUSE_LEFT_CLICK(aEvent)) { MouseClicked(aPresContext, aEvent); } break; } if (!doDefault) *aEventStatus = nsEventStatus_eConsumeNoDefault; if (doDefault && weakFrame.IsAlive()) return nsTitleBarFrame::HandleEvent(aPresContext, aEvent, aEventStatus); else return NS_OK; }
void nsProgressFrame::ReflowBarFrame(nsIFrame* aBarFrame, nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { bool vertical = GetStyleDisplay()->mOrient == NS_STYLE_ORIENT_VERTICAL; nsHTMLReflowState reflowState(aPresContext, aReflowState, aBarFrame, nsSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE)); nscoord size = vertical ? aReflowState.ComputedHeight() : aReflowState.ComputedWidth(); nscoord xoffset = aReflowState.mComputedBorderPadding.left; nscoord yoffset = aReflowState.mComputedBorderPadding.top; double position; nsCOMPtr<nsIDOMHTMLProgressElement> progressElement = do_QueryInterface(mContent); progressElement->GetPosition(&position); // Force the bar's size to match the current progress. // When indeterminate, the progress' size will be 100%. if (position >= 0.0) { size *= position; } if (!vertical && GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) { xoffset += aReflowState.ComputedWidth() - size; } // The bar size is fixed in these cases: // - the progress position is determined: the bar size is fixed according // to it's value. // - the progress position is indeterminate and the bar appearance should be // shown as native: the bar size is forced to 100%. // Otherwise (when the progress is indeterminate and the bar appearance isn't // native), the bar size isn't fixed and can be set by the author. if (position != -1 || ShouldUseNativeStyle()) { if (vertical) { // We want the bar to begin at the bottom. yoffset += aReflowState.ComputedHeight() - size; size -= reflowState.mComputedMargin.TopBottom() + reflowState.mComputedBorderPadding.TopBottom(); size = NS_MAX(size, 0); reflowState.SetComputedHeight(size); } else { size -= reflowState.mComputedMargin.LeftRight() + reflowState.mComputedBorderPadding.LeftRight(); size = NS_MAX(size, 0); reflowState.SetComputedWidth(size); } } else if (vertical) { // For vertical progress bars, we need to position the bar specificly when // the width isn't constrained (position == -1 and !ShouldUseNativeStyle()) // because aReflowState.ComputedHeight() - size == 0. yoffset += aReflowState.ComputedHeight() - reflowState.ComputedHeight(); } xoffset += reflowState.mComputedMargin.left; yoffset += reflowState.mComputedMargin.top; nsHTMLReflowMetrics barDesiredSize; ReflowChild(aBarFrame, aPresContext, barDesiredSize, reflowState, xoffset, yoffset, 0, aStatus); FinishReflowChild(aBarFrame, aPresContext, &reflowState, barDesiredSize, xoffset, yoffset, 0); }
void nsColumnSetFrame::PaintColumnRule(nsRenderingContext* aCtx, const nsRect& aDirtyRect, const nsPoint& aPt) { nsIFrame* child = mFrames.FirstChild(); if (!child) return; // no columns nsIFrame* nextSibling = child->GetNextSibling(); if (!nextSibling) return; // 1 column only - this means no gap to draw on bool isRTL = GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL; const nsStyleColumn* colStyle = GetStyleColumn(); PRUint8 ruleStyle; // Per spec, inset => ridge and outset => groove if (colStyle->mColumnRuleStyle == NS_STYLE_BORDER_STYLE_INSET) ruleStyle = NS_STYLE_BORDER_STYLE_RIDGE; else if (colStyle->mColumnRuleStyle == NS_STYLE_BORDER_STYLE_OUTSET) ruleStyle = NS_STYLE_BORDER_STYLE_GROOVE; else ruleStyle = colStyle->mColumnRuleStyle; nsPresContext* presContext = PresContext(); nscoord ruleWidth = colStyle->GetComputedColumnRuleWidth(); if (!ruleWidth) return; nscolor ruleColor = GetVisitedDependentColor(eCSSProperty__moz_column_rule_color); // In order to re-use a large amount of code, we treat the column rule as a border. // We create a new border style object and fill in all the details of the column rule as // the left border. PaintBorder() does all the rendering for us, so we not // only save an enormous amount of code but we'll support all the line styles that // we support on borders! nsStyleBorder border(presContext); border.SetBorderWidth(NS_SIDE_LEFT, ruleWidth); border.SetBorderStyle(NS_SIDE_LEFT, ruleStyle); border.SetBorderColor(NS_SIDE_LEFT, ruleColor); // Get our content rect as an absolute coordinate, not relative to // our parent (which is what the X and Y normally is) nsRect contentRect = GetContentRect() - GetRect().TopLeft() + aPt; nsSize ruleSize(ruleWidth, contentRect.height); while (nextSibling) { // The frame tree goes RTL in RTL nsIFrame* leftSibling = isRTL ? nextSibling : child; nsIFrame* rightSibling = isRTL ? child : nextSibling; // Each child frame's position coordinates is actually relative to this nsColumnSetFrame. // linePt will be at the top-left edge to paint the line. nsPoint edgeOfLeftSibling = leftSibling->GetRect().TopRight() + aPt; nsPoint edgeOfRightSibling = rightSibling->GetRect().TopLeft() + aPt; nsPoint linePt((edgeOfLeftSibling.x + edgeOfRightSibling.x - ruleWidth) / 2, contentRect.y); nsRect lineRect(linePt, ruleSize); nsCSSRendering::PaintBorderWithStyleBorder(presContext, *aCtx, this, aDirtyRect, lineRect, border, GetStyleContext(), // Remember, we only have the "left" "border". Skip everything else (1 << NS_SIDE_TOP | 1 << NS_SIDE_RIGHT | 1 << NS_SIDE_BOTTOM)); child = nextSibling; nextSibling = nextSibling->GetNextSibling(); } }