1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/generic/nsBRFrame.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,261 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* rendering object for HTML <br> elements */ 1.10 + 1.11 +#include "nsCOMPtr.h" 1.12 +#include "nsFrame.h" 1.13 +#include "nsPresContext.h" 1.14 +#include "nsLineLayout.h" 1.15 +#include "nsStyleConsts.h" 1.16 +#include "nsGkAtoms.h" 1.17 +#include "nsRenderingContext.h" 1.18 +#include "nsLayoutUtils.h" 1.19 + 1.20 +//FOR SELECTION 1.21 +#include "nsIContent.h" 1.22 +//END INCLUDES FOR SELECTION 1.23 + 1.24 +using namespace mozilla; 1.25 + 1.26 +class BRFrame : public nsFrame { 1.27 +public: 1.28 + NS_DECL_FRAMEARENA_HELPERS 1.29 + 1.30 + friend nsIFrame* NS_NewBRFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); 1.31 + 1.32 + virtual ContentOffsets CalcContentOffsetsFromFramePoint(nsPoint aPoint) MOZ_OVERRIDE; 1.33 + 1.34 + virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) MOZ_OVERRIDE; 1.35 + virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset, 1.36 + bool aRespectClusters = true) MOZ_OVERRIDE; 1.37 + virtual FrameSearchResult PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, 1.38 + bool aIsKeyboardSelect, int32_t* aOffset, 1.39 + PeekWordState* aState) MOZ_OVERRIDE; 1.40 + 1.41 + virtual nsresult Reflow(nsPresContext* aPresContext, 1.42 + nsHTMLReflowMetrics& aDesiredSize, 1.43 + const nsHTMLReflowState& aReflowState, 1.44 + nsReflowStatus& aStatus) MOZ_OVERRIDE; 1.45 + virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext, 1.46 + InlineMinWidthData *aData) MOZ_OVERRIDE; 1.47 + virtual void AddInlinePrefWidth(nsRenderingContext *aRenderingContext, 1.48 + InlinePrefWidthData *aData) MOZ_OVERRIDE; 1.49 + virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; 1.50 + virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; 1.51 + virtual nsIAtom* GetType() const MOZ_OVERRIDE; 1.52 + virtual nscoord GetBaseline() const MOZ_OVERRIDE; 1.53 + 1.54 + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE 1.55 + { 1.56 + return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced | 1.57 + nsIFrame::eLineParticipant)); 1.58 + } 1.59 + 1.60 +#ifdef ACCESSIBILITY 1.61 + virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE; 1.62 +#endif 1.63 + 1.64 +protected: 1.65 + BRFrame(nsStyleContext* aContext) : nsFrame(aContext) {} 1.66 + virtual ~BRFrame(); 1.67 + 1.68 + nscoord mAscent; 1.69 +}; 1.70 + 1.71 +nsIFrame* 1.72 +NS_NewBRFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) 1.73 +{ 1.74 + return new (aPresShell) BRFrame(aContext); 1.75 +} 1.76 + 1.77 +NS_IMPL_FRAMEARENA_HELPERS(BRFrame) 1.78 + 1.79 +BRFrame::~BRFrame() 1.80 +{ 1.81 +} 1.82 + 1.83 +nsresult 1.84 +BRFrame::Reflow(nsPresContext* aPresContext, 1.85 + nsHTMLReflowMetrics& aMetrics, 1.86 + const nsHTMLReflowState& aReflowState, 1.87 + nsReflowStatus& aStatus) 1.88 +{ 1.89 + DO_GLOBAL_REFLOW_COUNT("BRFrame"); 1.90 + DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus); 1.91 + aMetrics.Height() = 0; // BR frames with height 0 are ignored in quirks 1.92 + // mode by nsLineLayout::VerticalAlignFrames . 1.93 + // However, it's not always 0. See below. 1.94 + aMetrics.Width() = 0; 1.95 + aMetrics.SetTopAscent(0); 1.96 + 1.97 + // Only when the BR is operating in a line-layout situation will it 1.98 + // behave like a BR. 1.99 + nsLineLayout* ll = aReflowState.mLineLayout; 1.100 + if (ll) { 1.101 + // Note that the compatibility mode check excludes AlmostStandards 1.102 + // mode, since this is the inline box model. See bug 161691. 1.103 + if ( ll->LineIsEmpty() || 1.104 + aPresContext->CompatibilityMode() == eCompatibility_FullStandards ) { 1.105 + // The line is logically empty; any whitespace is trimmed away. 1.106 + // 1.107 + // If this frame is going to terminate the line we know 1.108 + // that nothing else will go on the line. Therefore, in this 1.109 + // case, we provide some height for the BR frame so that it 1.110 + // creates some vertical whitespace. It's necessary to use the 1.111 + // line-height rather than the font size because the 1.112 + // quirks-mode fix that doesn't apply the block's min 1.113 + // line-height makes this necessary to make BR cause a line 1.114 + // of the full line-height 1.115 + 1.116 + // We also do this in strict mode because BR should act like a 1.117 + // normal inline frame. That line-height is used is important 1.118 + // here for cases where the line-height is less than 1. 1.119 + nsRefPtr<nsFontMetrics> fm; 1.120 + nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm), 1.121 + nsLayoutUtils::FontSizeInflationFor(this)); 1.122 + aReflowState.rendContext->SetFont(fm); // FIXME: maybe not needed? 1.123 + if (fm) { 1.124 + nscoord logicalHeight = aReflowState.CalcLineHeight(); 1.125 + aMetrics.Height() = logicalHeight; 1.126 + aMetrics.SetTopAscent(nsLayoutUtils::GetCenteredFontBaseline(fm, logicalHeight)); 1.127 + } 1.128 + else { 1.129 + aMetrics.SetTopAscent(aMetrics.Height() = 0); 1.130 + } 1.131 + 1.132 + // XXX temporary until I figure out a better solution; see the 1.133 + // code in nsLineLayout::VerticalAlignFrames that zaps minY/maxY 1.134 + // if the width is zero. 1.135 + // XXX This also fixes bug 10036! 1.136 + // Warning: nsTextControlFrame::CalculateSizeStandard depends on 1.137 + // the following line, see bug 228752. 1.138 + aMetrics.Width() = 1; 1.139 + } 1.140 + 1.141 + // Return our reflow status 1.142 + uint32_t breakType = aReflowState.mStyleDisplay->mBreakType; 1.143 + if (NS_STYLE_CLEAR_NONE == breakType) { 1.144 + breakType = NS_STYLE_CLEAR_LINE; 1.145 + } 1.146 + 1.147 + aStatus = NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER | 1.148 + NS_INLINE_MAKE_BREAK_TYPE(breakType); 1.149 + ll->SetLineEndsInBR(true); 1.150 + } 1.151 + else { 1.152 + aStatus = NS_FRAME_COMPLETE; 1.153 + } 1.154 + 1.155 + aMetrics.SetOverflowAreasToDesiredBounds(); 1.156 + 1.157 + mAscent = aMetrics.TopAscent(); 1.158 + 1.159 + NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics); 1.160 + return NS_OK; 1.161 +} 1.162 + 1.163 +/* virtual */ void 1.164 +BRFrame::AddInlineMinWidth(nsRenderingContext *aRenderingContext, 1.165 + nsIFrame::InlineMinWidthData *aData) 1.166 +{ 1.167 + aData->ForceBreak(aRenderingContext); 1.168 +} 1.169 + 1.170 +/* virtual */ void 1.171 +BRFrame::AddInlinePrefWidth(nsRenderingContext *aRenderingContext, 1.172 + nsIFrame::InlinePrefWidthData *aData) 1.173 +{ 1.174 + aData->ForceBreak(aRenderingContext); 1.175 +} 1.176 + 1.177 +/* virtual */ nscoord 1.178 +BRFrame::GetMinWidth(nsRenderingContext *aRenderingContext) 1.179 +{ 1.180 + nscoord result = 0; 1.181 + DISPLAY_MIN_WIDTH(this, result); 1.182 + return result; 1.183 +} 1.184 + 1.185 +/* virtual */ nscoord 1.186 +BRFrame::GetPrefWidth(nsRenderingContext *aRenderingContext) 1.187 +{ 1.188 + nscoord result = 0; 1.189 + DISPLAY_PREF_WIDTH(this, result); 1.190 + return result; 1.191 +} 1.192 + 1.193 +nsIAtom* 1.194 +BRFrame::GetType() const 1.195 +{ 1.196 + return nsGkAtoms::brFrame; 1.197 +} 1.198 + 1.199 +nscoord 1.200 +BRFrame::GetBaseline() const 1.201 +{ 1.202 + return mAscent; 1.203 +} 1.204 + 1.205 +nsIFrame::ContentOffsets BRFrame::CalcContentOffsetsFromFramePoint(nsPoint aPoint) 1.206 +{ 1.207 + ContentOffsets offsets; 1.208 + offsets.content = mContent->GetParent(); 1.209 + if (offsets.content) { 1.210 + offsets.offset = offsets.content->IndexOf(mContent); 1.211 + offsets.secondaryOffset = offsets.offset; 1.212 + offsets.associateWithNext = true; 1.213 + } 1.214 + return offsets; 1.215 +} 1.216 + 1.217 +nsIFrame::FrameSearchResult 1.218 +BRFrame::PeekOffsetNoAmount(bool aForward, int32_t* aOffset) 1.219 +{ 1.220 + NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range"); 1.221 + int32_t startOffset = *aOffset; 1.222 + // If we hit the end of a BR going backwards, go to its beginning and stay there. 1.223 + if (!aForward && startOffset != 0) { 1.224 + *aOffset = 0; 1.225 + return FOUND; 1.226 + } 1.227 + // Otherwise, stop if we hit the beginning, continue (forward) if we hit the end. 1.228 + return (startOffset == 0) ? FOUND : CONTINUE; 1.229 +} 1.230 + 1.231 +nsIFrame::FrameSearchResult 1.232 +BRFrame::PeekOffsetCharacter(bool aForward, int32_t* aOffset, 1.233 + bool aRespectClusters) 1.234 +{ 1.235 + NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range"); 1.236 + // Keep going. The actual line jumping will stop us. 1.237 + return CONTINUE; 1.238 +} 1.239 + 1.240 +nsIFrame::FrameSearchResult 1.241 +BRFrame::PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect, 1.242 + int32_t* aOffset, PeekWordState* aState) 1.243 +{ 1.244 + NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range"); 1.245 + // Keep going. The actual line jumping will stop us. 1.246 + return CONTINUE; 1.247 +} 1.248 + 1.249 +#ifdef ACCESSIBILITY 1.250 +a11y::AccType 1.251 +BRFrame::AccessibleType() 1.252 +{ 1.253 + nsIContent *parent = mContent->GetParent(); 1.254 + if (parent && parent->IsRootOfNativeAnonymousSubtree() && 1.255 + parent->GetChildCount() == 1) { 1.256 + // This <br> is the only node in a text control, therefore it is the hacky 1.257 + // "bogus node" used when there is no text in the control 1.258 + return a11y::eNoType; 1.259 + } 1.260 + 1.261 + return a11y::eHTMLBRType; 1.262 +} 1.263 +#endif 1.264 +