nsresult nsSVGMarkerFrame::PaintMark(nsRenderingContext *aContext, nsSVGPathGeometryFrame *aMarkedFrame, nsSVGMark *aMark, float aStrokeWidth) { // If the flag is set when we get here, it means this marker frame // has already been used painting the current mark, and the document // has a marker reference loop. if (mInUse) return NS_OK; AutoMarkerReferencer markerRef(this, aMarkedFrame); nsSVGMarkerElement *marker = static_cast<nsSVGMarkerElement*>(mContent); const nsSVGViewBoxRect viewBox = marker->GetViewBoxRect(); if (viewBox.width <= 0.0f || viewBox.height <= 0.0f) { // We must disable rendering if the viewBox width or height are zero. return NS_OK; } mStrokeWidth = aStrokeWidth; mX = aMark->x; mY = aMark->y; mAutoAngle = aMark->angle; gfxContext *gfx = aContext->ThebesContext(); if (GetStyleDisplay()->IsScrollableOverflow()) { gfx->Save(); gfxRect clipRect = nsSVGUtils::GetClipRectForFrame(this, viewBox.x, viewBox.y, viewBox.width, viewBox.height); nsSVGUtils::SetClipRect(gfx, GetCanvasTM(nsISVGChildFrame::FOR_PAINTING), clipRect); } for (nsIFrame* kid = mFrames.FirstChild(); kid; kid = kid->GetNextSibling()) { nsISVGChildFrame* SVGFrame = do_QueryFrame(kid); if (SVGFrame) { // The CTM of each frame referencing us may be different. SVGFrame->NotifySVGChanged( nsISVGChildFrame::DO_NOT_NOTIFY_RENDERING_OBSERVERS | nsISVGChildFrame::TRANSFORM_CHANGED); nsSVGUtils::PaintFrameWithEffects(aContext, nsnull, kid); } } if (GetStyleDisplay()->IsScrollableOverflow()) gfx->Restore(); return NS_OK; }
// // DidSetStyleContext // // When the style context changes, make sure that all of our image is up to date. // /* virtual */ void nsImageBoxFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext) { nsLeafBoxFrame::DidSetStyleContext(aOldStyleContext); // Fetch our subrect. const nsStyleList* myList = GetStyleList(); mSubRect = myList->mImageRegion; // before |mSuppressStyleCheck| test! if (mUseSrcAttr || mSuppressStyleCheck) return; // No more work required, since the image isn't specified by style. // If we're using a native theme implementation, we shouldn't draw anything. const nsStyleDisplay* disp = GetStyleDisplay(); if (disp->mAppearance && nsBox::gTheme && nsBox::gTheme->ThemeSupportsWidget(nsnull, this, disp->mAppearance)) return; // If list-style-image changes, we have a new image. nsCOMPtr<nsIURI> oldURI, newURI; if (mImageRequest) mImageRequest->GetURI(getter_AddRefs(oldURI)); if (myList->GetListStyleImage()) myList->GetListStyleImage()->GetURI(getter_AddRefs(newURI)); PRBool equal; if (newURI == oldURI || // handles null==null (newURI && oldURI && NS_SUCCEEDED(newURI->Equals(oldURI, &equal)) && equal)) return; UpdateImage(); } // DidSetStyleContext
NS_IMETHODIMP nsSVGInnerSVGFrame::PaintSVG(nsRenderingContext *aContext, const nsIntRect *aDirtyRect) { gfxContextAutoSaveRestore autoSR; if (GetStyleDisplay()->IsScrollableOverflow()) { float x, y, width, height; static_cast<nsSVGSVGElement*>(mContent)-> GetAnimatedLengthValues(&x, &y, &width, &height, nsnull); if (width <= 0 || height <= 0) { return NS_OK; } nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent); gfxMatrix clipTransform = parent->GetCanvasTM(); gfxContext *gfx = aContext->ThebesContext(); autoSR.SetContext(gfx); gfxRect clipRect = nsSVGUtils::GetClipRectForFrame(this, x, y, width, height); nsSVGUtils::SetClipRect(gfx, clipTransform, clipRect); } return nsSVGInnerSVGFrameBase::PaintSVG(aContext, aDirtyRect); }
NS_IMETHODIMP nsBox::GetBorder(nsMargin& aMargin) { aMargin.SizeTo(0,0,0,0); const nsStyleDisplay* disp = GetStyleDisplay(); if (disp->mAppearance && gTheme) { // Go to the theme for the border. nsPresContext *context = PresContext(); if (gTheme->ThemeSupportsWidget(context, this, disp->mAppearance)) { nsIntMargin margin(0, 0, 0, 0); gTheme->GetWidgetBorder(context->DeviceContext(), this, disp->mAppearance, &margin); aMargin.top = context->DevPixelsToAppUnits(margin.top); aMargin.right = context->DevPixelsToAppUnits(margin.right); aMargin.bottom = context->DevPixelsToAppUnits(margin.bottom); aMargin.left = context->DevPixelsToAppUnits(margin.left); return NS_OK; } } aMargin = GetStyleBorder()->GetActualBorder(); return NS_OK; }
nsSize nsProgressFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext, nsSize aCBSize, nscoord aAvailableWidth, nsSize aMargin, nsSize aBorder, nsSize aPadding, bool aShrinkWrap) { float inflation = nsLayoutUtils::FontSizeInflationFor(this, aCBSize.width); nsRefPtr<nsFontMetrics> fontMet; NS_ENSURE_SUCCESS(nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet), inflation), nsSize(0, 0)); nsSize autoSize; autoSize.height = autoSize.width = fontMet->Font().size; // 1em if (GetStyleDisplay()->mOrient == NS_STYLE_ORIENT_VERTICAL) { autoSize.height *= 10; // 10em } else { autoSize.width *= 10; // 10em } return autoSize; }
NS_IMETHODIMP nsComboboxControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { #ifdef NOISY printf("%p paint at (%d, %d, %d, %d)\n", this, aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height); #endif 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 = nsBlockFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists); NS_ENSURE_SUCCESS(rv, rv); } nsPresContext *presContext = PresContext(); const nsStyleDisplay *disp = GetStyleDisplay(); if ((!IsThemed(disp) || !presContext->GetTheme()->ThemeDrawsFocusForWidget(presContext, this, disp->mAppearance)) && mDisplayFrame && IsVisibleForPainting(aBuilder)) { nsresult rv = aLists.Content()->AppendNewToTop(new (aBuilder) nsDisplayComboboxFocus(this)); NS_ENSURE_SUCCESS(rv, rv); } return DisplaySelectionOverlay(aBuilder, aLists); }
NS_IMETHODIMP nsBox::GetPadding(nsMargin& aMargin) { const nsStyleDisplay *disp = GetStyleDisplay(); if (disp->mAppearance && gTheme) { // Go to the theme for the padding. nsPresContext *context = PresContext(); if (gTheme->ThemeSupportsWidget(context, this, disp->mAppearance)) { nsIntMargin margin(0, 0, 0, 0); PRBool useThemePadding; useThemePadding = gTheme->GetWidgetPadding(context->DeviceContext(), this, disp->mAppearance, &margin); if (useThemePadding) { aMargin.top = context->DevPixelsToAppUnits(margin.top); aMargin.right = context->DevPixelsToAppUnits(margin.right); aMargin.bottom = context->DevPixelsToAppUnits(margin.bottom); aMargin.left = context->DevPixelsToAppUnits(margin.left); return NS_OK; } } } aMargin.SizeTo(0,0,0,0); GetStylePadding()->GetPadding(aMargin); return NS_OK; }
nscoord nsMeterFrame::GetMinWidth(nsRenderingContext *aRenderingContext) { nsRefPtr<nsFontMetrics> fontMet; NS_ENSURE_SUCCESS( nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet)), 0); nscoord minWidth = fontMet->Font().size; // 1em if (GetStyleDisplay()->mOrient == NS_STYLE_ORIENT_AUTO || GetStyleDisplay()->mOrient == NS_STYLE_ORIENT_HORIZONTAL) { // The orientation is horizontal minWidth *= 5; // 5em } return minWidth; }
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); }
float nsSVGGeometryFrame::MaybeOptimizeOpacity(float aFillOrStrokeOpacity) { float opacity = GetStyleDisplay()->mOpacity; if (opacity < 1 && nsSVGUtils::CanOptimizeOpacity(this)) { return aFillOrStrokeOpacity * opacity; } return aFillOrStrokeOpacity; }
PRBool nsBox::DoesClipChildren() { const nsStyleDisplay* display = GetStyleDisplay(); NS_ASSERTION((display->mOverflowY == NS_STYLE_OVERFLOW_CLIP) == (display->mOverflowX == NS_STYLE_OVERFLOW_CLIP), "If one overflow is clip, the other should be too"); return display->mOverflowX == NS_STYLE_OVERFLOW_CLIP; }
void nsImageBoxFrame::UpdateImage() { if (mImageRequest) { mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE); mImageRequest = nsnull; } // get the new image src nsAutoString src; mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src); mUseSrcAttr = !src.IsEmpty(); if (mUseSrcAttr) { nsIDocument* doc = mContent->GetDocument(); if (!doc) { // No need to do anything here... return; } nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI(); nsCOMPtr<nsIURI> uri; nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(uri), src, doc, baseURI); if (uri && nsContentUtils::CanLoadImage(uri, mContent, doc, mContent->NodePrincipal())) { nsContentUtils::LoadImage(uri, doc, mContent->NodePrincipal(), doc->GetDocumentURI(), mListener, mLoadFlags, getter_AddRefs(mImageRequest)); } } else { // Only get the list-style-image if we aren't being drawn // by a native theme. PRUint8 appearance = GetStyleDisplay()->mAppearance; if (!(appearance && nsBox::gTheme && nsBox::gTheme->ThemeSupportsWidget(nsnull, this, appearance))) { // get the list-style-image imgIRequest *styleRequest = GetStyleList()->GetListStyleImage(); if (styleRequest) { styleRequest->Clone(mListener, getter_AddRefs(mImageRequest)); } } } if (!mImageRequest) { // We have no image, so size to 0 mIntrinsicSize.SizeTo(0, 0); } else { // We don't want discarding or decode-on-draw for xul images. mImageRequest->RequestDecode(); mImageRequest->LockImage(); } }
bool nsProgressFrame::ShouldUseNativeStyle() const { // Use the native style if these conditions are satisfied: // - both frames use the native appearance; // - neither frame has author specified rules setting the border or the // background. return GetStyleDisplay()->mAppearance == NS_THEME_PROGRESSBAR && mBarDiv->GetPrimaryFrame()->GetStyleDisplay()->mAppearance == NS_THEME_PROGRESSBAR_CHUNK && !PresContext()->HasAuthorSpecifiedRules(const_cast<nsProgressFrame*>(this), NS_AUTHOR_SPECIFIED_BORDER | NS_AUTHOR_SPECIFIED_BACKGROUND) && !PresContext()->HasAuthorSpecifiedRules(mBarDiv->GetPrimaryFrame(), NS_AUTHOR_SPECIFIED_BORDER | NS_AUTHOR_SPECIFIED_BACKGROUND); }
nscoord nsProgressFrame::GetMinWidth(nsRenderingContext *aRenderingContext) { nsRefPtr<nsFontMetrics> fontMet; NS_ENSURE_SUCCESS( nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet)), 0); nscoord minWidth = fontMet->Font().size; // 1em if (GetStyleDisplay()->mOrient == NS_STYLE_ORIENT_HORIZONTAL) { minWidth *= 10; // 10em } return minWidth; }
nsresult nsFirstLetterFrame::CreateContinuationForFloatingParent(nsPresContext* aPresContext, nsIFrame* aChild, nsIFrame** aContinuation, PRBool aIsFluid) { NS_ASSERTION(GetStyleDisplay()->IsFloating(), "can only call this on floating first letter frames"); NS_PRECONDITION(aContinuation, "bad args"); *aContinuation = nsnull; nsresult rv = NS_OK; nsIPresShell* presShell = aPresContext->PresShell(); nsPlaceholderFrame* placeholderFrame = presShell->FrameManager()->GetPlaceholderFrameFor(this); nsIFrame* parent = placeholderFrame->GetParent(); nsIFrame* continuation; rv = presShell->FrameConstructor()-> CreateContinuingFrame(aPresContext, aChild, parent, &continuation, aIsFluid); if (NS_FAILED(rv) || !continuation) { return rv; } // The continuation will have gotten the first letter style from it's // prev continuation, so we need to repair the style context so it // doesn't have the first letter styling. nsStyleContext* parentSC = this->GetStyleContext()->GetParent(); if (parentSC) { nsRefPtr<nsStyleContext> newSC; newSC = presShell->StyleSet()->ResolveStyleForNonElement(parentSC); if (newSC) { continuation->SetStyleContext(newSC); } } //XXX Bidi may not be involved but we have to use the list name // nsGkAtoms::nextBidi because this is just like creating a continuation // except we have to insert it in a different place and we don't want a // reflow command to try to be issued. nsFrameList temp(continuation, continuation); rv = parent->InsertFrames(nsGkAtoms::nextBidi, placeholderFrame, temp); *aContinuation = continuation; return rv; }
NS_IMETHODIMP nsHTMLButtonControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { nsDisplayList onTop; if (IsVisibleForPainting(aBuilder)) { nsresult rv = mRenderer.DisplayButton(aBuilder, aLists.BorderBackground(), &onTop); NS_ENSURE_SUCCESS(rv, rv); } nsDisplayListCollection set; // Do not allow the child subtree to receive events. if (!aBuilder->IsForEventDelivery()) { 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); // clips to our padding box for <input>s but not <button>s, unless // they have non-visible overflow.. if (IsInput() || GetStyleDisplay()->mOverflowX != NS_STYLE_OVERFLOW_VISIBLE) { nsMargin border = GetStyleBorder()->GetActualBorder(); nsRect rect(aBuilder->ToReferenceFrame(this), GetSize()); rect.Deflate(border); nsresult rv = OverflowClip(aBuilder, set, aLists, rect); NS_ENSURE_SUCCESS(rv, rv); } else { set.MoveTo(aLists); } nsresult rv = DisplayOutline(aBuilder, aLists); NS_ENSURE_SUCCESS(rv, rv); // to draw border when selected in editor return DisplaySelectionOverlay(aBuilder, aLists); }
nsSVGInnerSVGFrame::GetFrameForPoint(const nsPoint &aPoint) { if (GetStyleDisplay()->IsScrollableOverflow()) { nsSVGElement *content = static_cast<nsSVGElement*>(mContent); nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent); float clipX, clipY, clipWidth, clipHeight; content->GetAnimatedLengthValues(&clipX, &clipY, &clipWidth, &clipHeight, nsnull); if (!nsSVGUtils::HitTestRect(parent->GetCanvasTM(), clipX, clipY, clipWidth, clipHeight, PresContext()->AppUnitsToDevPixels(aPoint.x), PresContext()->AppUnitsToDevPixels(aPoint.y))) { return nsnull; } } return nsSVGInnerSVGFrameBase::GetFrameForPoint(aPoint); }
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); }
NS_IMETHODIMP nsSVGForeignObjectFrame::PaintSVG(nsSVGRenderState *aContext, const nsIntRect *aDirtyRect) { if (IsDisabled()) return NS_OK; nsIFrame* kid = GetFirstChild(nsnull); if (!kid) return NS_OK; gfxMatrix matrixForChildren = GetCanvasTMForChildren(); gfxMatrix matrix = GetCanvasTM(); nsRenderingContext *ctx = aContext->GetRenderingContext(this); if (!ctx || matrixForChildren.IsSingular()) { NS_WARNING("Can't render foreignObject element!"); return NS_ERROR_FAILURE; } /* Check if we need to draw anything. */ if (aDirtyRect) { PRInt32 appUnitsPerDevPx = PresContext()->AppUnitsPerDevPixel(); if (!mRect.ToOutsidePixels(appUnitsPerDevPx).Intersects(*aDirtyRect)) return NS_OK; } gfxContext *gfx = aContext->GetGfxContext(); gfx->Save(); if (GetStyleDisplay()->IsScrollableOverflow()) { float x, y, width, height; static_cast<nsSVGElement*>(mContent)-> GetAnimatedLengthValues(&x, &y, &width, &height, nsnull); gfxRect clipRect = nsSVGUtils::GetClipRectForFrame(this, 0.0f, 0.0f, width, height); nsSVGUtils::SetClipRect(gfx, matrix, clipRect); } gfx->Multiply(matrixForChildren); // Transform the dirty rect into the rectangle containing the // transformed dirty rect. gfxMatrix invmatrix = matrix.Invert(); NS_ASSERTION(!invmatrix.IsSingular(), "inverse of non-singular matrix should be non-singular"); gfxRect transDirtyRect = gfxRect(aDirtyRect->x, aDirtyRect->y, aDirtyRect->width, aDirtyRect->height); transDirtyRect = invmatrix.TransformBounds(transDirtyRect); transDirtyRect.Scale(nsPresContext::AppUnitsPerCSSPixel()); nsPoint tl(NSToCoordFloor(transDirtyRect.X()), NSToCoordFloor(transDirtyRect.Y())); nsPoint br(NSToCoordCeil(transDirtyRect.XMost()), NSToCoordCeil(transDirtyRect.YMost())); nsRect kidDirtyRect(tl.x, tl.y, br.x - tl.x, br.y - tl.y); kidDirtyRect.IntersectRect(kidDirtyRect, kid->GetRect()); PRUint32 flags = nsLayoutUtils::PAINT_IN_TRANSFORM; if (aContext->IsPaintingToWindow()) { flags |= nsLayoutUtils::PAINT_TO_WINDOW; } nsresult rv = nsLayoutUtils::PaintFrame(ctx, kid, nsRegion(kidDirtyRect), NS_RGBA(0,0,0,0), flags); gfx->Restore(); return rv; }
NS_IMETHODIMP nsSVGForeignObjectFrame::PaintSVG(nsRenderingContext *aContext, const nsIntRect *aDirtyRect) { if (IsDisabled()) return NS_OK; nsIFrame* kid = GetFirstPrincipalChild(); if (!kid) return NS_OK; gfxMatrix matrixForChildren = GetCanvasTMForChildren(); gfxMatrix matrix = GetCanvasTM(); if (matrixForChildren.IsSingular()) { NS_WARNING("Can't render foreignObject element!"); return NS_ERROR_FAILURE; } nsRect kidDirtyRect = kid->GetVisualOverflowRect(); /* Check if we need to draw anything. */ if (aDirtyRect) { // Transform the dirty rect into app units in our userspace. gfxMatrix invmatrix = matrix; invmatrix.Invert(); NS_ASSERTION(!invmatrix.IsSingular(), "inverse of non-singular matrix should be non-singular"); gfxRect transDirtyRect = gfxRect(aDirtyRect->x, aDirtyRect->y, aDirtyRect->width, aDirtyRect->height); transDirtyRect = invmatrix.TransformBounds(transDirtyRect); kidDirtyRect.IntersectRect(kidDirtyRect, nsLayoutUtils::RoundGfxRectToAppRect(transDirtyRect, PresContext()->AppUnitsPerCSSPixel())); // XXX after bug 614732 is fixed, we will compare mRect with aDirtyRect, // not with kidDirtyRect. I.e. // PRInt32 appUnitsPerDevPx = PresContext()->AppUnitsPerDevPixel(); // mRect.ToOutsidePixels(appUnitsPerDevPx).Intersects(*aDirtyRect) if (kidDirtyRect.IsEmpty()) return NS_OK; } gfxContext *gfx = aContext->ThebesContext(); gfx->Save(); if (GetStyleDisplay()->IsScrollableOverflow()) { float x, y, width, height; static_cast<nsSVGElement*>(mContent)-> GetAnimatedLengthValues(&x, &y, &width, &height, nsnull); gfxRect clipRect = nsSVGUtils::GetClipRectForFrame(this, 0.0f, 0.0f, width, height); nsSVGUtils::SetClipRect(gfx, matrix, clipRect); } gfx->Multiply(matrixForChildren); PRUint32 flags = nsLayoutUtils::PAINT_IN_TRANSFORM; if (SVGAutoRenderState::IsPaintingToWindow(aContext)) { flags |= nsLayoutUtils::PAINT_TO_WINDOW; } nsresult rv = nsLayoutUtils::PaintFrame(aContext, kid, nsRegion(kidDirtyRect), NS_RGBA(0,0,0,0), flags); gfx->Restore(); return rv; }
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; }
nsresult nsSubDocumentFrame::ShowDocShell() { nsCOMPtr<nsIDocShell> docShell; nsresult rv = GetDocShell(getter_AddRefs(docShell)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIPresShell> presShell; docShell->GetPresShell(getter_AddRefs(presShell)); if (presShell) { // The docshell is already showing, nothing left to do... NS_ASSERTION(mInnerView, "What's going on?"); return NS_OK; } // pass along marginwidth, marginheight, scrolling so sub document // can use it nsIntSize margin = GetMarginAttributes(); docShell->SetMarginWidth(margin.width); docShell->SetMarginHeight(margin.height); // Current and initial scrolling is set so that all succeeding docs // will use the scrolling value set here, regardless if scrolling is // set by viewing a particular document (e.g. XUL turns off scrolling) nsCOMPtr<nsIScrollable> sc(do_QueryInterface(docShell)); if (sc) { const nsStyleDisplay *disp = GetStyleDisplay(); sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X, ConvertOverflow(disp->mOverflowX)); sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y, ConvertOverflow(disp->mOverflowY)); } PRInt32 itemType = nsIDocShellTreeItem::typeContent; nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(docShell)); if (treeItem) { treeItem->GetItemType(&itemType); } nsContentType contentType; if (itemType == nsIDocShellTreeItem::typeChrome) { contentType = eContentTypeUI; } else { nsCOMPtr<nsIDocShellTreeItem> sameTypeParent; treeItem->GetSameTypeParent(getter_AddRefs(sameTypeParent)); contentType = sameTypeParent ? eContentTypeContentFrame : eContentTypeContent; } rv = CreateViewAndWidget(contentType); if (NS_FAILED(rv)) { return rv; } nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(docShell)); if (baseWindow) { baseWindow->InitWindow(nsnull, mInnerView->GetWidget(), 0, 0, 10, 10); // This is kinda whacky, this "Create()" call doesn't really // create anything, one starts to wonder why this was named // "Create"... baseWindow->Create(); baseWindow->SetVisibility(PR_TRUE); } // Trigger editor re-initialization if midas is turned on in the // sub-document. This shouldn't be necessary, but given the way our // editor works, it is. See // https://bugzilla.mozilla.org/show_bug.cgi?id=284245 docShell->GetPresShell(getter_AddRefs(presShell)); if (presShell) { nsCOMPtr<nsIDOMNSHTMLDocument> doc = do_QueryInterface(presShell->GetDocument()); if (doc) { nsAutoString designMode; doc->GetDesignMode(designMode); if (designMode.EqualsLiteral("on")) { doc->SetDesignMode(NS_LITERAL_STRING("off")); doc->SetDesignMode(NS_LITERAL_STRING("on")); } } } return NS_OK; }
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);*/ }
NS_IMETHODIMP nsFirstLetterFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aMetrics, const nsHTMLReflowState& aReflowState, nsReflowStatus& aReflowStatus) { DO_GLOBAL_REFLOW_COUNT("nsFirstLetterFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aReflowStatus); nsresult rv = NS_OK; // Grab overflow list DrainOverflowFrames(aPresContext); nsIFrame* kid = mFrames.FirstChild(); // Setup reflow state for our child nsSize availSize(aReflowState.availableWidth, aReflowState.availableHeight); const nsMargin& bp = aReflowState.mComputedBorderPadding; nscoord lr = bp.left + bp.right; nscoord tb = bp.top + bp.bottom; NS_ASSERTION(availSize.width != NS_UNCONSTRAINEDSIZE, "should no longer use unconstrained widths"); availSize.width -= lr; if (NS_UNCONSTRAINEDSIZE != availSize.height) { availSize.height -= tb; } // Reflow the child if (!aReflowState.mLineLayout) { // When there is no lineLayout provided, we provide our own. The // only time that the first-letter-frame is not reflowing in a // line context is when its floating. nsHTMLReflowState rs(aPresContext, aReflowState, kid, availSize); nsLineLayout ll(aPresContext, nsnull, &aReflowState, nsnull); ll.BeginLineReflow(bp.left, bp.top, availSize.width, NS_UNCONSTRAINEDSIZE, PR_FALSE, PR_TRUE); rs.mLineLayout = ≪ ll.SetInFirstLetter(PR_TRUE); ll.SetFirstLetterStyleOK(PR_TRUE); kid->WillReflow(aPresContext); kid->Reflow(aPresContext, aMetrics, rs, aReflowStatus); ll.EndLineReflow(); ll.SetInFirstLetter(PR_FALSE); } else { // Pretend we are a span and reflow the child frame nsLineLayout* ll = aReflowState.mLineLayout; PRBool pushedFrame; ll->SetInFirstLetter( mStyleContext->GetPseudo() == nsCSSPseudoElements::firstLetter); ll->BeginSpan(this, &aReflowState, bp.left, availSize.width); ll->ReflowFrame(kid, aReflowStatus, &aMetrics, pushedFrame); ll->EndSpan(this); ll->SetInFirstLetter(PR_FALSE); } // Place and size the child and update the output metrics kid->SetRect(nsRect(bp.left, bp.top, aMetrics.width, aMetrics.height)); kid->FinishAndStoreOverflow(&aMetrics); kid->DidReflow(aPresContext, nsnull, NS_FRAME_REFLOW_FINISHED); aMetrics.width += lr; aMetrics.height += tb; aMetrics.ascent += bp.top; mBaseline = aMetrics.ascent; // Ensure that the overflow rect contains the child textframe's overflow rect. // Note that if this is floating, the overline/underline drawable area is in // the overflow rect of the child textframe. aMetrics.UnionOverflowAreasWithDesiredBounds(); ConsiderChildOverflow(aMetrics.mOverflowAreas, kid); // Create a continuation or remove existing continuations based on // the reflow completion status. if (NS_FRAME_IS_COMPLETE(aReflowStatus)) { if (aReflowState.mLineLayout) { aReflowState.mLineLayout->SetFirstLetterStyleOK(PR_FALSE); } nsIFrame* kidNextInFlow = kid->GetNextInFlow(); if (kidNextInFlow) { // Remove all of the childs next-in-flows static_cast<nsContainerFrame*>(kidNextInFlow->GetParent()) ->DeleteNextInFlowChild(aPresContext, kidNextInFlow, PR_TRUE); } } else { // Create a continuation for the child frame if it doesn't already // have one. if (!GetStyleDisplay()->IsFloating()) { nsIFrame* nextInFlow; rv = CreateNextInFlow(aPresContext, kid, nextInFlow); if (NS_FAILED(rv)) { return rv; } // And then push it to our overflow list const nsFrameList& overflow = mFrames.RemoveFramesAfter(kid); if (overflow.NotEmpty()) { SetOverflowFrames(aPresContext, overflow); } } else if (!kid->GetNextInFlow()) { // For floating first letter frames (if a continuation wasn't already // created for us) we need to put the continuation with the rest of the // text that the first letter frame was made out of. nsIFrame* continuation; rv = CreateContinuationForFloatingParent(aPresContext, kid, &continuation, PR_TRUE); } } FinishAndStoreOverflow(&aMetrics); NS_FRAME_SET_TRUNCATION(aReflowStatus, aReflowState, aMetrics); return rv; }