Line data Source code
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/. */
6 :
7 : #include "GridLines.h"
8 :
9 : #include "GridDimension.h"
10 : #include "GridLine.h"
11 : #include "mozilla/dom/GridBinding.h"
12 : #include "nsGridContainerFrame.h"
13 :
14 : namespace mozilla {
15 : namespace dom {
16 :
17 0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(GridLines, mParent, mLines)
18 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(GridLines)
19 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(GridLines)
20 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GridLines)
21 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
22 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
23 0 : NS_INTERFACE_MAP_END
24 :
25 0 : GridLines::GridLines(GridDimension* aParent)
26 0 : : mParent(aParent)
27 : {
28 0 : MOZ_ASSERT(aParent,
29 : "Should never be instantiated with a null GridDimension");
30 0 : }
31 :
32 0 : GridLines::~GridLines()
33 : {
34 0 : }
35 :
36 : JSObject*
37 0 : GridLines::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
38 : {
39 0 : return GridLinesBinding::Wrap(aCx, this, aGivenProto);
40 : }
41 :
42 : uint32_t
43 0 : GridLines::Length() const
44 : {
45 0 : return mLines.Length();
46 : }
47 :
48 : GridLine*
49 0 : GridLines::Item(uint32_t aIndex)
50 : {
51 0 : return mLines.SafeElementAt(aIndex);
52 : }
53 :
54 : GridLine*
55 0 : GridLines::IndexedGetter(uint32_t aIndex,
56 : bool& aFound)
57 : {
58 0 : aFound = aIndex < mLines.Length();
59 0 : if (!aFound) {
60 0 : return nullptr;
61 : }
62 0 : return mLines[aIndex];
63 : }
64 :
65 : void
66 0 : GridLines::SetLineInfo(const ComputedGridTrackInfo* aTrackInfo,
67 : const ComputedGridLineInfo* aLineInfo,
68 : const nsTArray<RefPtr<GridArea>>& aAreas,
69 : bool aIsRow)
70 : {
71 0 : MOZ_ASSERT(aLineInfo);
72 0 : mLines.Clear();
73 :
74 0 : if (!aTrackInfo) {
75 0 : return;
76 : }
77 :
78 0 : uint32_t trackCount = aTrackInfo->mEndFragmentTrack -
79 0 : aTrackInfo->mStartFragmentTrack;
80 :
81 : // If there is at least one track, line count is one more
82 : // than the number of tracks.
83 0 : if (trackCount > 0) {
84 0 : nscoord lastTrackEdge = 0;
85 : nscoord startOfNextTrack;
86 0 : uint32_t repeatIndex = 0;
87 0 : uint32_t numRepeatTracks = aTrackInfo->mRemovedRepeatTracks.Length();
88 0 : uint32_t numAddedLines = 0;
89 :
90 0 : for (uint32_t i = aTrackInfo->mStartFragmentTrack;
91 0 : i < aTrackInfo->mEndFragmentTrack + 1;
92 : i++) {
93 : // Since line indexes are 1-based, calculate a 1-based value
94 : // for this track to simplify some calculations.
95 0 : const uint32_t line1Index = i + 1;
96 :
97 0 : startOfNextTrack = (i < aTrackInfo->mEndFragmentTrack) ?
98 0 : aTrackInfo->mPositions[i] :
99 : lastTrackEdge;
100 :
101 0 : nsTArray<nsString> lineNames;
102 0 : lineNames = aLineInfo->mNames.SafeElementAt(i, nsTArray<nsString>());
103 :
104 : // Add in names from grid areas where this line is used as a boundary.
105 0 : for (auto area : aAreas) {
106 0 : bool haveNameToAdd = false;
107 0 : nsAutoString nameToAdd;
108 0 : area->GetName(nameToAdd);
109 0 : if (aIsRow) {
110 0 : if (area->RowStart() == line1Index) {
111 0 : haveNameToAdd = true;
112 0 : nameToAdd.AppendLiteral("-start");
113 0 : } else if (area->RowEnd() == line1Index) {
114 0 : haveNameToAdd = true;
115 0 : nameToAdd.AppendLiteral("-end");
116 : }
117 : } else {
118 0 : if (area->ColumnStart() == line1Index) {
119 0 : haveNameToAdd = true;
120 0 : nameToAdd.AppendLiteral("-start");
121 0 : } else if (area->ColumnEnd() == line1Index) {
122 0 : haveNameToAdd = true;
123 0 : nameToAdd.AppendLiteral("-end");
124 : }
125 : }
126 :
127 0 : if (haveNameToAdd && !lineNames.Contains(nameToAdd)) {
128 0 : lineNames.AppendElement(nameToAdd);
129 : }
130 : }
131 :
132 0 : if (i >= aTrackInfo->mRepeatFirstTrack &&
133 0 : repeatIndex < numRepeatTracks) {
134 0 : numAddedLines += AppendRemovedAutoFits(aTrackInfo,
135 : aLineInfo,
136 : lastTrackEdge,
137 : repeatIndex,
138 : numRepeatTracks,
139 : lineNames);
140 : }
141 :
142 0 : RefPtr<GridLine> line = new GridLine(this);
143 0 : mLines.AppendElement(line);
144 0 : MOZ_ASSERT(line1Index > 0, "line1Index must be positive.");
145 : bool isBeforeFirstExplicit =
146 0 : (line1Index <= aTrackInfo->mNumLeadingImplicitTracks);
147 : // Calculate an actionable line number for this line, that could be used
148 : // in a css grid property to align a grid item or area at that line.
149 : // For implicit lines that appear before line 1, report a number of 0.
150 : // We can't report negative indexes, because those have a different
151 : // meaning in the css grid spec (negative indexes are negative-1-based
152 : // from the end of the grid decreasing towards the front).
153 0 : uint32_t lineNumber = isBeforeFirstExplicit ? 0 :
154 0 : (line1Index - aTrackInfo->mNumLeadingImplicitTracks + numAddedLines);
155 : GridDeclaration lineType =
156 0 : (isBeforeFirstExplicit ||
157 0 : line1Index > (aTrackInfo->mNumLeadingImplicitTracks +
158 0 : aTrackInfo->mNumExplicitTracks + 1))
159 0 : ? GridDeclaration::Implicit
160 0 : : GridDeclaration::Explicit;
161 0 : line->SetLineValues(
162 : lineNames,
163 : nsPresContext::AppUnitsToDoubleCSSPixels(lastTrackEdge),
164 : nsPresContext::AppUnitsToDoubleCSSPixels(startOfNextTrack -
165 : lastTrackEdge),
166 : lineNumber,
167 : lineType
168 0 : );
169 :
170 0 : if (i < aTrackInfo->mEndFragmentTrack) {
171 0 : lastTrackEdge = aTrackInfo->mPositions[i] + aTrackInfo->mSizes[i];
172 : }
173 : }
174 : }
175 : }
176 :
177 : uint32_t
178 0 : GridLines::AppendRemovedAutoFits(const ComputedGridTrackInfo* aTrackInfo,
179 : const ComputedGridLineInfo* aLineInfo,
180 : nscoord aLastTrackEdge,
181 : uint32_t& aRepeatIndex,
182 : uint32_t aNumRepeatTracks,
183 : nsTArray<nsString>& aLineNames)
184 : {
185 : // Check to see if lineNames contains ALL of the before line names.
186 0 : bool alreadyHasBeforeLineNames = true;
187 0 : for (const auto& beforeName : aLineInfo->mNamesBefore) {
188 0 : if (!aLineNames.Contains(beforeName)) {
189 0 : alreadyHasBeforeLineNames = false;
190 0 : break;
191 : }
192 : }
193 :
194 0 : bool extractedExplicitLineNames = false;
195 0 : nsTArray<nsString> explicitLineNames;
196 0 : uint32_t linesAdded = 0;
197 0 : while (aRepeatIndex < aNumRepeatTracks &&
198 0 : aTrackInfo->mRemovedRepeatTracks[aRepeatIndex]) {
199 : // If this is not the very first call to this function, and if we
200 : // haven't already added a line this call, pull all the explicit
201 : // names to pass along to the next line that will be added after
202 : // this function completes.
203 0 : if (aRepeatIndex > 0 &&
204 : linesAdded == 0) {
205 : // Find the names that didn't match the before or after names,
206 : // and extract them.
207 0 : for (const auto& name : aLineNames) {
208 0 : if (!aLineInfo->mNamesBefore.Contains(name) &&
209 0 : !aLineInfo->mNamesAfter.Contains(name)) {
210 0 : explicitLineNames.AppendElement(name);
211 : }
212 : }
213 0 : for (const auto& extractedName : explicitLineNames) {
214 0 : aLineNames.RemoveElement(extractedName);
215 : }
216 0 : extractedExplicitLineNames = true;
217 : }
218 :
219 : // If this is the second or later time through, or didn't already
220 : // have before names, add them.
221 0 : if (linesAdded > 0 || !alreadyHasBeforeLineNames) {
222 0 : aLineNames.AppendElements(aLineInfo->mNamesBefore);
223 : }
224 :
225 0 : RefPtr<GridLine> line = new GridLine(this);
226 0 : mLines.AppendElement(line);
227 0 : MOZ_ASSERT(aTrackInfo->mRepeatFirstTrack >=
228 : aTrackInfo->mNumLeadingImplicitTracks,
229 : "We shouldn't have a repeat track within the implicit tracks.");
230 0 : uint32_t lineNumber = aTrackInfo->mRepeatFirstTrack -
231 0 : aTrackInfo->mNumLeadingImplicitTracks + aRepeatIndex + 1;
232 0 : line->SetLineValues(
233 : aLineNames,
234 : nsPresContext::AppUnitsToDoubleCSSPixels(aLastTrackEdge),
235 : nsPresContext::AppUnitsToDoubleCSSPixels(0),
236 : lineNumber,
237 : GridDeclaration::Explicit
238 0 : );
239 :
240 : // No matter what, the next line should have the after names associated
241 : // with it. If we go through the loop again, the before names will also
242 : // be added.
243 0 : aLineNames = aLineInfo->mNamesAfter;
244 0 : aRepeatIndex++;
245 :
246 0 : linesAdded++;
247 : }
248 0 : aRepeatIndex++;
249 :
250 0 : if (extractedExplicitLineNames) {
251 : // Pass on the explicit names we saved to the next explicit line.
252 0 : aLineNames.AppendElements(explicitLineNames);
253 : }
254 :
255 0 : if (alreadyHasBeforeLineNames && linesAdded > 0) {
256 : // If we started with before names, pass them on to the next explicit
257 : // line.
258 0 : aLineNames.AppendElements(aLineInfo->mNamesBefore);
259 : }
260 0 : return linesAdded;
261 : }
262 :
263 : } // namespace dom
264 : } // namespace mozilla
|