layout/generic/nsBRFrame.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /* rendering object for HTML <br> elements */
michael@0 7
michael@0 8 #include "nsCOMPtr.h"
michael@0 9 #include "nsFrame.h"
michael@0 10 #include "nsPresContext.h"
michael@0 11 #include "nsLineLayout.h"
michael@0 12 #include "nsStyleConsts.h"
michael@0 13 #include "nsGkAtoms.h"
michael@0 14 #include "nsRenderingContext.h"
michael@0 15 #include "nsLayoutUtils.h"
michael@0 16
michael@0 17 //FOR SELECTION
michael@0 18 #include "nsIContent.h"
michael@0 19 //END INCLUDES FOR SELECTION
michael@0 20
michael@0 21 using namespace mozilla;
michael@0 22
michael@0 23 class BRFrame : public nsFrame {
michael@0 24 public:
michael@0 25 NS_DECL_FRAMEARENA_HELPERS
michael@0 26
michael@0 27 friend nsIFrame* NS_NewBRFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
michael@0 28
michael@0 29 virtual ContentOffsets CalcContentOffsetsFromFramePoint(nsPoint aPoint) MOZ_OVERRIDE;
michael@0 30
michael@0 31 virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) MOZ_OVERRIDE;
michael@0 32 virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset,
michael@0 33 bool aRespectClusters = true) MOZ_OVERRIDE;
michael@0 34 virtual FrameSearchResult PeekOffsetWord(bool aForward, bool aWordSelectEatSpace,
michael@0 35 bool aIsKeyboardSelect, int32_t* aOffset,
michael@0 36 PeekWordState* aState) MOZ_OVERRIDE;
michael@0 37
michael@0 38 virtual nsresult Reflow(nsPresContext* aPresContext,
michael@0 39 nsHTMLReflowMetrics& aDesiredSize,
michael@0 40 const nsHTMLReflowState& aReflowState,
michael@0 41 nsReflowStatus& aStatus) MOZ_OVERRIDE;
michael@0 42 virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext,
michael@0 43 InlineMinWidthData *aData) MOZ_OVERRIDE;
michael@0 44 virtual void AddInlinePrefWidth(nsRenderingContext *aRenderingContext,
michael@0 45 InlinePrefWidthData *aData) MOZ_OVERRIDE;
michael@0 46 virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
michael@0 47 virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
michael@0 48 virtual nsIAtom* GetType() const MOZ_OVERRIDE;
michael@0 49 virtual nscoord GetBaseline() const MOZ_OVERRIDE;
michael@0 50
michael@0 51 virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE
michael@0 52 {
michael@0 53 return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced |
michael@0 54 nsIFrame::eLineParticipant));
michael@0 55 }
michael@0 56
michael@0 57 #ifdef ACCESSIBILITY
michael@0 58 virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE;
michael@0 59 #endif
michael@0 60
michael@0 61 protected:
michael@0 62 BRFrame(nsStyleContext* aContext) : nsFrame(aContext) {}
michael@0 63 virtual ~BRFrame();
michael@0 64
michael@0 65 nscoord mAscent;
michael@0 66 };
michael@0 67
michael@0 68 nsIFrame*
michael@0 69 NS_NewBRFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
michael@0 70 {
michael@0 71 return new (aPresShell) BRFrame(aContext);
michael@0 72 }
michael@0 73
michael@0 74 NS_IMPL_FRAMEARENA_HELPERS(BRFrame)
michael@0 75
michael@0 76 BRFrame::~BRFrame()
michael@0 77 {
michael@0 78 }
michael@0 79
michael@0 80 nsresult
michael@0 81 BRFrame::Reflow(nsPresContext* aPresContext,
michael@0 82 nsHTMLReflowMetrics& aMetrics,
michael@0 83 const nsHTMLReflowState& aReflowState,
michael@0 84 nsReflowStatus& aStatus)
michael@0 85 {
michael@0 86 DO_GLOBAL_REFLOW_COUNT("BRFrame");
michael@0 87 DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
michael@0 88 aMetrics.Height() = 0; // BR frames with height 0 are ignored in quirks
michael@0 89 // mode by nsLineLayout::VerticalAlignFrames .
michael@0 90 // However, it's not always 0. See below.
michael@0 91 aMetrics.Width() = 0;
michael@0 92 aMetrics.SetTopAscent(0);
michael@0 93
michael@0 94 // Only when the BR is operating in a line-layout situation will it
michael@0 95 // behave like a BR.
michael@0 96 nsLineLayout* ll = aReflowState.mLineLayout;
michael@0 97 if (ll) {
michael@0 98 // Note that the compatibility mode check excludes AlmostStandards
michael@0 99 // mode, since this is the inline box model. See bug 161691.
michael@0 100 if ( ll->LineIsEmpty() ||
michael@0 101 aPresContext->CompatibilityMode() == eCompatibility_FullStandards ) {
michael@0 102 // The line is logically empty; any whitespace is trimmed away.
michael@0 103 //
michael@0 104 // If this frame is going to terminate the line we know
michael@0 105 // that nothing else will go on the line. Therefore, in this
michael@0 106 // case, we provide some height for the BR frame so that it
michael@0 107 // creates some vertical whitespace. It's necessary to use the
michael@0 108 // line-height rather than the font size because the
michael@0 109 // quirks-mode fix that doesn't apply the block's min
michael@0 110 // line-height makes this necessary to make BR cause a line
michael@0 111 // of the full line-height
michael@0 112
michael@0 113 // We also do this in strict mode because BR should act like a
michael@0 114 // normal inline frame. That line-height is used is important
michael@0 115 // here for cases where the line-height is less than 1.
michael@0 116 nsRefPtr<nsFontMetrics> fm;
michael@0 117 nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
michael@0 118 nsLayoutUtils::FontSizeInflationFor(this));
michael@0 119 aReflowState.rendContext->SetFont(fm); // FIXME: maybe not needed?
michael@0 120 if (fm) {
michael@0 121 nscoord logicalHeight = aReflowState.CalcLineHeight();
michael@0 122 aMetrics.Height() = logicalHeight;
michael@0 123 aMetrics.SetTopAscent(nsLayoutUtils::GetCenteredFontBaseline(fm, logicalHeight));
michael@0 124 }
michael@0 125 else {
michael@0 126 aMetrics.SetTopAscent(aMetrics.Height() = 0);
michael@0 127 }
michael@0 128
michael@0 129 // XXX temporary until I figure out a better solution; see the
michael@0 130 // code in nsLineLayout::VerticalAlignFrames that zaps minY/maxY
michael@0 131 // if the width is zero.
michael@0 132 // XXX This also fixes bug 10036!
michael@0 133 // Warning: nsTextControlFrame::CalculateSizeStandard depends on
michael@0 134 // the following line, see bug 228752.
michael@0 135 aMetrics.Width() = 1;
michael@0 136 }
michael@0 137
michael@0 138 // Return our reflow status
michael@0 139 uint32_t breakType = aReflowState.mStyleDisplay->mBreakType;
michael@0 140 if (NS_STYLE_CLEAR_NONE == breakType) {
michael@0 141 breakType = NS_STYLE_CLEAR_LINE;
michael@0 142 }
michael@0 143
michael@0 144 aStatus = NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER |
michael@0 145 NS_INLINE_MAKE_BREAK_TYPE(breakType);
michael@0 146 ll->SetLineEndsInBR(true);
michael@0 147 }
michael@0 148 else {
michael@0 149 aStatus = NS_FRAME_COMPLETE;
michael@0 150 }
michael@0 151
michael@0 152 aMetrics.SetOverflowAreasToDesiredBounds();
michael@0 153
michael@0 154 mAscent = aMetrics.TopAscent();
michael@0 155
michael@0 156 NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
michael@0 157 return NS_OK;
michael@0 158 }
michael@0 159
michael@0 160 /* virtual */ void
michael@0 161 BRFrame::AddInlineMinWidth(nsRenderingContext *aRenderingContext,
michael@0 162 nsIFrame::InlineMinWidthData *aData)
michael@0 163 {
michael@0 164 aData->ForceBreak(aRenderingContext);
michael@0 165 }
michael@0 166
michael@0 167 /* virtual */ void
michael@0 168 BRFrame::AddInlinePrefWidth(nsRenderingContext *aRenderingContext,
michael@0 169 nsIFrame::InlinePrefWidthData *aData)
michael@0 170 {
michael@0 171 aData->ForceBreak(aRenderingContext);
michael@0 172 }
michael@0 173
michael@0 174 /* virtual */ nscoord
michael@0 175 BRFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
michael@0 176 {
michael@0 177 nscoord result = 0;
michael@0 178 DISPLAY_MIN_WIDTH(this, result);
michael@0 179 return result;
michael@0 180 }
michael@0 181
michael@0 182 /* virtual */ nscoord
michael@0 183 BRFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
michael@0 184 {
michael@0 185 nscoord result = 0;
michael@0 186 DISPLAY_PREF_WIDTH(this, result);
michael@0 187 return result;
michael@0 188 }
michael@0 189
michael@0 190 nsIAtom*
michael@0 191 BRFrame::GetType() const
michael@0 192 {
michael@0 193 return nsGkAtoms::brFrame;
michael@0 194 }
michael@0 195
michael@0 196 nscoord
michael@0 197 BRFrame::GetBaseline() const
michael@0 198 {
michael@0 199 return mAscent;
michael@0 200 }
michael@0 201
michael@0 202 nsIFrame::ContentOffsets BRFrame::CalcContentOffsetsFromFramePoint(nsPoint aPoint)
michael@0 203 {
michael@0 204 ContentOffsets offsets;
michael@0 205 offsets.content = mContent->GetParent();
michael@0 206 if (offsets.content) {
michael@0 207 offsets.offset = offsets.content->IndexOf(mContent);
michael@0 208 offsets.secondaryOffset = offsets.offset;
michael@0 209 offsets.associateWithNext = true;
michael@0 210 }
michael@0 211 return offsets;
michael@0 212 }
michael@0 213
michael@0 214 nsIFrame::FrameSearchResult
michael@0 215 BRFrame::PeekOffsetNoAmount(bool aForward, int32_t* aOffset)
michael@0 216 {
michael@0 217 NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
michael@0 218 int32_t startOffset = *aOffset;
michael@0 219 // If we hit the end of a BR going backwards, go to its beginning and stay there.
michael@0 220 if (!aForward && startOffset != 0) {
michael@0 221 *aOffset = 0;
michael@0 222 return FOUND;
michael@0 223 }
michael@0 224 // Otherwise, stop if we hit the beginning, continue (forward) if we hit the end.
michael@0 225 return (startOffset == 0) ? FOUND : CONTINUE;
michael@0 226 }
michael@0 227
michael@0 228 nsIFrame::FrameSearchResult
michael@0 229 BRFrame::PeekOffsetCharacter(bool aForward, int32_t* aOffset,
michael@0 230 bool aRespectClusters)
michael@0 231 {
michael@0 232 NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
michael@0 233 // Keep going. The actual line jumping will stop us.
michael@0 234 return CONTINUE;
michael@0 235 }
michael@0 236
michael@0 237 nsIFrame::FrameSearchResult
michael@0 238 BRFrame::PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
michael@0 239 int32_t* aOffset, PeekWordState* aState)
michael@0 240 {
michael@0 241 NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
michael@0 242 // Keep going. The actual line jumping will stop us.
michael@0 243 return CONTINUE;
michael@0 244 }
michael@0 245
michael@0 246 #ifdef ACCESSIBILITY
michael@0 247 a11y::AccType
michael@0 248 BRFrame::AccessibleType()
michael@0 249 {
michael@0 250 nsIContent *parent = mContent->GetParent();
michael@0 251 if (parent && parent->IsRootOfNativeAnonymousSubtree() &&
michael@0 252 parent->GetChildCount() == 1) {
michael@0 253 // This <br> is the only node in a text control, therefore it is the hacky
michael@0 254 // "bogus node" used when there is no text in the control
michael@0 255 return a11y::eNoType;
michael@0 256 }
michael@0 257
michael@0 258 return a11y::eHTMLBRType;
michael@0 259 }
michael@0 260 #endif
michael@0 261

mercurial