no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / layout / mathml / nsMathMLTokenFrame.cpp
blob5481e6faec8b1bd732f188201b8a0b0aae492cfe
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsMathMLTokenFrame.h"
9 #include "mozilla/PresShell.h"
10 #include "nsLayoutUtils.h"
11 #include "nsPresContext.h"
12 #include "nsContentUtils.h"
13 #include "nsTextFrame.h"
14 #include "gfxContext.h"
15 #include <algorithm>
17 using namespace mozilla;
19 nsIFrame* NS_NewMathMLTokenFrame(PresShell* aPresShell, ComputedStyle* aStyle) {
20 return new (aPresShell)
21 nsMathMLTokenFrame(aStyle, aPresShell->GetPresContext());
24 NS_IMPL_FRAMEARENA_HELPERS(nsMathMLTokenFrame)
26 nsMathMLTokenFrame::~nsMathMLTokenFrame() = default;
28 NS_IMETHODIMP
29 nsMathMLTokenFrame::InheritAutomaticData(nsIFrame* aParent) {
30 // let the base class get the default from our parent
31 nsMathMLContainerFrame::InheritAutomaticData(aParent);
33 return NS_OK;
36 eMathMLFrameType nsMathMLTokenFrame::GetMathMLFrameType() {
37 // treat everything other than <mi> as ordinary...
38 if (!mContent->IsMathMLElement(nsGkAtoms::mi_)) {
39 return eMathMLFrameType_Ordinary;
42 StyleMathVariant mathVariant = StyleFont()->mMathVariant;
43 if ((mathVariant == StyleMathVariant::None &&
44 (StyleFont()->mFont.style.IsItalic() ||
45 HasAnyStateBits(NS_FRAME_IS_IN_SINGLE_CHAR_MI))) ||
46 mathVariant == StyleMathVariant::Italic ||
47 mathVariant == StyleMathVariant::BoldItalic ||
48 mathVariant == StyleMathVariant::SansSerifItalic ||
49 mathVariant == StyleMathVariant::SansSerifBoldItalic) {
50 return eMathMLFrameType_ItalicIdentifier;
52 return eMathMLFrameType_UprightIdentifier;
55 void nsMathMLTokenFrame::MarkTextFramesAsTokenMathML() {
56 nsIFrame* child = nullptr;
57 uint32_t childCount = 0;
59 // Set flags on child text frames
60 // - to force them to trim their leading and trailing whitespaces.
61 // - Indicate which frames are suitable for mathvariant
62 // - flag single character <mi> frames for special italic treatment
63 for (nsIFrame* childFrame = PrincipalChildList().FirstChild(); childFrame;
64 childFrame = childFrame->GetNextSibling()) {
65 for (nsIFrame* childFrame2 = childFrame->PrincipalChildList().FirstChild();
66 childFrame2; childFrame2 = childFrame2->GetNextSibling()) {
67 if (childFrame2->IsTextFrame()) {
68 childFrame2->AddStateBits(TEXT_IS_IN_TOKEN_MATHML);
69 child = childFrame2;
70 childCount++;
74 if (mContent->IsMathMLElement(nsGkAtoms::mi_) && childCount == 1) {
75 nsAutoString data;
76 nsContentUtils::GetNodeTextContent(mContent, false, data);
78 data.CompressWhitespace();
79 int32_t length = data.Length();
81 bool isSingleCharacter =
82 length == 1 || (length == 2 && NS_IS_HIGH_SURROGATE(data[0]));
84 if (isSingleCharacter) {
85 child->AddStateBits(NS_FRAME_IS_IN_SINGLE_CHAR_MI);
86 AddStateBits(NS_FRAME_IS_IN_SINGLE_CHAR_MI);
91 void nsMathMLTokenFrame::SetInitialChildList(ChildListID aListID,
92 nsFrameList&& aChildList) {
93 // First, let the base class do its work
94 nsMathMLContainerFrame::SetInitialChildList(aListID, std::move(aChildList));
95 MarkTextFramesAsTokenMathML();
98 void nsMathMLTokenFrame::AppendFrames(ChildListID aListID,
99 nsFrameList&& aChildList) {
100 nsMathMLContainerFrame::AppendFrames(aListID, std::move(aChildList));
101 MarkTextFramesAsTokenMathML();
104 void nsMathMLTokenFrame::InsertFrames(
105 ChildListID aListID, nsIFrame* aPrevFrame,
106 const nsLineList::iterator* aPrevFrameLine, nsFrameList&& aChildList) {
107 nsMathMLContainerFrame::InsertFrames(aListID, aPrevFrame, aPrevFrameLine,
108 std::move(aChildList));
109 MarkTextFramesAsTokenMathML();
112 void nsMathMLTokenFrame::Reflow(nsPresContext* aPresContext,
113 ReflowOutput& aDesiredSize,
114 const ReflowInput& aReflowInput,
115 nsReflowStatus& aStatus) {
116 MarkInReflow();
117 MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
119 mPresentationData.flags &= ~NS_MATHML_ERROR;
121 // initializations needed for empty markup like <mtag></mtag>
122 aDesiredSize.ClearSize();
123 aDesiredSize.SetBlockStartAscent(0);
124 aDesiredSize.mBoundingMetrics = nsBoundingMetrics();
126 for (nsIFrame* childFrame : PrincipalChildList()) {
127 // ask our children to compute their bounding metrics
128 ReflowOutput childDesiredSize(aReflowInput.GetWritingMode());
129 WritingMode wm = childFrame->GetWritingMode();
130 LogicalSize availSize = aReflowInput.ComputedSize(wm);
131 availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
132 ReflowInput childReflowInput(aPresContext, aReflowInput, childFrame,
133 availSize);
134 nsReflowStatus childStatus;
135 ReflowChild(childFrame, aPresContext, childDesiredSize, childReflowInput,
136 childStatus);
137 NS_ASSERTION(childStatus.IsComplete(),
138 "We gave the child unconstrained available block-size, so its "
139 "status should be complete!");
140 SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
141 childDesiredSize.mBoundingMetrics);
144 // place and size children
145 FinalizeReflow(aReflowInput.mRenderingContext->GetDrawTarget(), aDesiredSize);
147 aStatus.Reset(); // This type of frame can't be split.
150 // For token elements, mBoundingMetrics is computed at the ReflowToken
151 // pass, it is not computed here because our children may be text frames
152 // that do not implement the GetBoundingMetrics() interface.
153 /* virtual */
154 nsresult nsMathMLTokenFrame::Place(DrawTarget* aDrawTarget, bool aPlaceOrigin,
155 ReflowOutput& aDesiredSize) {
156 mBoundingMetrics = nsBoundingMetrics();
157 for (nsIFrame* childFrame : PrincipalChildList()) {
158 ReflowOutput childSize(aDesiredSize.GetWritingMode());
159 GetReflowAndBoundingMetricsFor(childFrame, childSize,
160 childSize.mBoundingMetrics, nullptr);
161 // compute and cache the bounding metrics
162 mBoundingMetrics += childSize.mBoundingMetrics;
165 RefPtr<nsFontMetrics> fm =
166 nsLayoutUtils::GetInflatedFontMetricsForFrame(this);
167 nscoord ascent = fm->MaxAscent();
168 nscoord descent = fm->MaxDescent();
170 aDesiredSize.mBoundingMetrics = mBoundingMetrics;
171 aDesiredSize.Width() = mBoundingMetrics.width;
172 aDesiredSize.SetBlockStartAscent(std::max(mBoundingMetrics.ascent, ascent));
173 aDesiredSize.Height() = aDesiredSize.BlockStartAscent() +
174 std::max(mBoundingMetrics.descent, descent);
176 if (aPlaceOrigin) {
177 nscoord dy, dx = 0;
178 for (nsIFrame* childFrame : PrincipalChildList()) {
179 ReflowOutput childSize(aDesiredSize.GetWritingMode());
180 GetReflowAndBoundingMetricsFor(childFrame, childSize,
181 childSize.mBoundingMetrics);
183 // place and size the child; (dx,0) makes the caret happy - bug 188146
184 dy = childSize.Height() == 0
186 : aDesiredSize.BlockStartAscent() - childSize.BlockStartAscent();
187 FinishReflowChild(childFrame, PresContext(), childSize, nullptr, dx, dy,
188 ReflowChildFlags::Default);
189 dx += childSize.Width();
193 SetReference(nsPoint(0, aDesiredSize.BlockStartAscent()));
195 return NS_OK;