264 lines
8.6 KiB
C++
264 lines
8.6 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* 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 "GridLines.h"
|
|
|
|
#include "GridArea.h"
|
|
#include "GridDimension.h"
|
|
#include "GridLine.h"
|
|
#include "mozilla/dom/GridBinding.h"
|
|
#include "nsGridContainerFrame.h"
|
|
|
|
namespace mozilla {
|
|
namespace dom {
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(GridLines, mParent, mLines)
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(GridLines)
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(GridLines)
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GridLines)
|
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
GridLines::GridLines(GridDimension* aParent)
|
|
: mParent(aParent)
|
|
{
|
|
MOZ_ASSERT(aParent,
|
|
"Should never be instantiated with a null GridDimension");
|
|
}
|
|
|
|
GridLines::~GridLines()
|
|
{
|
|
}
|
|
|
|
JSObject*
|
|
GridLines::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
|
{
|
|
return GridLinesBinding::Wrap(aCx, this, aGivenProto);
|
|
}
|
|
|
|
uint32_t
|
|
GridLines::Length() const
|
|
{
|
|
return mLines.Length();
|
|
}
|
|
|
|
GridLine*
|
|
GridLines::Item(uint32_t aIndex)
|
|
{
|
|
return mLines.SafeElementAt(aIndex);
|
|
}
|
|
|
|
GridLine*
|
|
GridLines::IndexedGetter(uint32_t aIndex,
|
|
bool& aFound)
|
|
{
|
|
aFound = aIndex < mLines.Length();
|
|
if (!aFound) {
|
|
return nullptr;
|
|
}
|
|
return mLines[aIndex];
|
|
}
|
|
|
|
void
|
|
GridLines::SetLineInfo(const ComputedGridTrackInfo* aTrackInfo,
|
|
const ComputedGridLineInfo* aLineInfo,
|
|
const nsTArray<RefPtr<GridArea>>& aAreas,
|
|
bool aIsRow)
|
|
{
|
|
MOZ_ASSERT(aLineInfo);
|
|
mLines.Clear();
|
|
|
|
if (!aTrackInfo) {
|
|
return;
|
|
}
|
|
|
|
uint32_t trackCount = aTrackInfo->mEndFragmentTrack -
|
|
aTrackInfo->mStartFragmentTrack;
|
|
|
|
// If there is at least one track, line count is one more
|
|
// than the number of tracks.
|
|
if (trackCount > 0) {
|
|
nscoord lastTrackEdge = 0;
|
|
nscoord startOfNextTrack;
|
|
uint32_t repeatIndex = 0;
|
|
uint32_t numRepeatTracks = aTrackInfo->mRemovedRepeatTracks.Length();
|
|
uint32_t numAddedLines = 0;
|
|
|
|
for (uint32_t i = aTrackInfo->mStartFragmentTrack;
|
|
i < aTrackInfo->mEndFragmentTrack + 1;
|
|
i++) {
|
|
// Since line indexes are 1-based, calculate a 1-based value
|
|
// for this track to simplify some calculations.
|
|
const uint32_t line1Index = i + 1;
|
|
|
|
startOfNextTrack = (i < aTrackInfo->mEndFragmentTrack) ?
|
|
aTrackInfo->mPositions[i] :
|
|
lastTrackEdge;
|
|
|
|
nsTArray<nsString> lineNames;
|
|
lineNames = aLineInfo->mNames.SafeElementAt(i, nsTArray<nsString>());
|
|
|
|
// Add in names from grid areas where this line is used as a boundary.
|
|
for (auto area : aAreas) {
|
|
bool haveNameToAdd = false;
|
|
nsAutoString nameToAdd;
|
|
area->GetName(nameToAdd);
|
|
if (aIsRow) {
|
|
if (area->RowStart() == line1Index) {
|
|
haveNameToAdd = true;
|
|
nameToAdd.AppendLiteral("-start");
|
|
} else if (area->RowEnd() == line1Index) {
|
|
haveNameToAdd = true;
|
|
nameToAdd.AppendLiteral("-end");
|
|
}
|
|
} else {
|
|
if (area->ColumnStart() == line1Index) {
|
|
haveNameToAdd = true;
|
|
nameToAdd.AppendLiteral("-start");
|
|
} else if (area->ColumnEnd() == line1Index) {
|
|
haveNameToAdd = true;
|
|
nameToAdd.AppendLiteral("-end");
|
|
}
|
|
}
|
|
|
|
if (haveNameToAdd && !lineNames.Contains(nameToAdd)) {
|
|
lineNames.AppendElement(nameToAdd);
|
|
}
|
|
}
|
|
|
|
if (i >= (aTrackInfo->mRepeatFirstTrack +
|
|
aTrackInfo->mNumLeadingImplicitTracks) &&
|
|
repeatIndex < numRepeatTracks) {
|
|
numAddedLines += AppendRemovedAutoFits(aTrackInfo,
|
|
aLineInfo,
|
|
lastTrackEdge,
|
|
repeatIndex,
|
|
numRepeatTracks,
|
|
lineNames);
|
|
}
|
|
|
|
RefPtr<GridLine> line = new GridLine(this);
|
|
mLines.AppendElement(line);
|
|
MOZ_ASSERT(line1Index > 0, "line1Index must be positive.");
|
|
bool isBeforeFirstExplicit =
|
|
(line1Index <= aTrackInfo->mNumLeadingImplicitTracks);
|
|
// Calculate an actionable line number for this line, that could be used
|
|
// in a css grid property to align a grid item or area at that line.
|
|
// For implicit lines that appear before line 1, report a number of 0.
|
|
// We can't report negative indexes, because those have a different
|
|
// meaning in the css grid spec (negative indexes are negative-1-based
|
|
// from the end of the grid decreasing towards the front).
|
|
uint32_t lineNumber = isBeforeFirstExplicit ? 0 :
|
|
(line1Index - aTrackInfo->mNumLeadingImplicitTracks + numAddedLines);
|
|
GridDeclaration lineType =
|
|
(isBeforeFirstExplicit ||
|
|
line1Index > (aTrackInfo->mNumLeadingImplicitTracks +
|
|
aTrackInfo->mNumExplicitTracks + 1))
|
|
? GridDeclaration::Implicit
|
|
: GridDeclaration::Explicit;
|
|
line->SetLineValues(
|
|
lineNames,
|
|
nsPresContext::AppUnitsToDoubleCSSPixels(lastTrackEdge),
|
|
nsPresContext::AppUnitsToDoubleCSSPixels(startOfNextTrack -
|
|
lastTrackEdge),
|
|
lineNumber,
|
|
lineType
|
|
);
|
|
|
|
if (i < aTrackInfo->mEndFragmentTrack) {
|
|
lastTrackEdge = aTrackInfo->mPositions[i] + aTrackInfo->mSizes[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
uint32_t
|
|
GridLines::AppendRemovedAutoFits(const ComputedGridTrackInfo* aTrackInfo,
|
|
const ComputedGridLineInfo* aLineInfo,
|
|
nscoord aLastTrackEdge,
|
|
uint32_t& aRepeatIndex,
|
|
uint32_t aNumRepeatTracks,
|
|
nsTArray<nsString>& aLineNames)
|
|
{
|
|
// Check to see if lineNames contains ALL of the before line names.
|
|
bool alreadyHasBeforeLineNames = true;
|
|
for (const auto& beforeName : aLineInfo->mNamesBefore) {
|
|
if (!aLineNames.Contains(beforeName)) {
|
|
alreadyHasBeforeLineNames = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool extractedExplicitLineNames = false;
|
|
nsTArray<nsString> explicitLineNames;
|
|
uint32_t linesAdded = 0;
|
|
while (aRepeatIndex < aNumRepeatTracks &&
|
|
aTrackInfo->mRemovedRepeatTracks[aRepeatIndex]) {
|
|
// If this is not the very first call to this function, and if we
|
|
// haven't already added a line this call, pull all the explicit
|
|
// names to pass along to the next line that will be added after
|
|
// this function completes.
|
|
if (aRepeatIndex > 0 &&
|
|
linesAdded == 0) {
|
|
// Find the names that didn't match the before or after names,
|
|
// and extract them.
|
|
for (const auto& name : aLineNames) {
|
|
if (!aLineInfo->mNamesBefore.Contains(name) &&
|
|
!aLineInfo->mNamesAfter.Contains(name)) {
|
|
explicitLineNames.AppendElement(name);
|
|
}
|
|
}
|
|
for (const auto& extractedName : explicitLineNames) {
|
|
aLineNames.RemoveElement(extractedName);
|
|
}
|
|
extractedExplicitLineNames = true;
|
|
}
|
|
|
|
// If this is the second or later time through, or didn't already
|
|
// have before names, add them.
|
|
if (linesAdded > 0 || !alreadyHasBeforeLineNames) {
|
|
aLineNames.AppendElements(aLineInfo->mNamesBefore);
|
|
}
|
|
|
|
RefPtr<GridLine> line = new GridLine(this);
|
|
mLines.AppendElement(line);
|
|
uint32_t lineNumber = aTrackInfo->mRepeatFirstTrack +
|
|
aRepeatIndex + 1;
|
|
line->SetLineValues(
|
|
aLineNames,
|
|
nsPresContext::AppUnitsToDoubleCSSPixels(aLastTrackEdge),
|
|
nsPresContext::AppUnitsToDoubleCSSPixels(0),
|
|
lineNumber,
|
|
GridDeclaration::Explicit
|
|
);
|
|
|
|
// No matter what, the next line should have the after names associated
|
|
// with it. If we go through the loop again, the before names will also
|
|
// be added.
|
|
aLineNames = aLineInfo->mNamesAfter;
|
|
aRepeatIndex++;
|
|
|
|
linesAdded++;
|
|
}
|
|
aRepeatIndex++;
|
|
|
|
if (extractedExplicitLineNames) {
|
|
// Pass on the explicit names we saved to the next explicit line.
|
|
aLineNames.AppendElements(explicitLineNames);
|
|
}
|
|
|
|
if (alreadyHasBeforeLineNames && linesAdded > 0) {
|
|
// If we started with before names, pass them on to the next explicit
|
|
// line.
|
|
aLineNames.AppendElements(aLineInfo->mNamesBefore);
|
|
}
|
|
return linesAdded;
|
|
}
|
|
|
|
} // namespace dom
|
|
} // namespace mozilla
|