Improve performance of table drawing again.
This commit is contained in:
parent
43ca885eb6
commit
1190eea26a
|
@ -175,23 +175,17 @@ HTMLTableCellAccessible::Table() const
|
||||||
uint32_t
|
uint32_t
|
||||||
HTMLTableCellAccessible::ColIdx() const
|
HTMLTableCellAccessible::ColIdx() const
|
||||||
{
|
{
|
||||||
nsITableCellLayout* cellLayout = GetCellLayout();
|
nsTableCellFrame* cellFrame = GetCellFrame();
|
||||||
NS_ENSURE_TRUE(cellLayout, 0);
|
NS_ENSURE_TRUE(cellFrame, 0);
|
||||||
|
return cellFrame->ColIndex();
|
||||||
int32_t colIdx = 0;
|
|
||||||
cellLayout->GetColIndex(colIdx);
|
|
||||||
return colIdx > 0 ? static_cast<uint32_t>(colIdx) : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
HTMLTableCellAccessible::RowIdx() const
|
HTMLTableCellAccessible::RowIdx() const
|
||||||
{
|
{
|
||||||
nsITableCellLayout* cellLayout = GetCellLayout();
|
nsTableCellFrame* cellFrame = GetCellFrame();
|
||||||
NS_ENSURE_TRUE(cellLayout, 0);
|
NS_ENSURE_TRUE(cellFrame, 0);
|
||||||
|
return cellFrame->RowIndex();
|
||||||
int32_t rowIdx = 0;
|
|
||||||
cellLayout->GetRowIndex(rowIdx);
|
|
||||||
return rowIdx > 0 ? static_cast<uint32_t>(rowIdx) : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
|
@ -285,6 +279,12 @@ HTMLTableCellAccessible::GetCellLayout() const
|
||||||
return do_QueryFrame(mContent->GetPrimaryFrame());
|
return do_QueryFrame(mContent->GetPrimaryFrame());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsTableCellFrame*
|
||||||
|
HTMLTableCellAccessible::GetCellFrame() const
|
||||||
|
{
|
||||||
|
return do_QueryFrame(mContent->GetPrimaryFrame());
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLTableCellAccessible::GetCellIndexes(int32_t& aRowIdx, int32_t& aColIdx) const
|
HTMLTableCellAccessible::GetCellIndexes(int32_t& aRowIdx, int32_t& aColIdx) const
|
||||||
{
|
{
|
||||||
|
@ -520,11 +520,9 @@ HTMLTableAccessible::SelectedCellCount()
|
||||||
if (!cellFrame || !cellFrame->IsSelected())
|
if (!cellFrame || !cellFrame->IsSelected())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int32_t startRow = -1, startCol = -1;
|
uint32_t startRow = cellFrame->RowIndex();
|
||||||
cellFrame->GetRowIndex(startRow);
|
uint32_t startCol = cellFrame->ColIndex();
|
||||||
cellFrame->GetColIndex(startCol);
|
if (startRow == rowIdx && startCol == colIdx)
|
||||||
if (startRow >= 0 && (uint32_t)startRow == rowIdx &&
|
|
||||||
startCol >= 0 && (uint32_t)startCol == colIdx)
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -570,11 +568,9 @@ HTMLTableAccessible::SelectedCells(nsTArray<Accessible*>* aCells)
|
||||||
if (!cellFrame || !cellFrame->IsSelected())
|
if (!cellFrame || !cellFrame->IsSelected())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int32_t startCol = -1, startRow = -1;
|
uint32_t startRow = cellFrame->RowIndex();
|
||||||
cellFrame->GetRowIndex(startRow);
|
uint32_t startCol = cellFrame->ColIndex();
|
||||||
cellFrame->GetColIndex(startCol);
|
if (startRow != rowIdx || startCol != colIdx)
|
||||||
if ((startRow >= 0 && (uint32_t)startRow != rowIdx) ||
|
|
||||||
(startCol >= 0 && (uint32_t)startCol != colIdx))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Accessible* cell = mDoc->GetAccessible(cellFrame->GetContent());
|
Accessible* cell = mDoc->GetAccessible(cellFrame->GetContent());
|
||||||
|
@ -597,11 +593,9 @@ HTMLTableAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells)
|
||||||
if (!cellFrame || !cellFrame->IsSelected())
|
if (!cellFrame || !cellFrame->IsSelected())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int32_t startRow = -1, startCol = -1;
|
uint32_t startCol = cellFrame->ColIndex();
|
||||||
cellFrame->GetColIndex(startCol);
|
uint32_t startRow = cellFrame->RowIndex();
|
||||||
cellFrame->GetRowIndex(startRow);
|
if (startRow == rowIdx && startCol == colIdx)
|
||||||
if (startRow >= 0 && (uint32_t)startRow == rowIdx &&
|
|
||||||
startCol >= 0 && (uint32_t)startCol == colIdx)
|
|
||||||
aCells->AppendElement(CellIndexAt(rowIdx, colIdx));
|
aCells->AppendElement(CellIndexAt(rowIdx, colIdx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "TableCellAccessible.h"
|
#include "TableCellAccessible.h"
|
||||||
|
|
||||||
class nsITableCellLayout;
|
class nsITableCellLayout;
|
||||||
|
class nsTableCellFrame;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace a11y {
|
namespace a11y {
|
||||||
|
@ -53,6 +54,11 @@ protected:
|
||||||
*/
|
*/
|
||||||
nsITableCellLayout* GetCellLayout() const;
|
nsITableCellLayout* GetCellLayout() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the table cell frame.
|
||||||
|
*/
|
||||||
|
nsTableCellFrame* GetCellFrame() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return row and column indices of the cell.
|
* Return row and column indices of the cell.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1526,6 +1526,40 @@ nsAttrValue::ParseIntWithFallback(const nsAString& aString, int32_t aDefault,
|
||||||
SetIntValueAndType(val, eInteger, nonStrict ? &aString : nullptr);
|
SetIntValueAndType(val, eInteger, nonStrict ? &aString : nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAttrValue::ParseClampedNonNegativeInt(const nsAString& aString,
|
||||||
|
int32_t aDefault, int32_t aMin,
|
||||||
|
int32_t aMax)
|
||||||
|
{
|
||||||
|
ResetIfSet();
|
||||||
|
|
||||||
|
nsContentUtils::ParseHTMLIntegerResultFlags result;
|
||||||
|
int32_t val = nsContentUtils::ParseHTMLInteger(aString, &result);
|
||||||
|
bool nonStrict = (result & nsContentUtils::eParseHTMLInteger_IsPercent) ||
|
||||||
|
(result & nsContentUtils::eParseHTMLInteger_NonStandard) ||
|
||||||
|
(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput);
|
||||||
|
|
||||||
|
if (result & nsContentUtils::eParseHTMLInteger_ErrorOverflow) {
|
||||||
|
if (result & nsContentUtils::eParseHTMLInteger_Negative) {
|
||||||
|
val = aDefault;
|
||||||
|
} else {
|
||||||
|
val = aMax;
|
||||||
|
}
|
||||||
|
nonStrict = true;
|
||||||
|
} else if ((result & nsContentUtils::eParseHTMLInteger_Error) || val < 0) {
|
||||||
|
val = aDefault;
|
||||||
|
nonStrict = true;
|
||||||
|
} else if (val < aMin) {
|
||||||
|
val = aMin;
|
||||||
|
nonStrict = true;
|
||||||
|
} else if (val > aMax) {
|
||||||
|
val = aMax;
|
||||||
|
nonStrict = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetIntValueAndType(val, eInteger, nonStrict ? &aString : nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsAttrValue::ParseNonNegativeIntValue(const nsAString& aString)
|
nsAttrValue::ParseNonNegativeIntValue(const nsAString& aString)
|
||||||
{
|
{
|
||||||
|
|
|
@ -362,6 +362,19 @@ public:
|
||||||
*/
|
*/
|
||||||
bool ParseNonNegativeIntValue(const nsAString& aString);
|
bool ParseNonNegativeIntValue(const nsAString& aString);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a string value into a clamped non-negative integer.
|
||||||
|
* This method follows the rules for parsing non-negative integer from:
|
||||||
|
* https://html.spec.whatwg.org/multipage/infrastructure.html#clamped-to-the-range
|
||||||
|
*
|
||||||
|
* @param aString the string to parse
|
||||||
|
* @param aDefault value to return for negative or invalid values
|
||||||
|
* @param aMin minimum value
|
||||||
|
* @param aMax maximum value
|
||||||
|
*/
|
||||||
|
void ParseClampedNonNegativeInt(const nsAString& aString, int32_t aDefault,
|
||||||
|
int32_t aMin, int32_t aMax);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a string value into a positive integer.
|
* Parse a string value into a positive integer.
|
||||||
* This method follows the rules for parsing non-negative integer from:
|
* This method follows the rules for parsing non-negative integer from:
|
||||||
|
|
|
@ -1088,6 +1088,7 @@ nsContentUtils::ParseHTMLInteger(const nsAString& aValue,
|
||||||
int sign = 1;
|
int sign = 1;
|
||||||
if (*iter == char16_t('-')) {
|
if (*iter == char16_t('-')) {
|
||||||
sign = -1;
|
sign = -1;
|
||||||
|
result |= eParseHTMLInteger_Negative;
|
||||||
++iter;
|
++iter;
|
||||||
} else if (*iter == char16_t('+')) {
|
} else if (*iter == char16_t('+')) {
|
||||||
result |= eParseHTMLInteger_NonStandard;
|
result |= eParseHTMLInteger_NonStandard;
|
||||||
|
|
|
@ -445,7 +445,9 @@ public:
|
||||||
// Set if one or more error flags were set.
|
// Set if one or more error flags were set.
|
||||||
eParseHTMLInteger_Error = 1 << 3,
|
eParseHTMLInteger_Error = 1 << 3,
|
||||||
eParseHTMLInteger_ErrorNoValue = 1 << 4,
|
eParseHTMLInteger_ErrorNoValue = 1 << 4,
|
||||||
eParseHTMLInteger_ErrorOverflow = 1 << 5
|
eParseHTMLInteger_ErrorOverflow = 1 << 5,
|
||||||
|
// Use this flag to detect the difference between overflow and underflow
|
||||||
|
eParseHTMLInteger_Negative = 1 << 6,
|
||||||
};
|
};
|
||||||
static int32_t ParseHTMLInteger(const nsAString& aValue,
|
static int32_t ParseHTMLInteger(const nsAString& aValue,
|
||||||
ParseHTMLIntegerResultFlags *aResult);
|
ParseHTMLIntegerResultFlags *aResult);
|
||||||
|
|
|
@ -390,26 +390,16 @@ HTMLTableCellElement::ParseAttribute(int32_t aNamespaceID,
|
||||||
return aResult.ParseIntWithBounds(aValue, 0);
|
return aResult.ParseIntWithBounds(aValue, 0);
|
||||||
}
|
}
|
||||||
if (aAttribute == nsGkAtoms::colspan) {
|
if (aAttribute == nsGkAtoms::colspan) {
|
||||||
bool res = aResult.ParseIntWithBounds(aValue, -1);
|
aResult.ParseClampedNonNegativeInt(aValue, 1, 1, MAX_COLSPAN);
|
||||||
if (res) {
|
return true;
|
||||||
int32_t val = aResult.GetIntegerValue();
|
|
||||||
// reset large colspan values as IE and opera do
|
|
||||||
if (val > MAX_COLSPAN || val <= 0) {
|
|
||||||
aResult.SetTo(1, &aValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
if (aAttribute == nsGkAtoms::rowspan) {
|
if (aAttribute == nsGkAtoms::rowspan) {
|
||||||
bool res = aResult.ParseIntWithBounds(aValue, -1, MAX_ROWSPAN);
|
aResult.ParseClampedNonNegativeInt(aValue, 1, 0, MAX_ROWSPAN);
|
||||||
if (res) {
|
// quirks mode does not honor the special html 4 value of 0
|
||||||
int32_t val = aResult.GetIntegerValue();
|
if (aResult.GetIntegerValue() == 0 && InNavQuirksMode(OwnerDoc())) {
|
||||||
// quirks mode does not honor the special html 4 value of 0
|
|
||||||
if (val < 0 || (0 == val && InNavQuirksMode(OwnerDoc()))) {
|
|
||||||
aResult.SetTo(1, &aValue);
|
aResult.SetTo(1, &aValue);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return res;
|
return true;
|
||||||
}
|
}
|
||||||
if (aAttribute == nsGkAtoms::height) {
|
if (aAttribute == nsGkAtoms::height) {
|
||||||
return aResult.ParseSpecialIntValue(aValue);
|
return aResult.ParseSpecialIntValue(aValue);
|
||||||
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
}
|
}
|
||||||
void SetColSpan(uint32_t aColSpan, ErrorResult& aError)
|
void SetColSpan(uint32_t aColSpan, ErrorResult& aError)
|
||||||
{
|
{
|
||||||
SetHTMLIntAttr(nsGkAtoms::colspan, aColSpan, aError);
|
SetUnsignedIntAttr(nsGkAtoms::colspan, aColSpan, 1, aError);
|
||||||
}
|
}
|
||||||
uint32_t RowSpan() const
|
uint32_t RowSpan() const
|
||||||
{
|
{
|
||||||
|
@ -45,7 +45,7 @@ public:
|
||||||
}
|
}
|
||||||
void SetRowSpan(uint32_t aRowSpan, ErrorResult& aError)
|
void SetRowSpan(uint32_t aRowSpan, ErrorResult& aError)
|
||||||
{
|
{
|
||||||
SetHTMLIntAttr(nsGkAtoms::rowspan, aRowSpan, aError);
|
SetUnsignedIntAttr(nsGkAtoms::rowspan, aRowSpan, 1, aError);
|
||||||
}
|
}
|
||||||
//already_AddRefed<nsDOMTokenList> Headers() const;
|
//already_AddRefed<nsDOMTokenList> Headers() const;
|
||||||
void GetHeaders(DOMString& aHeaders)
|
void GetHeaders(DOMString& aHeaders)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "base/compiler_specific.h"
|
#include "base/compiler_specific.h"
|
||||||
#include "mozilla/ArrayUtils.h"
|
#include "mozilla/ArrayUtils.h"
|
||||||
#include "nsGkAtoms.h"
|
#include "nsGkAtoms.h"
|
||||||
|
#include "nsITableCellLayout.h" // for MAX_COLSPAN / MAX_ROWSPAN
|
||||||
#include "nsCRT.h"
|
#include "nsCRT.h"
|
||||||
#include "nsLayoutStylesheetCache.h"
|
#include "nsLayoutStylesheetCache.h"
|
||||||
#include "nsRuleData.h"
|
#include "nsRuleData.h"
|
||||||
|
@ -150,8 +151,9 @@ nsMathMLElement::ParseAttribute(int32_t aNamespaceID,
|
||||||
const nsAString& aValue,
|
const nsAString& aValue,
|
||||||
nsAttrValue& aResult)
|
nsAttrValue& aResult)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(IsMathMLElement());
|
||||||
if (aNamespaceID == kNameSpaceID_None) {
|
if (aNamespaceID == kNameSpaceID_None) {
|
||||||
if (IsMathMLElement(nsGkAtoms::math) && aAttribute == nsGkAtoms::mode) {
|
if (mNodeInfo->Equals(nsGkAtoms::math) && aAttribute == nsGkAtoms::mode) {
|
||||||
WarnDeprecated(nsGkAtoms::mode->GetUTF16String(),
|
WarnDeprecated(nsGkAtoms::mode->GetUTF16String(),
|
||||||
nsGkAtoms::display->GetUTF16String(), OwnerDoc());
|
nsGkAtoms::display->GetUTF16String(), OwnerDoc());
|
||||||
}
|
}
|
||||||
|
@ -165,6 +167,16 @@ nsMathMLElement::ParseAttribute(int32_t aNamespaceID,
|
||||||
aAttribute == nsGkAtoms::mathbackground_) {
|
aAttribute == nsGkAtoms::mathbackground_) {
|
||||||
return aResult.ParseColor(aValue);
|
return aResult.ParseColor(aValue);
|
||||||
}
|
}
|
||||||
|
if (mNodeInfo->Equals(nsGkAtoms::mtd_)) {
|
||||||
|
if (aAttribute == nsGkAtoms::columnspan_) {
|
||||||
|
aResult.ParseClampedNonNegativeInt(aValue, 1, 1, MAX_COLSPAN);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (aAttribute == nsGkAtoms::rowspan) {
|
||||||
|
aResult.ParseClampedNonNegativeInt(aValue, 1, 0, MAX_ROWSPAN);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nsMathMLElementBase::ParseAttribute(aNamespaceID, aAttribute,
|
return nsMathMLElementBase::ParseAttribute(aNamespaceID, aAttribute,
|
||||||
|
@ -209,6 +221,8 @@ static Element::MappedAttributeEntry sDirStyles[] = {
|
||||||
bool
|
bool
|
||||||
nsMathMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const
|
nsMathMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(IsMathMLElement());
|
||||||
|
|
||||||
static const MappedAttributeEntry* const mtableMap[] = {
|
static const MappedAttributeEntry* const mtableMap[] = {
|
||||||
sMtableStyles,
|
sMtableStyles,
|
||||||
sCommonPresStyles
|
sCommonPresStyles
|
||||||
|
@ -240,10 +254,10 @@ nsMathMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const
|
||||||
if (IsAnyOfMathMLElements(nsGkAtoms::mstyle_, nsGkAtoms::math))
|
if (IsAnyOfMathMLElements(nsGkAtoms::mstyle_, nsGkAtoms::math))
|
||||||
return FindAttributeDependence(aAttribute, mstyleMap);
|
return FindAttributeDependence(aAttribute, mstyleMap);
|
||||||
|
|
||||||
if (IsMathMLElement(nsGkAtoms::mtable_))
|
if (mNodeInfo->Equals(nsGkAtoms::mtable_))
|
||||||
return FindAttributeDependence(aAttribute, mtableMap);
|
return FindAttributeDependence(aAttribute, mtableMap);
|
||||||
|
|
||||||
if (IsMathMLElement(nsGkAtoms::mrow_))
|
if (mNodeInfo->Equals(nsGkAtoms::mrow_))
|
||||||
return FindAttributeDependence(aAttribute, mrowMap);
|
return FindAttributeDependence(aAttribute, mrowMap);
|
||||||
|
|
||||||
if (IsAnyOfMathMLElements(nsGkAtoms::maction_,
|
if (IsAnyOfMathMLElements(nsGkAtoms::maction_,
|
||||||
|
|
|
@ -2730,8 +2730,8 @@ HTMLEditor::GetCellDataAt(nsIDOMElement* aTable,
|
||||||
}
|
}
|
||||||
|
|
||||||
*aIsSelected = cellFrame->IsSelected();
|
*aIsSelected = cellFrame->IsSelected();
|
||||||
cellFrame->GetRowIndex(*aStartRowIndex);
|
*aStartRowIndex = cellFrame->RowIndex();
|
||||||
cellFrame->GetColIndex(*aStartColIndex);
|
*aStartColIndex = cellFrame->ColIndex();
|
||||||
*aRowSpan = cellFrame->GetRowSpan();
|
*aRowSpan = cellFrame->GetRowSpan();
|
||||||
*aColSpan = cellFrame->GetColSpan();
|
*aColSpan = cellFrame->GetColSpan();
|
||||||
*aActualRowSpan = tableFrame->GetEffectiveRowSpanAt(aRowIndex, aColIndex);
|
*aActualRowSpan = tableFrame->GetEffectiveRowSpanAt(aRowIndex, aColIndex);
|
||||||
|
|
|
@ -2882,16 +2882,15 @@ nsFrameSelection::UnselectCells(nsIContent *aTableContent,
|
||||||
nsTableCellFrame* cellFrame =
|
nsTableCellFrame* cellFrame =
|
||||||
tableFrame->GetCellFrameAt(curRowIndex, curColIndex);
|
tableFrame->GetCellFrameAt(curRowIndex, curColIndex);
|
||||||
|
|
||||||
int32_t origRowIndex, origColIndex;
|
uint32_t origRowIndex = cellFrame->RowIndex();
|
||||||
cellFrame->GetRowIndex(origRowIndex);
|
uint32_t origColIndex = cellFrame->ColIndex();
|
||||||
cellFrame->GetColIndex(origColIndex);
|
|
||||||
uint32_t actualRowSpan =
|
uint32_t actualRowSpan =
|
||||||
tableFrame->GetEffectiveRowSpanAt(origRowIndex, origColIndex);
|
tableFrame->GetEffectiveRowSpanAt(origRowIndex, origColIndex);
|
||||||
uint32_t actualColSpan =
|
uint32_t actualColSpan =
|
||||||
tableFrame->GetEffectiveColSpanAt(curRowIndex, curColIndex);
|
tableFrame->GetEffectiveColSpanAt(curRowIndex, curColIndex);
|
||||||
if (origRowIndex <= maxRowIndex && maxRowIndex >= 0 &&
|
if (origRowIndex <= static_cast<uint32_t>(maxRowIndex) && maxRowIndex >= 0 &&
|
||||||
origRowIndex + actualRowSpan - 1 >= static_cast<uint32_t>(minRowIndex) &&
|
origRowIndex + actualRowSpan - 1 >= static_cast<uint32_t>(minRowIndex) &&
|
||||||
origColIndex <= maxColIndex && maxColIndex >= 0 &&
|
origColIndex <= static_cast<uint32_t>(maxColIndex) && maxColIndex >= 0 &&
|
||||||
origColIndex + actualColSpan - 1 >= static_cast<uint32_t>(minColIndex)) {
|
origColIndex + actualColSpan - 1 >= static_cast<uint32_t>(minColIndex)) {
|
||||||
|
|
||||||
mDomSelections[index]->RemoveRange(range);
|
mDomSelections[index]->RemoveRange(range);
|
||||||
|
@ -2925,33 +2924,32 @@ nsFrameSelection::AddCellsToSelection(nsIContent *aTableContent,
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
nsresult result = NS_OK;
|
nsresult result = NS_OK;
|
||||||
int32_t row = aStartRowIndex;
|
uint32_t row = aStartRowIndex;
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
int32_t col = aStartColumnIndex;
|
uint32_t col = aStartColumnIndex;
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
nsTableCellFrame* cellFrame = tableFrame->GetCellFrameAt(row, col);
|
nsTableCellFrame* cellFrame = tableFrame->GetCellFrameAt(row, col);
|
||||||
|
|
||||||
// Skip cells that are spanned from previous locations or are already selected
|
// Skip cells that are spanned from previous locations or are already selected
|
||||||
if (cellFrame) {
|
if (cellFrame) {
|
||||||
int32_t origRow, origCol;
|
uint32_t origRow = cellFrame->RowIndex();
|
||||||
cellFrame->GetRowIndex(origRow);
|
uint32_t origCol = cellFrame->ColIndex();
|
||||||
cellFrame->GetColIndex(origCol);
|
|
||||||
if (origRow == row && origCol == col && !cellFrame->IsSelected()) {
|
if (origRow == row && origCol == col && !cellFrame->IsSelected()) {
|
||||||
result = SelectCellElement(cellFrame->GetContent());
|
result = SelectCellElement(cellFrame->GetContent());
|
||||||
if (NS_FAILED(result)) return result;
|
if (NS_FAILED(result)) return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Done when we reach end column
|
// Done when we reach end column
|
||||||
if (col == aEndColumnIndex) break;
|
if (col == static_cast<uint32_t>(aEndColumnIndex)) break;
|
||||||
|
|
||||||
if (aStartColumnIndex < aEndColumnIndex)
|
if (aStartColumnIndex < aEndColumnIndex)
|
||||||
col ++;
|
col ++;
|
||||||
else
|
else
|
||||||
col--;
|
col--;
|
||||||
}
|
}
|
||||||
if (row == aEndRowIndex) break;
|
if (row == static_cast<uint32_t>(aEndRowIndex)) break;
|
||||||
|
|
||||||
if (aStartRowIndex < aEndRowIndex)
|
if (aStartRowIndex < aEndRowIndex)
|
||||||
row++;
|
row++;
|
||||||
|
|
|
@ -183,10 +183,8 @@ static void
|
||||||
ApplyBorderToStyle(const nsMathMLmtdFrame* aFrame,
|
ApplyBorderToStyle(const nsMathMLmtdFrame* aFrame,
|
||||||
nsStyleBorder& aStyleBorder)
|
nsStyleBorder& aStyleBorder)
|
||||||
{
|
{
|
||||||
int32_t rowIndex;
|
uint32_t rowIndex = aFrame->RowIndex();
|
||||||
int32_t columnIndex;
|
uint32_t columnIndex = aFrame->ColIndex();
|
||||||
aFrame->GetRowIndex(rowIndex);
|
|
||||||
aFrame->GetColIndex(columnIndex);
|
|
||||||
|
|
||||||
nscoord borderWidth =
|
nscoord borderWidth =
|
||||||
aFrame->PresContext()->GetBorderWidthTable()[NS_STYLE_BORDER_WIDTH_THIN];
|
aFrame->PresContext()->GetBorderWidthTable()[NS_STYLE_BORDER_WIDTH_THIN];
|
||||||
|
@ -201,7 +199,7 @@ ApplyBorderToStyle(const nsMathMLmtdFrame* aFrame,
|
||||||
if (rowIndex > 0 && rowLinesList) {
|
if (rowIndex > 0 && rowLinesList) {
|
||||||
// If the row number is greater than the number of provided rowline
|
// If the row number is greater than the number of provided rowline
|
||||||
// values, we simply repeat the last value.
|
// values, we simply repeat the last value.
|
||||||
int32_t listLength = rowLinesList->Length();
|
uint32_t listLength = rowLinesList->Length();
|
||||||
if (rowIndex < listLength) {
|
if (rowIndex < listLength) {
|
||||||
aStyleBorder.SetBorderStyle(NS_SIDE_TOP,
|
aStyleBorder.SetBorderStyle(NS_SIDE_TOP,
|
||||||
rowLinesList->ElementAt(rowIndex - 1));
|
rowLinesList->ElementAt(rowIndex - 1));
|
||||||
|
@ -216,7 +214,7 @@ ApplyBorderToStyle(const nsMathMLmtdFrame* aFrame,
|
||||||
if (columnIndex > 0 && columnLinesList) {
|
if (columnIndex > 0 && columnLinesList) {
|
||||||
// If the column number is greater than the number of provided columline
|
// If the column number is greater than the number of provided columline
|
||||||
// values, we simply repeat the last value.
|
// values, we simply repeat the last value.
|
||||||
int32_t listLength = columnLinesList->Length();
|
uint32_t listLength = columnLinesList->Length();
|
||||||
if (columnIndex < listLength) {
|
if (columnIndex < listLength) {
|
||||||
aStyleBorder.SetBorderStyle(NS_SIDE_LEFT,
|
aStyleBorder.SetBorderStyle(NS_SIDE_LEFT,
|
||||||
columnLinesList->ElementAt(columnIndex - 1));
|
columnLinesList->ElementAt(columnIndex - 1));
|
||||||
|
@ -1160,47 +1158,6 @@ nsMathMLmtdFrame::Init(nsIContent* aContent,
|
||||||
RemoveStateBits(NS_FRAME_FONT_INFLATION_FLOW_ROOT);
|
RemoveStateBits(NS_FRAME_FONT_INFLATION_FLOW_ROOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
|
||||||
nsMathMLmtdFrame::GetRowSpan()
|
|
||||||
{
|
|
||||||
int32_t rowspan = 1;
|
|
||||||
|
|
||||||
// Don't look at the content's rowspan if we're not an mtd or a pseudo cell.
|
|
||||||
if (mContent->IsMathMLElement(nsGkAtoms::mtd_) &&
|
|
||||||
!StyleContext()->GetPseudo()) {
|
|
||||||
nsAutoString value;
|
|
||||||
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::rowspan, value);
|
|
||||||
if (!value.IsEmpty()) {
|
|
||||||
nsresult error;
|
|
||||||
rowspan = value.ToInteger(&error);
|
|
||||||
if (NS_FAILED(error) || rowspan < 0)
|
|
||||||
rowspan = 1;
|
|
||||||
rowspan = std::min(rowspan, MAX_ROWSPAN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rowspan;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t
|
|
||||||
nsMathMLmtdFrame::GetColSpan()
|
|
||||||
{
|
|
||||||
int32_t colspan = 1;
|
|
||||||
|
|
||||||
// Don't look at the content's colspan if we're not an mtd or a pseudo cell.
|
|
||||||
if (mContent->IsMathMLElement(nsGkAtoms::mtd_) &&
|
|
||||||
!StyleContext()->GetPseudo()) {
|
|
||||||
nsAutoString value;
|
|
||||||
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::columnspan_, value);
|
|
||||||
if (!value.IsEmpty()) {
|
|
||||||
nsresult error;
|
|
||||||
colspan = value.ToInteger(&error);
|
|
||||||
if (NS_FAILED(error) || colspan <= 0 || colspan > MAX_COLSPAN)
|
|
||||||
colspan = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return colspan;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsMathMLmtdFrame::AttributeChanged(int32_t aNameSpaceID,
|
nsMathMLmtdFrame::AttributeChanged(int32_t aNameSpaceID,
|
||||||
nsIAtom* aAttribute,
|
nsIAtom* aAttribute,
|
||||||
|
@ -1243,12 +1200,11 @@ nsMathMLmtdFrame::GetVerticalAlign() const
|
||||||
nsTArray<int8_t>* alignmentList = FindCellProperty(this, RowAlignProperty());
|
nsTArray<int8_t>* alignmentList = FindCellProperty(this, RowAlignProperty());
|
||||||
|
|
||||||
if (alignmentList) {
|
if (alignmentList) {
|
||||||
int32_t rowIndex;
|
uint32_t rowIndex = RowIndex();
|
||||||
GetRowIndex(rowIndex);
|
|
||||||
|
|
||||||
// If the row number is greater than the number of provided rowalign values,
|
// If the row number is greater than the number of provided rowalign values,
|
||||||
// we simply repeat the last value.
|
// we simply repeat the last value.
|
||||||
if (rowIndex < (int32_t)alignmentList->Length())
|
if (rowIndex < alignmentList->Length())
|
||||||
alignment = alignmentList->ElementAt(rowIndex);
|
alignment = alignmentList->ElementAt(rowIndex);
|
||||||
else
|
else
|
||||||
alignment = alignmentList->ElementAt(alignmentList->Length() - 1);
|
alignment = alignmentList->ElementAt(alignmentList->Length() - 1);
|
||||||
|
@ -1335,12 +1291,11 @@ nsStyleText* nsMathMLmtdInnerFrame::StyleTextForLineLayout()
|
||||||
|
|
||||||
if (alignmentList) {
|
if (alignmentList) {
|
||||||
nsMathMLmtdFrame* cellFrame = (nsMathMLmtdFrame*)GetParent();
|
nsMathMLmtdFrame* cellFrame = (nsMathMLmtdFrame*)GetParent();
|
||||||
int32_t columnIndex;
|
uint32_t columnIndex = cellFrame->ColIndex();
|
||||||
cellFrame->GetColIndex(columnIndex);
|
|
||||||
|
|
||||||
// If the column number is greater than the number of provided columalign
|
// If the column number is greater than the number of provided columalign
|
||||||
// values, we simply repeat the last value.
|
// values, we simply repeat the last value.
|
||||||
if (columnIndex < (int32_t)alignmentList->Length())
|
if (columnIndex < alignmentList->Length())
|
||||||
alignment = alignmentList->ElementAt(columnIndex);
|
alignment = alignmentList->ElementAt(columnIndex);
|
||||||
else
|
else
|
||||||
alignment = alignmentList->ElementAt(alignmentList->Length() - 1);
|
alignment = alignmentList->ElementAt(alignmentList->Length() - 1);
|
||||||
|
|
|
@ -257,8 +257,6 @@ public:
|
||||||
nsDisplayListBuilder* aBuilder,
|
nsDisplayListBuilder* aBuilder,
|
||||||
const nsDisplayListSet& aLists) override;
|
const nsDisplayListSet& aLists) override;
|
||||||
|
|
||||||
virtual int32_t GetRowSpan() override;
|
|
||||||
virtual int32_t GetColSpan() override;
|
|
||||||
virtual bool IsFrameOfType(uint32_t aFlags) const override
|
virtual bool IsFrameOfType(uint32_t aFlags) const override
|
||||||
{
|
{
|
||||||
return nsTableCellFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML));
|
return nsTableCellFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML));
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#define CellData_h__
|
#define CellData_h__
|
||||||
|
|
||||||
#include "nsISupports.h"
|
#include "nsISupports.h"
|
||||||
|
#include "nsITableCellLayout.h" // for MAX_COLSPAN / MAX_ROWSPAN
|
||||||
#include "nsCoord.h"
|
#include "nsCoord.h"
|
||||||
#include "mozilla/gfx/Types.h"
|
#include "mozilla/gfx/Types.h"
|
||||||
#include "mozilla/WritingModes.h"
|
#include "mozilla/WritingModes.h"
|
||||||
|
@ -15,11 +16,6 @@ class nsTableCellFrame;
|
||||||
class nsCellMap;
|
class nsCellMap;
|
||||||
class BCCellData;
|
class BCCellData;
|
||||||
|
|
||||||
|
|
||||||
#define MAX_ROWSPAN 65534 // the cellmap can not handle more.
|
|
||||||
#define MAX_COLSPAN 1000 // limit as IE and opera do. If this ever changes,
|
|
||||||
// change COL_SPAN_OFFSET/COL_SPAN_SHIFT accordingly.
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data stored by nsCellMap to rationalize rowspan and colspan cells.
|
* Data stored by nsCellMap to rationalize rowspan and colspan cells.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2431,9 +2431,8 @@ void nsCellMap::Dump(bool aIsBorderCollapse) const
|
||||||
if (cd) {
|
if (cd) {
|
||||||
if (cd->IsOrig()) {
|
if (cd->IsOrig()) {
|
||||||
nsTableCellFrame* cellFrame = cd->GetCellFrame();
|
nsTableCellFrame* cellFrame = cd->GetCellFrame();
|
||||||
int32_t cellFrameColIndex;
|
uint32_t cellFrameColIndex = cellFrame->ColIndex();
|
||||||
cellFrame->GetColIndex(cellFrameColIndex);
|
printf("C%d,%d=%p(%u) ", rIndex, colIndex, (void*)cellFrame,
|
||||||
printf("C%d,%d=%p(%d) ", rIndex, colIndex, (void*)cellFrame,
|
|
||||||
cellFrameColIndex);
|
cellFrameColIndex);
|
||||||
cellCount++;
|
cellCount++;
|
||||||
}
|
}
|
||||||
|
@ -2520,8 +2519,7 @@ nsCellMap::GetCellInfoAt(const nsTableCellMap& aMap,
|
||||||
cellFrame = GetCellFrame(aRowX, aColX, *data, true);
|
cellFrame = GetCellFrame(aRowX, aColX, *data, true);
|
||||||
}
|
}
|
||||||
if (cellFrame && aColSpan) {
|
if (cellFrame && aColSpan) {
|
||||||
int32_t initialColIndex;
|
uint32_t initialColIndex = cellFrame->ColIndex();
|
||||||
cellFrame->GetColIndex(initialColIndex);
|
|
||||||
*aColSpan = GetEffectiveColSpan(aMap, aRowX, initialColIndex);
|
*aColSpan = GetEffectiveColSpan(aMap, aRowX, initialColIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,14 @@
|
||||||
|
|
||||||
#include "nsQueryFrame.h"
|
#include "nsQueryFrame.h"
|
||||||
|
|
||||||
|
#define MAX_ROWSPAN 65534 // the cellmap can not handle more.
|
||||||
|
#define MAX_COLSPAN 1000 // limit as IE and opera do. If this ever changes,
|
||||||
|
// change COL_SPAN_OFFSET/COL_SPAN_SHIFT accordingly.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nsITableCellLayout
|
* nsITableCellLayout
|
||||||
* interface for layout objects that act like table cells.
|
* interface for layout objects that act like table cells.
|
||||||
|
* XXX: This interface should really go away...
|
||||||
*
|
*
|
||||||
* @author sclark
|
* @author sclark
|
||||||
*/
|
*/
|
||||||
|
@ -22,11 +27,6 @@ public:
|
||||||
/** return the mapped cell's row and column indexes (starting at 0 for each) */
|
/** return the mapped cell's row and column indexes (starting at 0 for each) */
|
||||||
NS_IMETHOD GetCellIndexes(int32_t &aRowIndex, int32_t &aColIndex)=0;
|
NS_IMETHOD GetCellIndexes(int32_t &aRowIndex, int32_t &aColIndex)=0;
|
||||||
|
|
||||||
/** return the mapped cell's row index (starting at 0 for the first row) */
|
|
||||||
virtual nsresult GetRowIndex(int32_t &aRowIndex) const = 0;
|
|
||||||
|
|
||||||
/** return the mapped cell's column index (starting at 0 for the first column) */
|
|
||||||
virtual nsresult GetColIndex(int32_t &aColIndex) const = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -59,20 +59,6 @@ nsTableCellFrame::~nsTableCellFrame()
|
||||||
|
|
||||||
NS_IMPL_FRAMEARENA_HELPERS(nsTableCellFrame)
|
NS_IMPL_FRAMEARENA_HELPERS(nsTableCellFrame)
|
||||||
|
|
||||||
nsTableCellFrame*
|
|
||||||
nsTableCellFrame::GetNextCell() const
|
|
||||||
{
|
|
||||||
nsIFrame* childFrame = GetNextSibling();
|
|
||||||
while (childFrame) {
|
|
||||||
nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
|
|
||||||
if (cellFrame) {
|
|
||||||
return cellFrame;
|
|
||||||
}
|
|
||||||
childFrame = childFrame->GetNextSibling();
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsTableCellFrame::Init(nsIContent* aContent,
|
nsTableCellFrame::Init(nsIContent* aContent,
|
||||||
nsContainerFrame* aParent,
|
nsContainerFrame* aParent,
|
||||||
|
@ -88,8 +74,7 @@ nsTableCellFrame::Init(nsIContent* aContent,
|
||||||
if (aPrevInFlow) {
|
if (aPrevInFlow) {
|
||||||
// Set the column index
|
// Set the column index
|
||||||
nsTableCellFrame* cellFrame = (nsTableCellFrame*)aPrevInFlow;
|
nsTableCellFrame* cellFrame = (nsTableCellFrame*)aPrevInFlow;
|
||||||
int32_t colIndex;
|
uint32_t colIndex = cellFrame->ColIndex();
|
||||||
cellFrame->GetColIndex(colIndex);
|
|
||||||
SetColIndex(colIndex);
|
SetColIndex(colIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,34 +167,6 @@ nsTableCellFrame::NeedsToObserve(const ReflowInput& aReflowInput)
|
||||||
fType == nsGkAtoms::tableWrapperFrame);
|
fType == nsGkAtoms::tableWrapperFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsTableCellFrame::GetRowIndex(int32_t &aRowIndex) const
|
|
||||||
{
|
|
||||||
nsresult result;
|
|
||||||
nsTableRowFrame* row = static_cast<nsTableRowFrame*>(GetParent());
|
|
||||||
if (row) {
|
|
||||||
aRowIndex = row->GetRowIndex();
|
|
||||||
result = NS_OK;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
aRowIndex = 0;
|
|
||||||
result = NS_ERROR_NOT_INITIALIZED;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsTableCellFrame::GetColIndex(int32_t &aColIndex) const
|
|
||||||
{
|
|
||||||
if (GetPrevInFlow()) {
|
|
||||||
return static_cast<nsTableCellFrame*>(FirstInFlow())->GetColIndex(aColIndex);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
aColIndex = mColIndex;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsTableCellFrame::AttributeChanged(int32_t aNameSpaceID,
|
nsTableCellFrame::AttributeChanged(int32_t aNameSpaceID,
|
||||||
nsIAtom* aAttribute,
|
nsIAtom* aAttribute,
|
||||||
|
@ -238,13 +195,13 @@ nsTableCellFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
||||||
nsTableFrame* tableFrame = GetTableFrame();
|
nsTableFrame* tableFrame = GetTableFrame();
|
||||||
if (tableFrame->IsBorderCollapse() &&
|
if (tableFrame->IsBorderCollapse() &&
|
||||||
tableFrame->BCRecalcNeeded(aOldStyleContext, StyleContext())) {
|
tableFrame->BCRecalcNeeded(aOldStyleContext, StyleContext())) {
|
||||||
int32_t colIndex, rowIndex;
|
uint32_t colIndex = ColIndex();
|
||||||
GetColIndex(colIndex);
|
uint32_t rowIndex = RowIndex();
|
||||||
GetRowIndex(rowIndex);
|
|
||||||
// row span needs to be clamped as we do not create rows in the cellmap
|
// row span needs to be clamped as we do not create rows in the cellmap
|
||||||
// which do not have cells originating in them
|
// which do not have cells originating in them
|
||||||
TableArea damageArea(colIndex, rowIndex, GetColSpan(),
|
TableArea damageArea(colIndex, rowIndex, GetColSpan(),
|
||||||
std::min(GetRowSpan(), tableFrame->GetRowCount() - rowIndex));
|
std::min(static_cast<uint32_t>(GetRowSpan()),
|
||||||
|
tableFrame->GetRowCount() - rowIndex));
|
||||||
tableFrame->AddBCDamageArea(damageArea);
|
tableFrame->AddBCDamageArea(damageArea);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -464,19 +421,40 @@ PaintTableCellSelection(nsIFrame* aFrame, DrawTarget* aDrawTarget,
|
||||||
aPt);
|
aPt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsTableCellFrame::ShouldPaintBordersAndBackgrounds() const
|
||||||
|
{
|
||||||
|
// If we're not visible, we don't paint.
|
||||||
|
if (!StyleVisibility()->IsVisible()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consider 'empty-cells', but only in separated borders mode.
|
||||||
|
if (!GetContentEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsTableFrame* tableFrame = GetTableFrame();
|
||||||
|
if (tableFrame->IsBorderCollapse()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return StyleTableBorder()->mEmptyCells == NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsTableCellFrame::ShouldPaintBackground(nsDisplayListBuilder* aBuilder)
|
||||||
|
{
|
||||||
|
return ShouldPaintBordersAndBackgrounds() && IsVisibleInSelection(aBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
const nsRect& aDirtyRect,
|
const nsRect& aDirtyRect,
|
||||||
const nsDisplayListSet& aLists)
|
const nsDisplayListSet& aLists)
|
||||||
{
|
{
|
||||||
DO_GLOBAL_REFLOW_COUNT_DSP("nsTableCellFrame");
|
DO_GLOBAL_REFLOW_COUNT_DSP("nsTableCellFrame");
|
||||||
nsTableFrame* tableFrame = GetTableFrame();
|
if (ShouldPaintBordersAndBackgrounds()) {
|
||||||
int32_t emptyCellStyle = GetContentEmpty() && !tableFrame->IsBorderCollapse() ?
|
|
||||||
StyleTableBorder()->mEmptyCells
|
|
||||||
: NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
|
|
||||||
// take account of 'empty-cells'
|
|
||||||
if (StyleVisibility()->IsVisible() &&
|
|
||||||
(NS_STYLE_TABLE_EMPTY_CELLS_HIDE != emptyCellStyle)) {
|
|
||||||
// display outset box-shadows if we need to.
|
// display outset box-shadows if we need to.
|
||||||
bool hasBoxShadow = !!StyleEffects()->mBoxShadow;
|
bool hasBoxShadow = !!StyleEffects()->mBoxShadow;
|
||||||
if (hasBoxShadow) {
|
if (hasBoxShadow) {
|
||||||
|
@ -501,7 +479,7 @@ nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
}
|
}
|
||||||
|
|
||||||
// display borders if we need to
|
// display borders if we need to
|
||||||
ProcessBorders(tableFrame, aBuilder, aLists);
|
ProcessBorders(GetTableFrame(), aBuilder, aLists);
|
||||||
|
|
||||||
// and display the selection border if we need to
|
// and display the selection border if we need to
|
||||||
if (IsSelected()) {
|
if (IsSelected()) {
|
||||||
|
@ -704,16 +682,18 @@ nsTableCellFrame::GetCellBaseline() const
|
||||||
borderPadding;
|
borderPadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t nsTableCellFrame::GetRowSpan()
|
int32_t
|
||||||
|
nsTableCellFrame::GetRowSpan()
|
||||||
{
|
{
|
||||||
int32_t rowSpan=1;
|
int32_t rowSpan=1;
|
||||||
nsGenericHTMLElement *hc = nsGenericHTMLElement::FromContent(mContent);
|
|
||||||
|
|
||||||
// Don't look at the content's rowspan if we're a pseudo cell
|
// Don't look at the content's rowspan if we're a pseudo cell
|
||||||
if (hc && !StyleContext()->GetPseudo()) {
|
if (!StyleContext()->GetPseudo()) {
|
||||||
const nsAttrValue* attr = hc->GetParsedAttr(nsGkAtoms::rowspan);
|
dom::Element* elem = mContent->AsElement();
|
||||||
|
const nsAttrValue* attr = elem->GetParsedAttr(nsGkAtoms::rowspan);
|
||||||
// Note that we don't need to check the tag name, because only table cells
|
// Note that we don't need to check the tag name, because only table cells
|
||||||
// and table headers parse the "rowspan" attribute into an integer.
|
// (including MathML <mtd>) and table headers parse the "rowspan" attribute
|
||||||
|
// into an integer.
|
||||||
if (attr && attr->Type() == nsAttrValue::eInteger) {
|
if (attr && attr->Type() == nsAttrValue::eInteger) {
|
||||||
rowSpan = attr->GetIntegerValue();
|
rowSpan = attr->GetIntegerValue();
|
||||||
}
|
}
|
||||||
|
@ -721,16 +701,20 @@ int32_t nsTableCellFrame::GetRowSpan()
|
||||||
return rowSpan;
|
return rowSpan;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t nsTableCellFrame::GetColSpan()
|
int32_t
|
||||||
|
nsTableCellFrame::GetColSpan()
|
||||||
{
|
{
|
||||||
int32_t colSpan=1;
|
int32_t colSpan=1;
|
||||||
nsGenericHTMLElement *hc = nsGenericHTMLElement::FromContent(mContent);
|
|
||||||
|
|
||||||
// Don't look at the content's colspan if we're a pseudo cell
|
// Don't look at the content's colspan if we're a pseudo cell
|
||||||
if (hc && !StyleContext()->GetPseudo()) {
|
if (!StyleContext()->GetPseudo()) {
|
||||||
const nsAttrValue* attr = hc->GetParsedAttr(nsGkAtoms::colspan);
|
dom::Element* elem = mContent->AsElement();
|
||||||
|
const nsAttrValue* attr = elem->GetParsedAttr(
|
||||||
|
MOZ_UNLIKELY(elem->IsMathMLElement()) ? nsGkAtoms::columnspan_
|
||||||
|
: nsGkAtoms::colspan);
|
||||||
// Note that we don't need to check the tag name, because only table cells
|
// Note that we don't need to check the tag name, because only table cells
|
||||||
// and table headers parse the "colspan" attribute into an integer.
|
// (including MathML <mtd>) and table headers parse the "colspan" attribute
|
||||||
|
// into an integer.
|
||||||
if (attr && attr->Type() == nsAttrValue::eInteger) {
|
if (attr && attr->Type() == nsAttrValue::eInteger) {
|
||||||
colSpan = attr->GetIntegerValue();
|
colSpan = attr->GetIntegerValue();
|
||||||
}
|
}
|
||||||
|
@ -807,14 +791,13 @@ CalcUnpaginatedBSize(nsTableCellFrame& aCellFrame,
|
||||||
nsTableRowGroupFrame* firstRGInFlow =
|
nsTableRowGroupFrame* firstRGInFlow =
|
||||||
static_cast<nsTableRowGroupFrame*>(row->GetParent());
|
static_cast<nsTableRowGroupFrame*>(row->GetParent());
|
||||||
|
|
||||||
int32_t rowIndex;
|
uint32_t rowIndex = firstCellInFlow->RowIndex();
|
||||||
firstCellInFlow->GetRowIndex(rowIndex);
|
|
||||||
int32_t rowSpan = aTableFrame.GetEffectiveRowSpan(*firstCellInFlow);
|
int32_t rowSpan = aTableFrame.GetEffectiveRowSpan(*firstCellInFlow);
|
||||||
|
|
||||||
nscoord computedBSize = firstTableInFlow->GetRowSpacing(rowIndex,
|
nscoord computedBSize = firstTableInFlow->GetRowSpacing(rowIndex,
|
||||||
rowIndex + rowSpan - 1);
|
rowIndex + rowSpan - 1);
|
||||||
computedBSize -= aBlockDirBorderPadding;
|
computedBSize -= aBlockDirBorderPadding;
|
||||||
int32_t rowX;
|
uint32_t rowX;
|
||||||
for (row = firstRGInFlow->GetFirstRow(), rowX = 0; row; row = row->GetNextRow(), rowX++) {
|
for (row = firstRGInFlow->GetFirstRow(), rowX = 0; row; row = row->GetNextRow(), rowX++) {
|
||||||
if (rowX > rowIndex + rowSpan - 1) {
|
if (rowX > rowIndex + rowSpan - 1) {
|
||||||
break;
|
break;
|
||||||
|
@ -1029,12 +1012,7 @@ nsTableCellFrame::AccessibleType()
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsTableCellFrame::GetCellIndexes(int32_t &aRowIndex, int32_t &aColIndex)
|
nsTableCellFrame::GetCellIndexes(int32_t &aRowIndex, int32_t &aColIndex)
|
||||||
{
|
{
|
||||||
nsresult res = GetRowIndex(aRowIndex);
|
aRowIndex = RowIndex();
|
||||||
if (NS_FAILED(res))
|
|
||||||
{
|
|
||||||
aColIndex = 0;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
aColIndex = mColIndex;
|
aColIndex = mColIndex;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,11 +165,11 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return the cell's specified row span. this is what was specified in the
|
* return the cell's specified row span. this is what was specified in the
|
||||||
* content model or in the style info, and is always >= 1.
|
* content model or in the style info, and is always >= 0.
|
||||||
* to get the effective row span (the actual value that applies), use GetEffectiveRowSpan()
|
* to get the effective row span (the actual value that applies), use GetEffectiveRowSpan()
|
||||||
* @see nsTableFrame::GetEffectiveRowSpan()
|
* @see nsTableFrame::GetEffectiveRowSpan()
|
||||||
*/
|
*/
|
||||||
virtual int32_t GetRowSpan();
|
int32_t GetRowSpan();
|
||||||
|
|
||||||
// there is no set row index because row index depends on the cell's parent row only
|
// there is no set row index because row index depends on the cell's parent row only
|
||||||
|
|
||||||
|
@ -183,7 +183,10 @@ public:
|
||||||
NS_IMETHOD GetCellIndexes(int32_t &aRowIndex, int32_t &aColIndex) override;
|
NS_IMETHOD GetCellIndexes(int32_t &aRowIndex, int32_t &aColIndex) override;
|
||||||
|
|
||||||
/** return the mapped cell's row index (starting at 0 for the first row) */
|
/** return the mapped cell's row index (starting at 0 for the first row) */
|
||||||
virtual nsresult GetRowIndex(int32_t &aRowIndex) const override;
|
uint32_t RowIndex() const
|
||||||
|
{
|
||||||
|
return static_cast<nsTableRowFrame*>(GetParent())->GetRowIndex();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return the cell's specified col span. this is what was specified in the
|
* return the cell's specified col span. this is what was specified in the
|
||||||
|
@ -191,10 +194,19 @@ public:
|
||||||
* to get the effective col span (the actual value that applies), use GetEffectiveColSpan()
|
* to get the effective col span (the actual value that applies), use GetEffectiveColSpan()
|
||||||
* @see nsTableFrame::GetEffectiveColSpan()
|
* @see nsTableFrame::GetEffectiveColSpan()
|
||||||
*/
|
*/
|
||||||
virtual int32_t GetColSpan();
|
int32_t GetColSpan();
|
||||||
|
|
||||||
/** return the cell's column index (starting at 0 for the first column) */
|
/** return the cell's column index (starting at 0 for the first column) */
|
||||||
virtual nsresult GetColIndex(int32_t &aColIndex) const override;
|
uint32_t ColIndex() const
|
||||||
|
{
|
||||||
|
// NOTE: We copy this from previous continuations, and we don't ever have
|
||||||
|
// dynamic updates when tables split, so our mColIndex always matches our
|
||||||
|
// first continuation's.
|
||||||
|
MOZ_ASSERT(static_cast<nsTableCellFrame*>(FirstContinuation())->mColIndex ==
|
||||||
|
mColIndex,
|
||||||
|
"mColIndex out of sync with first continuation");
|
||||||
|
return mColIndex;
|
||||||
|
}
|
||||||
void SetColIndex(int32_t aColIndex);
|
void SetColIndex(int32_t aColIndex);
|
||||||
|
|
||||||
/** return the available isize given to this frame during its last reflow */
|
/** return the available isize given to this frame during its last reflow */
|
||||||
|
@ -209,13 +221,23 @@ public:
|
||||||
/** set the desired size returned by this frame during its last reflow */
|
/** set the desired size returned by this frame during its last reflow */
|
||||||
inline void SetDesiredSize(const ReflowOutput & aDesiredSize);
|
inline void SetDesiredSize(const ReflowOutput & aDesiredSize);
|
||||||
|
|
||||||
bool GetContentEmpty();
|
bool GetContentEmpty() const;
|
||||||
void SetContentEmpty(bool aContentEmpty);
|
void SetContentEmpty(bool aContentEmpty);
|
||||||
|
|
||||||
bool HasPctOverBSize();
|
bool HasPctOverBSize();
|
||||||
void SetHasPctOverBSize(bool aValue);
|
void SetHasPctOverBSize(bool aValue);
|
||||||
|
|
||||||
nsTableCellFrame* GetNextCell() const;
|
nsTableCellFrame* GetNextCell() const
|
||||||
|
{
|
||||||
|
nsIFrame* sibling = GetNextSibling();
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (sibling) {
|
||||||
|
nsTableCellFrame* cellFrame = do_QueryFrame(sibling);
|
||||||
|
MOZ_ASSERT(cellFrame, "How do we have a non-cell sibling?");
|
||||||
|
}
|
||||||
|
#endif // DEBUG
|
||||||
|
return static_cast<nsTableCellFrame*>(sibling);
|
||||||
|
}
|
||||||
|
|
||||||
virtual LogicalMargin GetBorderWidth(WritingMode aWM) const;
|
virtual LogicalMargin GetBorderWidth(WritingMode aWM) const;
|
||||||
|
|
||||||
|
@ -237,6 +259,10 @@ public:
|
||||||
virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) override;
|
virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) override;
|
||||||
virtual void InvalidateFrameForRemoval() override { InvalidateFrameSubtree(); }
|
virtual void InvalidateFrameForRemoval() override { InvalidateFrameSubtree(); }
|
||||||
|
|
||||||
|
bool ShouldPaintBordersAndBackgrounds() const;
|
||||||
|
|
||||||
|
bool ShouldPaintBackground(nsDisplayListBuilder* aBuilder);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual LogicalSides
|
virtual LogicalSides
|
||||||
GetLogicalSkipSides(const ReflowInput* aReflowInput = nullptr) const override;
|
GetLogicalSkipSides(const ReflowInput* aReflowInput = nullptr) const override;
|
||||||
|
@ -273,7 +299,7 @@ inline void nsTableCellFrame::SetDesiredSize(const ReflowOutput & aDesiredSize)
|
||||||
mDesiredSize = aDesiredSize.Size(wm).ConvertTo(GetWritingMode(), wm);
|
mDesiredSize = aDesiredSize.Size(wm).ConvertTo(GetWritingMode(), wm);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool nsTableCellFrame::GetContentEmpty()
|
inline bool nsTableCellFrame::GetContentEmpty() const
|
||||||
{
|
{
|
||||||
return HasAnyStateBits(NS_TABLE_CELL_CONTENT_EMPTY);
|
return HasAnyStateBits(NS_TABLE_CELL_CONTENT_EMPTY);
|
||||||
}
|
}
|
||||||
|
@ -350,4 +376,17 @@ private:
|
||||||
BCPixelSize mIStartBorder;
|
BCPixelSize mIStartBorder;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Implemented here because that's a sane-ish way to make the includes work out.
|
||||||
|
inline nsTableCellFrame* nsTableRowFrame::GetFirstCell() const
|
||||||
|
{
|
||||||
|
nsIFrame* firstChild = mFrames.FirstChild();
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (firstChild) {
|
||||||
|
nsTableCellFrame* cellFrame = do_QueryFrame(firstChild);
|
||||||
|
MOZ_ASSERT(cellFrame, "How do we have a non-cell sibling?");
|
||||||
|
}
|
||||||
|
#endif // DEBUG
|
||||||
|
return static_cast<nsTableCellFrame*>(firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -368,9 +368,8 @@ nsTableFrame::AttributeChangedFor(nsIFrame* aFrame,
|
||||||
nsTableCellMap* cellMap = GetCellMap();
|
nsTableCellMap* cellMap = GetCellMap();
|
||||||
if (cellMap) {
|
if (cellMap) {
|
||||||
// for now just remove the cell from the map and reinsert it
|
// for now just remove the cell from the map and reinsert it
|
||||||
int32_t rowIndex, colIndex;
|
uint32_t rowIndex = cellFrame->RowIndex();
|
||||||
cellFrame->GetRowIndex(rowIndex);
|
uint32_t colIndex = cellFrame->ColIndex();
|
||||||
cellFrame->GetColIndex(colIndex);
|
|
||||||
RemoveCell(cellFrame, rowIndex);
|
RemoveCell(cellFrame, rowIndex);
|
||||||
AutoTArray<nsTableCellFrame*, 1> cells;
|
AutoTArray<nsTableCellFrame*, 1> cells;
|
||||||
cells.AppendElement(cellFrame);
|
cells.AppendElement(cellFrame);
|
||||||
|
@ -447,9 +446,7 @@ nsTableFrame::GetEffectiveRowSpan(int32_t aRowIndex,
|
||||||
nsTableCellMap* cellMap = GetCellMap();
|
nsTableCellMap* cellMap = GetCellMap();
|
||||||
NS_PRECONDITION (nullptr != cellMap, "bad call, cellMap not yet allocated.");
|
NS_PRECONDITION (nullptr != cellMap, "bad call, cellMap not yet allocated.");
|
||||||
|
|
||||||
int32_t colIndex;
|
return cellMap->GetEffectiveRowSpan(aRowIndex, aCell.ColIndex());
|
||||||
aCell.GetColIndex(colIndex);
|
|
||||||
return cellMap->GetEffectiveRowSpan(aRowIndex, colIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
|
@ -458,9 +455,8 @@ nsTableFrame::GetEffectiveRowSpan(const nsTableCellFrame& aCell,
|
||||||
{
|
{
|
||||||
nsTableCellMap* tableCellMap = GetCellMap(); if (!tableCellMap) ABORT1(1);
|
nsTableCellMap* tableCellMap = GetCellMap(); if (!tableCellMap) ABORT1(1);
|
||||||
|
|
||||||
int32_t colIndex, rowIndex;
|
uint32_t colIndex = aCell.ColIndex();
|
||||||
aCell.GetColIndex(colIndex);
|
uint32_t rowIndex = aCell.RowIndex();
|
||||||
aCell.GetRowIndex(rowIndex);
|
|
||||||
|
|
||||||
if (aCellMap)
|
if (aCellMap)
|
||||||
return aCellMap->GetRowSpan(rowIndex, colIndex, true);
|
return aCellMap->GetRowSpan(rowIndex, colIndex, true);
|
||||||
|
@ -474,9 +470,8 @@ nsTableFrame::GetEffectiveColSpan(const nsTableCellFrame& aCell,
|
||||||
{
|
{
|
||||||
nsTableCellMap* tableCellMap = GetCellMap(); if (!tableCellMap) ABORT1(1);
|
nsTableCellMap* tableCellMap = GetCellMap(); if (!tableCellMap) ABORT1(1);
|
||||||
|
|
||||||
int32_t colIndex, rowIndex;
|
uint32_t colIndex = aCell.ColIndex();
|
||||||
aCell.GetColIndex(colIndex);
|
uint32_t rowIndex = aCell.RowIndex();
|
||||||
aCell.GetRowIndex(rowIndex);
|
|
||||||
|
|
||||||
if (aCellMap)
|
if (aCellMap)
|
||||||
return aCellMap->GetEffectiveColSpan(*tableCellMap, rowIndex, colIndex);
|
return aCellMap->GetEffectiveColSpan(*tableCellMap, rowIndex, colIndex);
|
||||||
|
@ -1192,11 +1187,19 @@ PaintRowBackground(nsTableRowFrame* aRow,
|
||||||
nsIFrame* aFrame,
|
nsIFrame* aFrame,
|
||||||
nsDisplayListBuilder* aBuilder,
|
nsDisplayListBuilder* aBuilder,
|
||||||
const nsDisplayListSet& aLists,
|
const nsDisplayListSet& aLists,
|
||||||
|
const nsRect& aDirtyRect,
|
||||||
const nsPoint& aOffset = nsPoint())
|
const nsPoint& aOffset = nsPoint())
|
||||||
{
|
{
|
||||||
// Compute background rect by iterating over all cell frames.
|
// Compute background rect by iterating over all cell frames.
|
||||||
for (nsTableCellFrame* cell = aRow->GetFirstCell(); cell; cell = cell->GetNextCell()) {
|
for (nsTableCellFrame* cell = aRow->GetFirstCell(); cell; cell = cell->GetNextCell()) {
|
||||||
|
if (!cell->ShouldPaintBackground(aBuilder)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
auto cellRect = cell->GetRectRelativeToSelf() + cell->GetNormalPosition() + aOffset;
|
auto cellRect = cell->GetRectRelativeToSelf() + cell->GetNormalPosition() + aOffset;
|
||||||
|
if (!aDirtyRect.Intersects(cellRect)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect,
|
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect,
|
||||||
aLists.BorderBackground(),
|
aLists.BorderBackground(),
|
||||||
true, nullptr,
|
true, nullptr,
|
||||||
|
@ -1209,10 +1212,14 @@ static void
|
||||||
PaintRowGroupBackground(nsTableRowGroupFrame* aRowGroup,
|
PaintRowGroupBackground(nsTableRowGroupFrame* aRowGroup,
|
||||||
nsIFrame* aFrame,
|
nsIFrame* aFrame,
|
||||||
nsDisplayListBuilder* aBuilder,
|
nsDisplayListBuilder* aBuilder,
|
||||||
const nsDisplayListSet& aLists)
|
const nsDisplayListSet& aLists,
|
||||||
|
const nsRect& aDirtyRect)
|
||||||
{
|
{
|
||||||
for (nsTableRowFrame* row = aRowGroup->GetFirstRow(); row; row = row->GetNextRow()) {
|
for (nsTableRowFrame* row = aRowGroup->GetFirstRow(); row; row = row->GetNextRow()) {
|
||||||
PaintRowBackground(row, aFrame, aBuilder, aLists, row->GetNormalPosition());
|
if (!aDirtyRect.Intersects(nsRect(row->GetNormalPosition(), row->GetSize()))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
PaintRowBackground(row, aFrame, aBuilder, aLists, aDirtyRect, row->GetNormalPosition());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1221,21 +1228,42 @@ PaintRowGroupBackgroundByColIdx(nsTableRowGroupFrame* aRowGroup,
|
||||||
nsIFrame* aFrame,
|
nsIFrame* aFrame,
|
||||||
nsDisplayListBuilder* aBuilder,
|
nsDisplayListBuilder* aBuilder,
|
||||||
const nsDisplayListSet& aLists,
|
const nsDisplayListSet& aLists,
|
||||||
const nsTArray<int32_t>& aColIdx,
|
const nsRect& aDirtyRect,
|
||||||
|
const nsTArray<uint32_t>& aColIdx,
|
||||||
const nsPoint& aOffset)
|
const nsPoint& aOffset)
|
||||||
{
|
{
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(!aColIdx.IsEmpty(),
|
||||||
|
"Must be painting backgrounds for something");
|
||||||
for (nsTableRowFrame* row = aRowGroup->GetFirstRow(); row; row = row->GetNextRow()) {
|
for (nsTableRowFrame* row = aRowGroup->GetFirstRow(); row; row = row->GetNextRow()) {
|
||||||
|
auto rowPos = row->GetNormalPosition() + aOffset;
|
||||||
|
if (!aDirtyRect.Intersects(nsRect(rowPos, row->GetSize()))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for (nsTableCellFrame* cell = row->GetFirstCell(); cell; cell = cell->GetNextCell()) {
|
for (nsTableCellFrame* cell = row->GetFirstCell(); cell; cell = cell->GetNextCell()) {
|
||||||
int32_t curColIdx;
|
|
||||||
cell->GetColIndex(curColIdx);
|
uint32_t curColIdx = cell->ColIndex();
|
||||||
if (aColIdx.Contains(curColIdx)) {
|
if (!aColIdx.Contains(curColIdx)) {
|
||||||
auto cellRect = cell->GetRectRelativeToSelf() + cell->GetNormalPosition() + row->GetNormalPosition() + aOffset;
|
if (curColIdx > aColIdx.LastElement()) {
|
||||||
|
// We can just stop looking at this row.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cell->ShouldPaintBackground(aBuilder)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cellPos = cell->GetNormalPosition() + rowPos;
|
||||||
|
auto cellRect = nsRect(cellPos, cell->GetSize());
|
||||||
|
if (!aDirtyRect.Intersects(cellRect)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect,
|
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect,
|
||||||
aLists.BorderBackground(),
|
aLists.BorderBackground(),
|
||||||
true, nullptr,
|
true, nullptr,
|
||||||
aFrame->GetRectRelativeToSelf(),
|
aFrame->GetRectRelativeToSelf(),
|
||||||
cell);
|
cell);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1247,66 +1275,94 @@ nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
|
||||||
const nsDisplayListSet& aLists,
|
const nsDisplayListSet& aLists,
|
||||||
DisplayGenericTablePartTraversal aTraversal)
|
DisplayGenericTablePartTraversal aTraversal)
|
||||||
{
|
{
|
||||||
if (aFrame->IsVisibleForPainting(aBuilder)) {
|
bool isVisible = aFrame->IsVisibleForPainting(aBuilder);
|
||||||
|
bool isTable = (aFrame->GetType() == nsGkAtoms::tableFrame);
|
||||||
|
|
||||||
|
if (isVisible || !isTable) {
|
||||||
nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem();
|
nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem();
|
||||||
// currentItem may be null, when none of the table parts have a
|
// currentItem may be null, when none of the table parts have a
|
||||||
// background or border
|
// background or border
|
||||||
if (currentItem) {
|
if (currentItem) {
|
||||||
currentItem->UpdateForFrameBackground(aFrame);
|
currentItem->UpdateForFrameBackground(aFrame);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isVisible) {
|
||||||
|
// XXX: should box-shadow for rows/rowgroups/columns/colgroups get painted
|
||||||
|
// just because we're visible? Or should it depend on the cell visibility
|
||||||
|
// when we're not the whole table?
|
||||||
|
|
||||||
// Paint the outset box-shadows for the table frames
|
// Paint the outset box-shadows for the table frames
|
||||||
bool hasBoxShadow = aFrame->StyleEffects()->mBoxShadow != nullptr;
|
if (aFrame->StyleEffects()->mBoxShadow) {
|
||||||
if (hasBoxShadow) {
|
|
||||||
aLists.BorderBackground()->AppendNewToTop(
|
aLists.BorderBackground()->AppendNewToTop(
|
||||||
new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, aFrame));
|
new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, aFrame));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (aFrame->GetType() == nsGkAtoms::tableRowGroupFrame) {
|
// Background visibility for rows, rowgroups, columns, colgroups depends on
|
||||||
nsTableRowGroupFrame* rowGroup = static_cast<nsTableRowGroupFrame*>(aFrame);
|
// the visibility of the _cell_, not of the row/col(group).
|
||||||
PaintRowGroupBackground(rowGroup, aFrame, aBuilder, aLists);
|
// See spec at https://drafts.csswg.org/css-tables-3/#drawing-cell-backgrounds
|
||||||
} else if (aFrame->GetType() == nsGkAtoms::tableRowFrame) {
|
if (aFrame->GetType() == nsGkAtoms::tableRowGroupFrame) {
|
||||||
nsTableRowFrame* row = static_cast<nsTableRowFrame*>(aFrame);
|
nsTableRowGroupFrame* rowGroup = static_cast<nsTableRowGroupFrame*>(aFrame);
|
||||||
PaintRowBackground(row, aFrame, aBuilder, aLists);
|
PaintRowGroupBackground(rowGroup, aFrame, aBuilder, aLists, aDirtyRect);
|
||||||
} else if (aFrame->GetType() == nsGkAtoms::tableColGroupFrame) {
|
} else if (aFrame->GetType() == nsGkAtoms::tableRowFrame) {
|
||||||
// Compute background rect by iterating all cell frame.
|
nsTableRowFrame* row = static_cast<nsTableRowFrame*>(aFrame);
|
||||||
nsTableColGroupFrame* colGroup = static_cast<nsTableColGroupFrame*>(aFrame);
|
PaintRowBackground(row, aFrame, aBuilder, aLists, aDirtyRect);
|
||||||
// Collecting column index.
|
} else if (aFrame->GetType() == nsGkAtoms::tableColGroupFrame) {
|
||||||
AutoTArray<int32_t, 1> colIdx;
|
// Compute background rect by iterating all cell frame.
|
||||||
for (nsTableColFrame* col = colGroup->GetFirstColumn(); col; col = col->GetNextCol()) {
|
nsTableColGroupFrame* colGroup = static_cast<nsTableColGroupFrame*>(aFrame);
|
||||||
colIdx.AppendElement(col->GetColIndex());
|
// Collecting column index.
|
||||||
}
|
AutoTArray<uint32_t, 1> colIdx;
|
||||||
|
for (nsTableColFrame* col = colGroup->GetFirstColumn(); col; col = col->GetNextCol()) {
|
||||||
|
MOZ_ASSERT(colIdx.IsEmpty() ||
|
||||||
|
static_cast<uint32_t>(col->GetColIndex()) > colIdx.LastElement());
|
||||||
|
colIdx.AppendElement(col->GetColIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!colIdx.IsEmpty()) {
|
||||||
|
// We have some actual cells that live inside this rowgroup.
|
||||||
nsTableFrame* table = colGroup->GetTableFrame();
|
nsTableFrame* table = colGroup->GetTableFrame();
|
||||||
RowGroupArray rowGroups;
|
RowGroupArray rowGroups;
|
||||||
table->OrderRowGroups(rowGroups);
|
table->OrderRowGroups(rowGroups);
|
||||||
for (nsTableRowGroupFrame* rowGroup : rowGroups) {
|
for (nsTableRowGroupFrame* rowGroup : rowGroups) {
|
||||||
auto offset = rowGroup->GetNormalPosition() - colGroup->GetNormalPosition();
|
auto offset = rowGroup->GetNormalPosition() - colGroup->GetNormalPosition();
|
||||||
PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, colIdx, offset);
|
if (!aDirtyRect.Intersects(nsRect(offset, rowGroup->GetSize()))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, aDirtyRect, colIdx, offset);
|
||||||
}
|
}
|
||||||
} else if (aFrame->GetType() == nsGkAtoms::tableColFrame) {
|
|
||||||
// Compute background rect by iterating all cell frame.
|
|
||||||
nsTableColFrame* col = static_cast<nsTableColFrame*>(aFrame);
|
|
||||||
AutoTArray<int32_t, 1> colIdx;
|
|
||||||
colIdx.AppendElement(col->GetColIndex());
|
|
||||||
|
|
||||||
nsTableFrame* table = col->GetTableFrame();
|
|
||||||
RowGroupArray rowGroups;
|
|
||||||
table->OrderRowGroups(rowGroups);
|
|
||||||
for (nsTableRowGroupFrame* rowGroup : rowGroups) {
|
|
||||||
auto offset = rowGroup->GetNormalPosition() -
|
|
||||||
col->GetNormalPosition() -
|
|
||||||
col->GetTableColGroupFrame()->GetNormalPosition();
|
|
||||||
PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, colIdx, offset);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame,
|
|
||||||
aFrame->GetRectRelativeToSelf(),
|
|
||||||
aLists.BorderBackground());
|
|
||||||
}
|
}
|
||||||
|
} else if (aFrame->GetType() == nsGkAtoms::tableColFrame) {
|
||||||
|
// Compute background rect by iterating all cell frame.
|
||||||
|
nsTableColFrame* col = static_cast<nsTableColFrame*>(aFrame);
|
||||||
|
AutoTArray<uint32_t, 1> colIdx;
|
||||||
|
colIdx.AppendElement(col->GetColIndex());
|
||||||
|
|
||||||
|
nsTableFrame* table = col->GetTableFrame();
|
||||||
|
RowGroupArray rowGroups;
|
||||||
|
table->OrderRowGroups(rowGroups);
|
||||||
|
for (nsTableRowGroupFrame* rowGroup : rowGroups) {
|
||||||
|
auto offset = rowGroup->GetNormalPosition() -
|
||||||
|
col->GetNormalPosition() -
|
||||||
|
col->GetTableColGroupFrame()->GetNormalPosition();
|
||||||
|
if (!aDirtyRect.Intersects(nsRect(offset, rowGroup->GetSize()))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, aDirtyRect, colIdx, offset);
|
||||||
|
}
|
||||||
|
} else if (isVisible) {
|
||||||
|
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame,
|
||||||
|
aFrame->GetRectRelativeToSelf(),
|
||||||
|
aLists.BorderBackground());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isVisible) {
|
||||||
|
// XXX: should box-shadow for rows/rowgroups/columns/colgroups get painted
|
||||||
|
// just because we're visible? Or should it depend on the cell visibility
|
||||||
|
// when we're not the whole table?
|
||||||
|
|
||||||
// Paint the inset box-shadows for the table frames
|
// Paint the inset box-shadows for the table frames
|
||||||
if (hasBoxShadow) {
|
if (aFrame->StyleEffects()->mBoxShadow) {
|
||||||
aLists.BorderBackground()->AppendNewToTop(
|
aLists.BorderBackground()->AppendNewToTop(
|
||||||
new (aBuilder) nsDisplayBoxShadowInner(aBuilder, aFrame));
|
new (aBuilder) nsDisplayBoxShadowInner(aBuilder, aFrame));
|
||||||
}
|
}
|
||||||
|
@ -1314,8 +1370,8 @@ nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
|
||||||
|
|
||||||
aTraversal(aBuilder, aFrame, aDirtyRect, aLists);
|
aTraversal(aBuilder, aFrame, aDirtyRect, aLists);
|
||||||
|
|
||||||
if (aFrame->IsVisibleForPainting(aBuilder)) {
|
if (isVisible) {
|
||||||
if (aFrame->GetType() == nsGkAtoms::tableFrame) {
|
if (isTable) {
|
||||||
nsTableFrame* table = static_cast<nsTableFrame*>(aFrame);
|
nsTableFrame* table = static_cast<nsTableFrame*>(aFrame);
|
||||||
// In the collapsed border model, overlay all collapsed borders.
|
// In the collapsed border model, overlay all collapsed borders.
|
||||||
if (table->IsBorderCollapse()) {
|
if (table->IsBorderCollapse()) {
|
||||||
|
@ -3911,9 +3967,8 @@ nsTableFrame::DumpRowGroup(nsIFrame* aKidFrame)
|
||||||
for (nsIFrame* childFrame : cFrame->PrincipalChildList()) {
|
for (nsIFrame* childFrame : cFrame->PrincipalChildList()) {
|
||||||
nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
|
nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
|
||||||
if (cellFrame) {
|
if (cellFrame) {
|
||||||
int32_t colIndex;
|
uint32_t colIndex = cellFrame->ColIndex();
|
||||||
cellFrame->GetColIndex(colIndex);
|
printf("cell(%u)=%p ", colIndex, static_cast<void*>(childFrame));
|
||||||
printf("cell(%d)=%p ", colIndex, static_cast<void*>(childFrame));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
|
@ -235,7 +235,7 @@ nsTableRowFrame::InsertFrames(ChildListID aListID,
|
||||||
// insert the cells into the cell map
|
// insert the cells into the cell map
|
||||||
int32_t colIndex = -1;
|
int32_t colIndex = -1;
|
||||||
if (prevCellFrame) {
|
if (prevCellFrame) {
|
||||||
prevCellFrame->GetColIndex(colIndex);
|
colIndex = prevCellFrame->ColIndex();
|
||||||
}
|
}
|
||||||
tableFrame->InsertCells(cellChildren, GetRowIndex(), colIndex);
|
tableFrame->InsertCells(cellChildren, GetRowIndex(), colIndex);
|
||||||
|
|
||||||
|
@ -304,18 +304,6 @@ GetBSizeOfRowsSpannedBelowFirst(nsTableCellFrame& aTableCellFrame,
|
||||||
return bsize;
|
return bsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsTableCellFrame*
|
|
||||||
nsTableRowFrame::GetFirstCell()
|
|
||||||
{
|
|
||||||
for (nsIFrame* childFrame : mFrames) {
|
|
||||||
nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
|
|
||||||
if (cellFrame) {
|
|
||||||
return cellFrame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Post-reflow hook. This is where the table row does its post-processing
|
* Post-reflow hook. This is where the table row does its post-processing
|
||||||
*/
|
*/
|
||||||
|
@ -659,8 +647,7 @@ CalcAvailISize(nsTableFrame& aTableFrame,
|
||||||
nsTableCellFrame& aCellFrame)
|
nsTableCellFrame& aCellFrame)
|
||||||
{
|
{
|
||||||
nscoord cellAvailISize = 0;
|
nscoord cellAvailISize = 0;
|
||||||
int32_t colIndex;
|
uint32_t colIndex = aCellFrame.ColIndex();
|
||||||
aCellFrame.GetColIndex(colIndex);
|
|
||||||
int32_t colspan = aTableFrame.GetEffectiveColSpan(aCellFrame);
|
int32_t colspan = aTableFrame.GetEffectiveColSpan(aCellFrame);
|
||||||
NS_ASSERTION(colspan > 0, "effective colspan should be positive");
|
NS_ASSERTION(colspan > 0, "effective colspan should be positive");
|
||||||
nsTableFrame* fifTable =
|
nsTableFrame* fifTable =
|
||||||
|
@ -799,12 +786,12 @@ nsTableRowFrame::ReflowChildren(nsPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t cellColIndex;
|
uint32_t cellColIndex = cellFrame->ColIndex();
|
||||||
cellFrame->GetColIndex(cellColIndex);
|
|
||||||
cellColSpan = aTableFrame.GetEffectiveColSpan(*cellFrame);
|
cellColSpan = aTableFrame.GetEffectiveColSpan(*cellFrame);
|
||||||
|
|
||||||
// If the adjacent cell is in a prior row (because of a rowspan) add in the space
|
// If the adjacent cell is in a prior row (because of a rowspan) add in the space
|
||||||
if (prevColIndex != (cellColIndex - 1)) {
|
// NOTE: prevColIndex can be -1 here.
|
||||||
|
if (prevColIndex != (static_cast<int32_t>(cellColIndex) - 1)) {
|
||||||
iCoord += GetSpaceBetween(prevColIndex, cellColIndex, cellColSpan, aTableFrame,
|
iCoord += GetSpaceBetween(prevColIndex, cellColIndex, cellColSpan, aTableFrame,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
@ -1172,8 +1159,7 @@ nsTableRowFrame::CollapseRowIfNecessary(nscoord aRowOffset,
|
||||||
shift = rowRect.BSize(wm);
|
shift = rowRect.BSize(wm);
|
||||||
nsTableCellFrame* cellFrame = GetFirstCell();
|
nsTableCellFrame* cellFrame = GetFirstCell();
|
||||||
if (cellFrame) {
|
if (cellFrame) {
|
||||||
int32_t rowIndex;
|
uint32_t rowIndex = cellFrame->RowIndex();
|
||||||
cellFrame->GetRowIndex(rowIndex);
|
|
||||||
shift += tableFrame->GetRowSpacing(rowIndex);
|
shift += tableFrame->GetRowSpacing(rowIndex);
|
||||||
while (cellFrame) {
|
while (cellFrame) {
|
||||||
LogicalRect cRect = cellFrame->GetLogicalRect(wm, containerSize);
|
LogicalRect cRect = cellFrame->GetLogicalRect(wm, containerSize);
|
||||||
|
@ -1204,13 +1190,13 @@ nsTableRowFrame::CollapseRowIfNecessary(nscoord aRowOffset,
|
||||||
for (nsIFrame* kidFrame : mFrames) {
|
for (nsIFrame* kidFrame : mFrames) {
|
||||||
nsTableCellFrame *cellFrame = do_QueryFrame(kidFrame);
|
nsTableCellFrame *cellFrame = do_QueryFrame(kidFrame);
|
||||||
if (cellFrame) {
|
if (cellFrame) {
|
||||||
int32_t cellColIndex;
|
uint32_t cellColIndex = cellFrame->ColIndex();
|
||||||
cellFrame->GetColIndex(cellColIndex);
|
|
||||||
int32_t cellColSpan = tableFrame->GetEffectiveColSpan(*cellFrame);
|
int32_t cellColSpan = tableFrame->GetEffectiveColSpan(*cellFrame);
|
||||||
|
|
||||||
// If the adjacent cell is in a prior row (because of a rowspan) add in
|
// If the adjacent cell is in a prior row (because of a rowspan) add in
|
||||||
// the space
|
// the space
|
||||||
if (prevColIndex != (cellColIndex - 1)) {
|
// NOTE: prevColIndex can be -1 here.
|
||||||
|
if (prevColIndex != (static_cast<int32_t>(cellColIndex) - 1)) {
|
||||||
iPos += GetSpaceBetween(prevColIndex, cellColIndex, cellColSpan,
|
iPos += GetSpaceBetween(prevColIndex, cellColIndex, cellColSpan,
|
||||||
*tableFrame, true);
|
*tableFrame, true);
|
||||||
}
|
}
|
||||||
|
@ -1323,9 +1309,9 @@ nsTableRowFrame::InsertCellFrame(nsTableCellFrame* aFrame,
|
||||||
for (nsIFrame* child : mFrames) {
|
for (nsIFrame* child : mFrames) {
|
||||||
nsTableCellFrame *cellFrame = do_QueryFrame(child);
|
nsTableCellFrame *cellFrame = do_QueryFrame(child);
|
||||||
if (cellFrame) {
|
if (cellFrame) {
|
||||||
int32_t colIndex;
|
uint32_t colIndex = cellFrame->ColIndex();
|
||||||
cellFrame->GetColIndex(colIndex);
|
// Can aColIndex be -1 here? Let's assume it can for now.
|
||||||
if (colIndex < aColIndex) {
|
if (static_cast<int32_t>(colIndex) < aColIndex) {
|
||||||
priorCell = cellFrame;
|
priorCell = cellFrame;
|
||||||
}
|
}
|
||||||
else break;
|
else break;
|
||||||
|
|
|
@ -82,7 +82,9 @@ public:
|
||||||
const nsRect& aDirtyRect,
|
const nsRect& aDirtyRect,
|
||||||
const nsDisplayListSet& aLists) override;
|
const nsDisplayListSet& aLists) override;
|
||||||
|
|
||||||
nsTableCellFrame* GetFirstCell() ;
|
// Implemented in nsTableCellFrame.h, because it needs to know about the
|
||||||
|
// nsTableCellFrame class, but we can't include nsTableCellFrame.h here.
|
||||||
|
inline nsTableCellFrame* GetFirstCell() const;
|
||||||
|
|
||||||
/** calls Reflow for all of its child cells.
|
/** calls Reflow for all of its child cells.
|
||||||
* Cells with rowspan=1 are all set to the same height and stacked horizontally.
|
* Cells with rowspan=1 are all set to the same height and stacked horizontally.
|
||||||
|
|
|
@ -137,8 +137,7 @@ nsTableRowGroupFrame::InitRepeatedFrame(nsTableRowGroupFrame* aHeaderFooterFrame
|
||||||
while (copyCellFrame && originalCellFrame) {
|
while (copyCellFrame && originalCellFrame) {
|
||||||
NS_ASSERTION(originalCellFrame->GetContent() == copyCellFrame->GetContent(),
|
NS_ASSERTION(originalCellFrame->GetContent() == copyCellFrame->GetContent(),
|
||||||
"cell frames have different content");
|
"cell frames have different content");
|
||||||
int32_t colIndex;
|
uint32_t colIndex = originalCellFrame->ColIndex();
|
||||||
originalCellFrame->GetColIndex(colIndex);
|
|
||||||
copyCellFrame->SetColIndex(colIndex);
|
copyCellFrame->SetColIndex(colIndex);
|
||||||
|
|
||||||
// Move to the next cell frame
|
// Move to the next cell frame
|
||||||
|
@ -998,8 +997,7 @@ nsTableRowGroupFrame::SplitSpanningCells(nsPresContext& aPresContext,
|
||||||
nsTableCellFrame* contCell = static_cast<nsTableCellFrame*>(
|
nsTableCellFrame* contCell = static_cast<nsTableCellFrame*>(
|
||||||
aPresContext.PresShell()->FrameConstructor()->
|
aPresContext.PresShell()->FrameConstructor()->
|
||||||
CreateContinuingFrame(&aPresContext, cell, &aLastRow));
|
CreateContinuingFrame(&aPresContext, cell, &aLastRow));
|
||||||
int32_t colIndex;
|
uint32_t colIndex = cell->ColIndex();
|
||||||
cell->GetColIndex(colIndex);
|
|
||||||
aContRow->InsertCellFrame(contCell, colIndex);
|
aContRow->InsertCellFrame(contCell, colIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue