mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
b3541682d0
- bug 1157569 part 1 - Rename BC_BORDER_{TOP,RIGHT,BOTTOM,LEFT}_HALF* to BC_BORDER_{START,END}_HALF*. r=roc (2ef82ce76)
- Bug 1157569 part 2 - Convert output parameters of GetColorAndStyle/GetPaintStyleInfo in nsTableFrame to use pointers. r=roc (c58bbe734)
- Bug 1157569 part 3 - Merge two GetColorAndStyle functions in nsTableFrame. r=roc (009df4d97)
- Bug 1157569 part 4 - Replace mTableIsLTR with mTableWM in BCMapCellInfo & BCPaintBorderIterator. r=roc (9784a46eb)
- Bug 1157569 part 5 - Convert GetColorAndStyle, GetPaintStyleInfo, and CompareBorders in nsTableFrame to accept writing mode and logical side. r=roc (aaddc4a80)
- Bug 1157569 part 6 - Rename methods and fields in BCMapCellInfo from physicals to logicals. r=roc (aeaa0b18c)
- Bug 1157569 part 7 - Rename methods and fields in nsTableColFrame from physicals to logicals. r=roc (fd4e1e667)
- Bug 1157569 part 8 - Move some code in BCPaintBorderIterator::SetDamageArea for less computation. r=roc (634f19ca7)
- missing bit of Bug 895096 - Part 1 (a96e3d35c)
- Bug 1157569 part 9 - Rename methods and fields in nsTableRowFrame from physicals to logicals. r=roc (d097f1e4f)
- Bug 1157569 part 10 - Add operator+= for LogicalMargin. r=jfkthame (c651b685f)
- Bug 1159101 part 4 - Override GetWritingMode() in nsTable{{Col,Row}{,Group},Cell}Frame. r=roc (34d90d10b)
- Bug 1159101 part 5 - Initialize writing mode of desired mode of table cell frame from its table frame on a CLOSED TREE. r=roc (8bc6978ca)
- Bug 1157569 part 11 - Rename methods and fields in nsTableCellFrame from physicals to logicals. r=roc (bcfd4514b)
- Bug 1157569 part 12 - Remove useless m{Start,End}Side from BCMapCellInfo. r=roc (1df59d670)
- Bug 1159127 - Always redirect inserting col group frame to first-in-flow table frame. r=mats (2e41bbeeb)
- Bug 1167765: Misc whitespace cleanup in nsTableFrame.cpp. whitespace/rewrapping-only, no review, DONTBUILD (f256939c9)
- Bug 1167696 part 1: Remove nsTableReflowState's unused constructor & nsPresContext arg. r=mats (5b8beadb9)
- Bug 1167696 part 2: Remove nsTableReflowState's frame constructor-arg; get it from passed-in reflow state instead. r=mats (205dad74f)
- Bug 1155412: Use mozilla::Maybe instead of hardcoded placement-new, for reflow state created in nsTableOuterFrame::OuterBeginReflowChild() and used by its caller. r=dbaron (ebf9e9891)
- Bug 1147834: Use abstract coordinates in nsHTMLReflowState, r=jfkthame (30e644a14)
- Bug 1169432 part 2: Refactor nsTableFrame::Init. r=mats (779928597)
- Bug 1169432 part 3: Use nsTArray::Contains instead of nsTArray::IndexOf(), for brevity, in nsTableFrame. r=mats (aa6aee3c4)
- Bug 1169432 part 4: Convert NS_ASSERTION(false, ...) to NS_ERROR(...) in nsTableFrame. r=mats (9cbb2f53f)
- Bug 1169432 part 5: Use range-based 'for' loops when walking frame lists, in nsTableFrame. r=mats (bd4e7d0d4)
- Bug 1171328 - Convert nsTableFrame::GetChildAreaOffset() and its friends to use LogicalMargin. r=dholbert (196955d0c)
- Remove unneeded code from SmoothScrollAnimation. (bug 1139220 part 4, r=kats) (68c6af9f8)
- Use stronger typing for GetScrollWheelDelta. (bug 1139220 part 5, r=kats) (4669d1f38)
- When APZ is enabled, only apply the root scroll delta override to root frames. (bug 1155800, r=kats) (2a738ee82)
- Bug 1168629. Clear frame metrics on the root layer if we aren't setting new frame metrics because the layer may be recycled and still have frame metrics from last time. r=mstange (dc0889fae)
- Bug 1158424 - Rename FrameMetrics::mIsRoot to mIsRootContent. r=kats (0005fb016)
- Bug 1148078: Replace the word "Logical" with "Flex-Relative" in some vars & functions in flexbox layout. r=mats (601497c55)
- Bug 1148298 part 1: Convert most flexbox-layout IsAxisHorizontal() calls into IsMainAxisHorizontal()/IsCrossAxisHorizontal(). r=mats (ff2aaa5b3)
- Bug 1148298 part 3: Make flexbox helper GetBaselineOffsetFromOuterCrossEdge take a FlexboxAxisTracker instead of an explicit axis. r=mats (009dd9f7e)
- Bug 1148298 part 4: Convert flexbox helper-function IsAxisHorizontal() to be a private implementation detail of FlexboxAxisTracker. r=mats (901f830d6)
- Bug 1148298 part 2: Replace flexbox static helper-function GetSizeProBug 1148298 part 2: Replace flexbox static helper-function GetSizePro (3d2940f88)
- Bug 1158290 part 1: Use AvailableBSize instead of AvailableHeight, throughout flex layout. r=mats (49e2075f8)
- Bug 1148294 part 1: Determine flex axes (in FlexboxAxisTracker) using the flex container's writing mode. r=mats (67f12cf58)
- Bug 1148294 part 2: Add one reftest for writing-mode & direction properties' influence on flex axes. (85e0ede9d)
- Bug 1148294 part 3: Add more reftests for writing-mode & direction properties' influence on flex axes (as modified copies of first test). (fac965a24)
- Bug 1148294 followup: fix spec links in reftests flexbox-writing-mode-* to point to TR instead of ED spec version. (no review) (84333c728)
- Bug 1158290 part 2: Use logical (not physical) skipsides & borderpadding when chipping away from available BSize. r=mats (987b4edfa)
- Bug 1152913 part 1: Make FlexboxAxisTracker store the WritingMode & representation of how flex axes map to it. r=mats (675737981)
- Bug 1152951: Delete the copy-constructor and reassignment operator for FlexboxAxisTracker & PositionTracker state-management classes. r=mats (71c88e7e9)
- Bug 1152913 part 2: Convert flexbox 'IsAxisHorizontal' checks to use new logical-axis member data. r=mats (122b434a5)
- Bug 1158290 part 3: Convert GenerateFlexLines to use logical axes & sizes. r=mats (367cb1c01)
- Bug 1158290 part 4: Clarify documentation & naming of ClampFlexContainerMainSize (now called ResolveFlexContainerMainSize). r=mats (5af11ff23)
- Bug 1149383 part 1: Make flexbox writing-mode tests use different widths vs. heights to reveal bug with vertical writing-modes. (test-only) (c4782feaa)
- Bug 1149383 part 2: Reorder width/height decls in flexbox-writing-mode reftests for consistency. (test-only) (bba907b70)
- Bug 1158290 part 5: Use logical coords & axes in methods that computeBug 1158290 part 5: Use logical coords & axes in methods that compute (b78726528)
- Bug 1158290 part 6: Use new GET_[MAIN|CROSS]_COMPONENT_LOGICAL macros, to reduce explicit width/height usage. r=mats (25d2e20a3)
- Bug 1152913 part 3: Make flexbox's PositionTracker classes track whether axis is reversed, & directly convert flex item final sizes/positions to logical coords. r=mats (1feee7e6d)
- Bug 1174507 - Replace the frame flag CONTAINS_RELATIVE_HEIGHT with CONTAINS_RELATIVE_BSIZE, and adjust callsites appropriately. r=dholbert (0e981d5ac)
- Clip async scrollframes based on the displaylist clip, not the composition bounds. (bug 1148582 part 4, r=tn) (f2b1196ed)
- Bug 1148582 - Add mask layers to FrameMetrics for ancestor scroll frame clips. r=mattwoodrow (008239305)
- Bug 1148582 - Factor mask layer creation out of ContainerState::SetupMaskLayer. r=mstange (1d739614e)
- piece of Bug 1138442 (e98de18dd)
- Bug 1173307 - Convert nsTableCellFrame to work with logical coordinates. r=dholbert (81d0aa811)
- Bug 1174700 - patch 1 - Convert nsTableRowFrame and nsTableRowGroupFrame to work with logical coordinates. r=dholbert (09ee9c814)
- Bug 1174700 - patch 2 - Convert nsTableFrame::SetColumnDimensions to work with logical-order iteration over the table, so that column coordinates and collapsed borders are correct. r=dholbert (7957e377b)
- Bug 1129040 - Provide a way for content processes to query the chrome side blocklist service. r=billm (5ea750b8b)
- Bug 1174711 - patch 1 - Rename nsIPercentHeightObserver to nsIPercentBSizeObserver, and update related frame methods to match. r=dholbert (7a17fbe4f)
- Bug 1174711 - patch 2 - Convert nsTableFrame to work with logical coordinates. r=dholbert (329776abe)
- Bug 1174711 - patch 3 - Rename a couple more frame-state bits from physical to logical. r=dholbert (d61c9624d)
- Bug 1174711 - patch 4 - Rename mSpecialHeightReflow to mSpecialBSizeReflow, and update comments to match. r=dholbert (49969e512)
- Bug 1174711 patch 5 - Copy inline-size rather than width from prev-in-flow when initializing nsTableFrame. r=dholbert (7afb6c80a)
- pointer style (52cd6f9af)
- pointer style (ba99b3f74)
- Bug 1149797 - Use the loop's *static* block object when freshening a loop's block object, then copy in values from the old cloned block. Using the old cloned block directly isn't valid when the cloned block might be extended with additional variables created by eval or added by nested function statements. r=shu (deba22790)
- Bug 1165486 - Cleanup: use standard object allocation functions when allocating scope objects. (r=terrence) (b35a4d7aa)
- pointer style (74ea6d085)
- Bug 1165486 - Add StaticNonSyntacticScopeObjects and teach scope iterators about it. (r=luke) (18a526ed3)
- Bug 1144371: Implement DEBUG-only JS shell function |dumpStringRepresentation|. r=jandem (35524cf42)
- Bug 1148963 - OdinMonkey: add CompileOptions::lazyParsingDisabled and testing function setDiscardSource (r=bz) (53f9c8fe6)
- pointer style (edaa05d69)
- Bug 1165486 - Rename hasPollutedGlobalScope to hasNonSyntacticScope. (r=luke) (505fc8d05)
- pointer style (3c4435038)
- Bug 1165486 - Remove PollutedGlobalScopeOption in favor of using the static scope chain to detect non-syntactic scopes. (r=luke) (73ca126f5)
- Bug 1150106 - Async loadSubscript - Part 1, add `async` to loadSubscriptWithOptions r=bholley,mcrr8 (a0ffeed0d)
- Bug 1150106 - Add an async version of loadSubscript - Part 2, tests r=bholley (6aeaa93e4)
- Bug 1165486 - Use JS::CompileForNonSyntacticScope in Gecko where we used to set polluted global scope. (r=bz, rs=bholley) (073332ac9)
- Bug 1165486 - Split JS::Compile into JS::Compile and JS::CompileForNonSyntacticScope. (r=luke) (0b82c73c4)
- Bug 1165486 - Restructure function and script cloning in light of PollutingGlobal scope changes. (r=Waldo) (b4e39652c)
- Bug 1141865 - Part 7: Make new.target work in generator functions. (r=jorendorff, r=jandem) (a9f5ce1ad)
- Bug 1165486 - Detect with scopes at parse time using the static scope chain for non-function scripts. Also cache static scope properties on SharedGlobalContext. (r=efaust) (a7d4283cb)
- Bug 1176070 - Optimize nsTableFrame's FirstInFlow() lookups from calls to GetColumnISize(). r=dholbert (beed47b93)
- fix misspatch of Bug 1141862 - Part 6 (d091f70a2)
- Bug 1169736 - Temporarily disallow eval and arrow functions inside derived class constructors. (r=jorendorff) (6cf8a2db1)
- Bug 1150855 - Disallow method syntax without curly brackets. r=efaust (26086ee95)
- part of Bug 1150855 - Remove uses of the curly syntax. (bfe86ea19)
- Bug 1169853 - Require semicolon after export default AssignmentExpression. r=shu (580ff7e30)
- Bug 1174009 - Remove a couple of unused AutoRooter types; r=sfink (113aee16a)
688 lines
25 KiB
C++
688 lines
25 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "nsFieldSetFrame.h"
|
|
|
|
#include "mozilla/gfx/2D.h"
|
|
#include "nsCSSAnonBoxes.h"
|
|
#include "nsLayoutUtils.h"
|
|
#include "nsLegendFrame.h"
|
|
#include "nsCSSRendering.h"
|
|
#include <algorithm>
|
|
#include "nsIFrame.h"
|
|
#include "nsPresContext.h"
|
|
#include "RestyleManager.h"
|
|
#include "nsGkAtoms.h"
|
|
#include "nsStyleConsts.h"
|
|
#include "nsDisplayList.h"
|
|
#include "nsRenderingContext.h"
|
|
#include "nsIScrollableFrame.h"
|
|
#include "mozilla/Likely.h"
|
|
#include "mozilla/Maybe.h"
|
|
|
|
using namespace mozilla;
|
|
using namespace mozilla::gfx;
|
|
using namespace mozilla::image;
|
|
using namespace mozilla::layout;
|
|
|
|
nsContainerFrame*
|
|
NS_NewFieldSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
|
{
|
|
return new (aPresShell) nsFieldSetFrame(aContext);
|
|
}
|
|
|
|
NS_IMPL_FRAMEARENA_HELPERS(nsFieldSetFrame)
|
|
|
|
nsFieldSetFrame::nsFieldSetFrame(nsStyleContext* aContext)
|
|
: nsContainerFrame(aContext)
|
|
, mLegendRect(GetWritingMode())
|
|
{
|
|
mLegendSpace = 0;
|
|
}
|
|
|
|
nsIAtom*
|
|
nsFieldSetFrame::GetType() const
|
|
{
|
|
return nsGkAtoms::fieldSetFrame;
|
|
}
|
|
|
|
nsRect
|
|
nsFieldSetFrame::VisualBorderRectRelativeToSelf() const
|
|
{
|
|
WritingMode wm = GetWritingMode();
|
|
css::Side legendSide = wm.PhysicalSide(eLogicalSideBStart);
|
|
nscoord legendBorder = StyleBorder()->GetComputedBorderWidth(legendSide);
|
|
LogicalRect r(wm, LogicalPoint(wm, 0, 0), GetLogicalSize(wm));
|
|
nscoord containerWidth = r.Width(wm);
|
|
if (legendBorder < mLegendRect.BSize(wm)) {
|
|
nscoord off = (mLegendRect.BSize(wm) - legendBorder) / 2;
|
|
r.BStart(wm) += off;
|
|
r.BSize(wm) -= off;
|
|
}
|
|
return r.GetPhysicalRect(wm, containerWidth);
|
|
}
|
|
|
|
nsIFrame*
|
|
nsFieldSetFrame::GetInner() const
|
|
{
|
|
nsIFrame* last = mFrames.LastChild();
|
|
if (last &&
|
|
last->StyleContext()->GetPseudo() == nsCSSAnonBoxes::fieldsetContent) {
|
|
return last;
|
|
}
|
|
MOZ_ASSERT(mFrames.LastChild() == mFrames.FirstChild());
|
|
return nullptr;
|
|
}
|
|
|
|
nsIFrame*
|
|
nsFieldSetFrame::GetLegend() const
|
|
{
|
|
if (mFrames.FirstChild() == GetInner()) {
|
|
MOZ_ASSERT(mFrames.LastChild() == mFrames.FirstChild());
|
|
return nullptr;
|
|
}
|
|
MOZ_ASSERT(mFrames.FirstChild() &&
|
|
mFrames.FirstChild()->GetContentInsertionFrame()->GetType() ==
|
|
nsGkAtoms::legendFrame);
|
|
return mFrames.FirstChild();
|
|
}
|
|
|
|
class nsDisplayFieldSetBorderBackground : public nsDisplayItem {
|
|
public:
|
|
nsDisplayFieldSetBorderBackground(nsDisplayListBuilder* aBuilder,
|
|
nsFieldSetFrame* aFrame)
|
|
: nsDisplayItem(aBuilder, aFrame) {
|
|
MOZ_COUNT_CTOR(nsDisplayFieldSetBorderBackground);
|
|
}
|
|
#ifdef NS_BUILD_REFCNT_LOGGING
|
|
virtual ~nsDisplayFieldSetBorderBackground() {
|
|
MOZ_COUNT_DTOR(nsDisplayFieldSetBorderBackground);
|
|
}
|
|
#endif
|
|
|
|
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
|
|
HitTestState* aState,
|
|
nsTArray<nsIFrame*> *aOutFrames) override;
|
|
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
|
nsRenderingContext* aCtx) override;
|
|
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override;
|
|
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
|
const nsDisplayItemGeometry* aGeometry,
|
|
nsRegion *aInvalidRegion) override;
|
|
NS_DISPLAY_DECL_NAME("FieldSetBorderBackground", TYPE_FIELDSET_BORDER_BACKGROUND)
|
|
};
|
|
|
|
void nsDisplayFieldSetBorderBackground::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
|
|
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
|
|
{
|
|
// aPt is guaranteed to be in this item's bounds. We do the hit test based on the
|
|
// frame bounds even though our background doesn't cover the whole frame.
|
|
// It's not clear whether this is correct.
|
|
aOutFrames->AppendElement(mFrame);
|
|
}
|
|
|
|
void
|
|
nsDisplayFieldSetBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
|
|
nsRenderingContext* aCtx)
|
|
{
|
|
DrawResult result = static_cast<nsFieldSetFrame*>(mFrame)->
|
|
PaintBorderBackground(*aCtx, ToReferenceFrame(),
|
|
mVisibleRect, aBuilder->GetBackgroundPaintFlags());
|
|
|
|
nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
|
|
}
|
|
|
|
nsDisplayItemGeometry*
|
|
nsDisplayFieldSetBorderBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder)
|
|
{
|
|
return new nsDisplayItemGenericImageGeometry(this, aBuilder);
|
|
}
|
|
|
|
void
|
|
nsDisplayFieldSetBorderBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
|
const nsDisplayItemGeometry* aGeometry,
|
|
nsRegion *aInvalidRegion)
|
|
{
|
|
auto geometry =
|
|
static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
|
|
|
|
if (aBuilder->ShouldSyncDecodeImages() &&
|
|
geometry->ShouldInvalidateToSyncDecodeImages()) {
|
|
bool snap;
|
|
aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
|
|
}
|
|
|
|
nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
|
|
}
|
|
|
|
void
|
|
nsFieldSetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|
const nsRect& aDirtyRect,
|
|
const nsDisplayListSet& aLists) {
|
|
// Paint our background and border in a special way.
|
|
// REVIEW: We don't really need to check frame emptiness here; if it's empty,
|
|
// the background/border display item won't do anything, and if it isn't empty,
|
|
// we need to paint the outline
|
|
if (!(GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) &&
|
|
IsVisibleForPainting(aBuilder)) {
|
|
if (StyleBorder()->mBoxShadow) {
|
|
aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
|
|
nsDisplayBoxShadowOuter(aBuilder, this));
|
|
}
|
|
|
|
// don't bother checking to see if we really have a border or background.
|
|
// we usually will have a border.
|
|
aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
|
|
nsDisplayFieldSetBorderBackground(aBuilder, this));
|
|
|
|
DisplayOutlineUnconditional(aBuilder, aLists);
|
|
|
|
DO_GLOBAL_REFLOW_COUNT_DSP("nsFieldSetFrame");
|
|
}
|
|
|
|
if (GetPrevInFlow()) {
|
|
DisplayOverflowContainers(aBuilder, aDirtyRect, aLists);
|
|
}
|
|
|
|
nsDisplayListCollection contentDisplayItems;
|
|
if (nsIFrame* inner = GetInner()) {
|
|
// Collect the inner frame's display items into their own collection.
|
|
// We need to be calling BuildDisplayList on it before the legend in
|
|
// case it contains out-of-flow frames whose placeholders are in the
|
|
// legend. However, we want the inner frame's display items to be
|
|
// after the legend's display items in z-order, so we need to save them
|
|
// and append them later.
|
|
BuildDisplayListForChild(aBuilder, inner, aDirtyRect, contentDisplayItems);
|
|
}
|
|
if (nsIFrame* legend = GetLegend()) {
|
|
// The legend's background goes on our BlockBorderBackgrounds list because
|
|
// it's a block child.
|
|
nsDisplayListSet set(aLists, aLists.BlockBorderBackgrounds());
|
|
BuildDisplayListForChild(aBuilder, legend, aDirtyRect, set);
|
|
}
|
|
// Put the inner frame's display items on the master list. Note that this
|
|
// moves its border/background display items to our BorderBackground() list,
|
|
// which isn't really correct, but it's OK because the inner frame is
|
|
// anonymous and can't have its own border and background.
|
|
contentDisplayItems.MoveTo(aLists);
|
|
}
|
|
|
|
DrawResult
|
|
nsFieldSetFrame::PaintBorderBackground(nsRenderingContext& aRenderingContext,
|
|
nsPoint aPt, const nsRect& aDirtyRect, uint32_t aBGFlags)
|
|
{
|
|
// if the border is smaller than the legend. Move the border down
|
|
// to be centered on the legend.
|
|
// FIXME: This means border-radius clamping is incorrect; we should
|
|
// override nsIFrame::GetBorderRadii.
|
|
WritingMode wm = GetWritingMode();
|
|
nsRect rect = VisualBorderRectRelativeToSelf();
|
|
nscoord off = wm.IsVertical() ? rect.x : rect.y;
|
|
rect += aPt;
|
|
nsPresContext* presContext = PresContext();
|
|
|
|
DrawResult result =
|
|
nsCSSRendering::PaintBackground(presContext, aRenderingContext, this,
|
|
aDirtyRect, rect, aBGFlags);
|
|
|
|
nsCSSRendering::PaintBoxShadowInner(presContext, aRenderingContext,
|
|
this, rect, aDirtyRect);
|
|
|
|
if (nsIFrame* legend = GetLegend()) {
|
|
css::Side legendSide = wm.PhysicalSide(eLogicalSideBStart);
|
|
nscoord legendBorderWidth =
|
|
StyleBorder()->GetComputedBorderWidth(legendSide);
|
|
|
|
// Use the rect of the legend frame, not mLegendRect, so we draw our
|
|
// border under the legend's inline-start and -end margins.
|
|
LogicalRect legendRect(wm, legend->GetRect() + aPt, rect.width);
|
|
|
|
// Compute clipRect using logical coordinates, so that the legend space
|
|
// will be clipped out of the appropriate physical side depending on mode.
|
|
LogicalRect clipRect = LogicalRect(wm, rect, rect.width);
|
|
DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
|
|
gfxContext* gfx = aRenderingContext.ThebesContext();
|
|
int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
|
|
|
|
// draw inline-start portion of the block-start side of the border
|
|
clipRect.ISize(wm) = legendRect.IStart(wm) - clipRect.IStart(wm);
|
|
clipRect.BSize(wm) = legendBorderWidth;
|
|
|
|
gfx->Save();
|
|
gfx->Clip(NSRectToSnappedRect(clipRect.GetPhysicalRect(wm, rect.width),
|
|
appUnitsPerDevPixel, *drawTarget));
|
|
nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
|
|
aDirtyRect, rect, mStyleContext);
|
|
gfx->Restore();
|
|
|
|
// draw inline-end portion of the block-start side of the border
|
|
clipRect = LogicalRect(wm, rect, rect.width);
|
|
clipRect.ISize(wm) = clipRect.IEnd(wm) - legendRect.IEnd(wm);
|
|
clipRect.IStart(wm) = legendRect.IEnd(wm);
|
|
clipRect.BSize(wm) = legendBorderWidth;
|
|
|
|
gfx->Save();
|
|
gfx->Clip(NSRectToSnappedRect(clipRect.GetPhysicalRect(wm, rect.width),
|
|
appUnitsPerDevPixel, *drawTarget));
|
|
nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
|
|
aDirtyRect, rect, mStyleContext);
|
|
gfx->Restore();
|
|
|
|
// draw remainder of the border (omitting the block-start side)
|
|
clipRect = LogicalRect(wm, rect, rect.width);
|
|
clipRect.BStart(wm) += legendBorderWidth;
|
|
clipRect.BSize(wm) =
|
|
GetLogicalRect(rect.width).BSize(wm) - (off + legendBorderWidth);
|
|
|
|
gfx->Save();
|
|
gfx->Clip(NSRectToSnappedRect(clipRect.GetPhysicalRect(wm, rect.width),
|
|
appUnitsPerDevPixel, *drawTarget));
|
|
nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
|
|
aDirtyRect, rect, mStyleContext);
|
|
gfx->Restore();
|
|
} else {
|
|
nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
|
|
aDirtyRect,
|
|
nsRect(aPt, mRect.Size()),
|
|
mStyleContext);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
nscoord
|
|
nsFieldSetFrame::GetIntrinsicISize(nsRenderingContext* aRenderingContext,
|
|
nsLayoutUtils::IntrinsicISizeType aType)
|
|
{
|
|
nscoord legendWidth = 0;
|
|
nscoord contentWidth = 0;
|
|
if (nsIFrame* legend = GetLegend()) {
|
|
legendWidth =
|
|
nsLayoutUtils::IntrinsicForContainer(aRenderingContext, legend, aType);
|
|
}
|
|
|
|
if (nsIFrame* inner = GetInner()) {
|
|
// Ignore padding on the inner, since the padding will be applied to the
|
|
// outer instead, and the padding computed for the inner is wrong
|
|
// for percentage padding.
|
|
contentWidth =
|
|
nsLayoutUtils::IntrinsicForContainer(aRenderingContext, inner, aType,
|
|
nsLayoutUtils::IGNORE_PADDING);
|
|
}
|
|
|
|
return std::max(legendWidth, contentWidth);
|
|
}
|
|
|
|
|
|
nscoord
|
|
nsFieldSetFrame::GetMinISize(nsRenderingContext* aRenderingContext)
|
|
{
|
|
nscoord result = 0;
|
|
DISPLAY_MIN_WIDTH(this, result);
|
|
|
|
result = GetIntrinsicISize(aRenderingContext, nsLayoutUtils::MIN_ISIZE);
|
|
return result;
|
|
}
|
|
|
|
nscoord
|
|
nsFieldSetFrame::GetPrefISize(nsRenderingContext* aRenderingContext)
|
|
{
|
|
nscoord result = 0;
|
|
DISPLAY_PREF_WIDTH(this, result);
|
|
|
|
result = GetIntrinsicISize(aRenderingContext, nsLayoutUtils::PREF_ISIZE);
|
|
return result;
|
|
}
|
|
|
|
/* virtual */
|
|
LogicalSize
|
|
nsFieldSetFrame::ComputeSize(nsRenderingContext *aRenderingContext,
|
|
WritingMode aWM,
|
|
const LogicalSize& aCBSize,
|
|
nscoord aAvailableISize,
|
|
const LogicalSize& aMargin,
|
|
const LogicalSize& aBorder,
|
|
const LogicalSize& aPadding,
|
|
ComputeSizeFlags aFlags)
|
|
{
|
|
LogicalSize result =
|
|
nsContainerFrame::ComputeSize(aRenderingContext, aWM,
|
|
aCBSize, aAvailableISize,
|
|
aMargin, aBorder, aPadding, aFlags);
|
|
|
|
// XXX The code below doesn't make sense if the caller's writing mode
|
|
// is orthogonal to this frame's. Not sure yet what should happen then;
|
|
// for now, just bail out.
|
|
if (aWM.IsVertical() != GetWritingMode().IsVertical()) {
|
|
return result;
|
|
}
|
|
|
|
// Fieldsets never shrink below their min width.
|
|
|
|
// If we're a container for font size inflation, then shrink
|
|
// wrapping inside of us should not apply font size inflation.
|
|
AutoMaybeDisableFontInflation an(this);
|
|
|
|
nscoord minISize = GetMinISize(aRenderingContext);
|
|
if (minISize > result.ISize(aWM)) {
|
|
result.ISize(aWM) = minISize;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void
|
|
nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
const nsHTMLReflowState& aReflowState,
|
|
nsReflowStatus& aStatus)
|
|
{
|
|
MarkInReflow();
|
|
DO_GLOBAL_REFLOW_COUNT("nsFieldSetFrame");
|
|
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
|
|
|
NS_PRECONDITION(aReflowState.ComputedISize() != NS_INTRINSICSIZE,
|
|
"Should have a precomputed inline-size!");
|
|
|
|
// Initialize OUT parameter
|
|
aStatus = NS_FRAME_COMPLETE;
|
|
|
|
nsOverflowAreas ocBounds;
|
|
nsReflowStatus ocStatus = NS_FRAME_COMPLETE;
|
|
if (GetPrevInFlow()) {
|
|
ReflowOverflowContainerChildren(aPresContext, aReflowState, ocBounds, 0,
|
|
ocStatus);
|
|
}
|
|
|
|
//------------ Handle Incremental Reflow -----------------
|
|
bool reflowInner;
|
|
bool reflowLegend;
|
|
nsIFrame* legend = GetLegend();
|
|
nsIFrame* inner = GetInner();
|
|
if (aReflowState.ShouldReflowAllKids()) {
|
|
reflowInner = inner != nullptr;
|
|
reflowLegend = legend != nullptr;
|
|
} else {
|
|
reflowInner = inner && NS_SUBTREE_DIRTY(inner);
|
|
reflowLegend = legend && NS_SUBTREE_DIRTY(legend);
|
|
}
|
|
|
|
// We don't allow fieldsets to break vertically. If we did, we'd
|
|
// need logic here to push and pull overflow frames.
|
|
// Since we're not applying our padding in this frame, we need to add it here
|
|
// to compute the available width for our children.
|
|
WritingMode wm = GetWritingMode();
|
|
WritingMode innerWM = inner ? inner->GetWritingMode() : wm;
|
|
WritingMode legendWM = legend ? legend->GetWritingMode() : wm;
|
|
LogicalSize innerAvailSize = aReflowState.ComputedSizeWithPadding(innerWM);
|
|
LogicalSize legendAvailSize = aReflowState.ComputedSizeWithPadding(legendWM);
|
|
innerAvailSize.BSize(innerWM) = legendAvailSize.BSize(legendWM) =
|
|
NS_UNCONSTRAINEDSIZE;
|
|
NS_ASSERTION(!inner ||
|
|
nsLayoutUtils::IntrinsicForContainer(aReflowState.rendContext,
|
|
inner,
|
|
nsLayoutUtils::MIN_ISIZE) <=
|
|
innerAvailSize.ISize(innerWM),
|
|
"Bogus availSize.ISize; should be bigger");
|
|
NS_ASSERTION(!legend ||
|
|
nsLayoutUtils::IntrinsicForContainer(aReflowState.rendContext,
|
|
legend,
|
|
nsLayoutUtils::MIN_ISIZE) <=
|
|
legendAvailSize.ISize(legendWM),
|
|
"Bogus availSize.ISize; should be bigger");
|
|
|
|
// get our border and padding
|
|
LogicalMargin border = aReflowState.ComputedLogicalBorderPadding() -
|
|
aReflowState.ComputedLogicalPadding();
|
|
|
|
// Figure out how big the legend is if there is one.
|
|
// get the legend's margin
|
|
LogicalMargin legendMargin(wm);
|
|
// reflow the legend only if needed
|
|
Maybe<nsHTMLReflowState> legendReflowState;
|
|
if (legend) {
|
|
legendReflowState.emplace(aPresContext, aReflowState, legend,
|
|
legendAvailSize);
|
|
}
|
|
if (reflowLegend) {
|
|
nsHTMLReflowMetrics legendDesiredSize(aReflowState);
|
|
|
|
ReflowChild(legend, aPresContext, legendDesiredSize, *legendReflowState,
|
|
wm, LogicalPoint(wm), 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
|
|
#ifdef NOISY_REFLOW
|
|
printf(" returned (%d, %d)\n",
|
|
legendDesiredSize.Width(), legendDesiredSize.Height());
|
|
#endif
|
|
// figure out the legend's rectangle
|
|
legendMargin = legend->GetLogicalUsedMargin(wm);
|
|
mLegendRect =
|
|
LogicalRect(wm, 0, 0,
|
|
legendDesiredSize.ISize(wm) + legendMargin.IStartEnd(wm),
|
|
legendDesiredSize.BSize(wm) + legendMargin.BStartEnd(wm));
|
|
nscoord oldSpace = mLegendSpace;
|
|
mLegendSpace = 0;
|
|
if (mLegendRect.BSize(wm) > border.BStart(wm)) {
|
|
// center the border on the legend
|
|
mLegendSpace = mLegendRect.BSize(wm) - border.BStart(wm);
|
|
} else {
|
|
mLegendRect.BStart(wm) =
|
|
(border.BStart(wm) - mLegendRect.BSize(wm)) / 2;
|
|
}
|
|
|
|
// if the legend space changes then we need to reflow the
|
|
// content area as well.
|
|
if (mLegendSpace != oldSpace && inner) {
|
|
reflowInner = true;
|
|
}
|
|
|
|
// We'll move the legend to its proper place later.
|
|
FinishReflowChild(legend, aPresContext, legendDesiredSize,
|
|
legendReflowState.ptr(), wm, LogicalPoint(wm), 0,
|
|
NS_FRAME_NO_MOVE_FRAME);
|
|
} else if (!legend) {
|
|
mLegendRect.SetEmpty();
|
|
mLegendSpace = 0;
|
|
} else {
|
|
// mLegendSpace and mLegendRect haven't changed, but we need
|
|
// the used margin when placing the legend.
|
|
legendMargin = legend->GetLogicalUsedMargin(wm);
|
|
}
|
|
|
|
nscoord containerWidth = (wm.IsVertical() ? mLegendSpace : 0) +
|
|
border.LeftRight(wm);
|
|
// reflow the content frame only if needed
|
|
if (reflowInner) {
|
|
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, inner,
|
|
innerAvailSize, nullptr,
|
|
nsHTMLReflowState::CALLER_WILL_INIT);
|
|
// Override computed padding, in case it's percentage padding
|
|
kidReflowState.Init(aPresContext, nullptr, nullptr,
|
|
&aReflowState.ComputedPhysicalPadding());
|
|
// Our child is "height:100%" but we actually want its height to be reduced
|
|
// by the amount of content-height the legend is eating up, unless our
|
|
// height is unconstrained (in which case the child's will be too).
|
|
if (aReflowState.ComputedBSize() != NS_UNCONSTRAINEDSIZE) {
|
|
kidReflowState.SetComputedBSize(
|
|
std::max(0, aReflowState.ComputedBSize() - mLegendSpace));
|
|
}
|
|
|
|
if (aReflowState.ComputedMinBSize() > 0) {
|
|
kidReflowState.ComputedMinBSize() =
|
|
std::max(0, aReflowState.ComputedMinBSize() - mLegendSpace);
|
|
}
|
|
|
|
if (aReflowState.ComputedMaxBSize() != NS_UNCONSTRAINEDSIZE) {
|
|
kidReflowState.ComputedMaxBSize() =
|
|
std::max(0, aReflowState.ComputedMaxBSize() - mLegendSpace);
|
|
}
|
|
|
|
nsHTMLReflowMetrics kidDesiredSize(kidReflowState,
|
|
aDesiredSize.mFlags);
|
|
// Reflow the frame
|
|
NS_ASSERTION(kidReflowState.ComputedPhysicalMargin() == nsMargin(0,0,0,0),
|
|
"Margins on anonymous fieldset child not supported!");
|
|
LogicalPoint pt(wm, border.IStart(wm), border.BStart(wm) + mLegendSpace);
|
|
|
|
ReflowChild(inner, aPresContext, kidDesiredSize, kidReflowState,
|
|
wm, pt, containerWidth, 0, aStatus);
|
|
|
|
// update the container width after reflowing the inner frame
|
|
FinishReflowChild(inner, aPresContext, kidDesiredSize,
|
|
&kidReflowState, wm, pt,
|
|
containerWidth + kidDesiredSize.Width(), 0);
|
|
NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus);
|
|
}
|
|
|
|
if (inner) {
|
|
containerWidth += inner->GetSize().width;
|
|
}
|
|
|
|
LogicalRect contentRect(wm);
|
|
if (inner) {
|
|
// We don't support margins on inner, so our content rect is just the
|
|
// inner's border-box. We don't care about container-width at this point,
|
|
// as we'll figure out the actual positioning later.
|
|
contentRect = inner->GetLogicalRect(wm, containerWidth);
|
|
}
|
|
|
|
// Our content rect must fill up the available width
|
|
LogicalSize availSize = aReflowState.ComputedSizeWithPadding(wm);
|
|
if (availSize.ISize(wm) > contentRect.ISize(wm)) {
|
|
contentRect.ISize(wm) = innerAvailSize.ISize(wm);
|
|
}
|
|
|
|
if (legend) {
|
|
// The legend is positioned inline-wards within the inner's content rect
|
|
// (so that padding on the fieldset affects the legend position).
|
|
LogicalRect innerContentRect = contentRect;
|
|
innerContentRect.Deflate(wm, aReflowState.ComputedLogicalPadding());
|
|
// If the inner content rect is larger than the legend, we can align the
|
|
// legend.
|
|
if (innerContentRect.ISize(wm) > mLegendRect.ISize(wm)) {
|
|
int32_t align = static_cast<nsLegendFrame*>
|
|
(legend->GetContentInsertionFrame())->GetAlign();
|
|
if (!wm.IsBidiLTR()) {
|
|
if (align == NS_STYLE_TEXT_ALIGN_LEFT ||
|
|
align == NS_STYLE_TEXT_ALIGN_MOZ_LEFT) {
|
|
align = NS_STYLE_TEXT_ALIGN_END;
|
|
} else if (align == NS_STYLE_TEXT_ALIGN_RIGHT ||
|
|
align == NS_STYLE_TEXT_ALIGN_MOZ_RIGHT) {
|
|
align = NS_STYLE_TEXT_ALIGN_DEFAULT;
|
|
}
|
|
}
|
|
switch (align) {
|
|
case NS_STYLE_TEXT_ALIGN_END:
|
|
mLegendRect.IStart(wm) =
|
|
innerContentRect.IEnd(wm) - mLegendRect.ISize(wm);
|
|
break;
|
|
case NS_STYLE_TEXT_ALIGN_CENTER:
|
|
case NS_STYLE_TEXT_ALIGN_MOZ_CENTER:
|
|
// Note: rounding removed; there doesn't seem to be any need
|
|
mLegendRect.IStart(wm) = innerContentRect.IStart(wm) +
|
|
(innerContentRect.ISize(wm) - mLegendRect.ISize(wm)) / 2;
|
|
break;
|
|
default:
|
|
mLegendRect.IStart(wm) = innerContentRect.IStart(wm);
|
|
break;
|
|
}
|
|
} else {
|
|
// otherwise make place for the legend
|
|
mLegendRect.IStart(wm) = innerContentRect.IStart(wm);
|
|
innerContentRect.ISize(wm) = mLegendRect.ISize(wm);
|
|
contentRect.ISize(wm) = mLegendRect.ISize(wm) +
|
|
aReflowState.ComputedLogicalPadding().IStartEnd(wm);
|
|
}
|
|
|
|
// place the legend
|
|
LogicalRect actualLegendRect = mLegendRect;
|
|
actualLegendRect.Deflate(wm, legendMargin);
|
|
LogicalPoint actualLegendPos(actualLegendRect.Origin(wm));
|
|
|
|
// Note that legend's writing mode may be different from the fieldset's,
|
|
// so we need to convert offsets before applying them to it (bug 1134534).
|
|
LogicalMargin offsets =
|
|
legendReflowState->ComputedLogicalOffsets().
|
|
ConvertTo(wm, legendReflowState->GetWritingMode());
|
|
nsHTMLReflowState::ApplyRelativePositioning(legend, wm, offsets,
|
|
&actualLegendPos,
|
|
containerWidth);
|
|
|
|
legend->SetPosition(wm, actualLegendPos, containerWidth);
|
|
nsContainerFrame::PositionFrameView(legend);
|
|
nsContainerFrame::PositionChildViews(legend);
|
|
}
|
|
|
|
// Return our size and our result.
|
|
LogicalSize finalSize(wm, contentRect.ISize(wm) + border.IStartEnd(wm),
|
|
mLegendSpace + border.BStartEnd(wm) +
|
|
(inner ? inner->BSize(wm) : 0));
|
|
aDesiredSize.SetSize(wm, finalSize);
|
|
aDesiredSize.SetOverflowAreasToDesiredBounds();
|
|
|
|
if (legend) {
|
|
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, legend);
|
|
}
|
|
if (inner) {
|
|
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, inner);
|
|
}
|
|
|
|
// Merge overflow container bounds and status.
|
|
aDesiredSize.mOverflowAreas.UnionWith(ocBounds);
|
|
NS_MergeReflowStatusInto(&aStatus, ocStatus);
|
|
|
|
FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus);
|
|
|
|
InvalidateFrame();
|
|
|
|
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
void
|
|
nsFieldSetFrame::SetInitialChildList(ChildListID aListID,
|
|
nsFrameList& aChildList)
|
|
{
|
|
nsContainerFrame::SetInitialChildList(kPrincipalList, aChildList);
|
|
MOZ_ASSERT(GetInner());
|
|
}
|
|
void
|
|
nsFieldSetFrame::AppendFrames(ChildListID aListID,
|
|
nsFrameList& aFrameList)
|
|
{
|
|
MOZ_CRASH("nsFieldSetFrame::AppendFrames not supported");
|
|
}
|
|
|
|
void
|
|
nsFieldSetFrame::InsertFrames(ChildListID aListID,
|
|
nsIFrame* aPrevFrame,
|
|
nsFrameList& aFrameList)
|
|
{
|
|
MOZ_CRASH("nsFieldSetFrame::InsertFrames not supported");
|
|
}
|
|
|
|
void
|
|
nsFieldSetFrame::RemoveFrame(ChildListID aListID,
|
|
nsIFrame* aOldFrame)
|
|
{
|
|
MOZ_CRASH("nsFieldSetFrame::RemoveFrame not supported");
|
|
}
|
|
#endif
|
|
|
|
#ifdef ACCESSIBILITY
|
|
a11y::AccType
|
|
nsFieldSetFrame::AccessibleType()
|
|
{
|
|
return a11y::eHTMLGroupboxType;
|
|
}
|
|
#endif
|
|
|
|
nscoord
|
|
nsFieldSetFrame::GetLogicalBaseline(WritingMode aWritingMode) const
|
|
{
|
|
nsIFrame* inner = GetInner();
|
|
return inner->BStart(aWritingMode, GetParent()->GetSize().width) +
|
|
inner->GetLogicalBaseline(aWritingMode);
|
|
}
|