mirror of
https://github.com/HeyPuter/firefox.git
synced 2026-11-13 20:14:57 -10:00
Another preliminary change to simplify the `vertical-align` shorthand conversion (D277725). It introduces a new enum called `HTMLAlignValue` designed to avoid the problem of having different CSS enum types in the attribute mappings for the `align` attribute. In the process of implementing this, I found that the existing parsing and mapping of this attribute was convoluted and messy, with it not being immediately clear within a single element type how exactly the attribute value mapped to the CSS properties. (For example, the "div alignment" mapping was used for table elements, too, even though they had different parsing.) I added additional mapping methods so that each parser has a 1:1 correspondence with a mapper to avoid this confusion. Try for this change: https://treeherder.mozilla.org/jobs?repo=try&revision=04da2213b1818b7b0285563f430871e48ad0d3da Differential Revision: https://phabricator.services.mozilla.com/D277792
216 lines
6.6 KiB
C++
216 lines
6.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 "mozilla/dom/HTMLTableCellElement.h"
|
|
|
|
#include "celldata.h"
|
|
#include "mozilla/MappedDeclarationsBuilder.h"
|
|
#include "mozilla/dom/Document.h"
|
|
#include "mozilla/dom/HTMLTableCellElementBinding.h"
|
|
#include "mozilla/dom/HTMLTableElement.h"
|
|
#include "mozilla/dom/HTMLTableRowElement.h"
|
|
#include "nsAttrValueInlines.h"
|
|
|
|
namespace {
|
|
enum class StyleCellScope : uint8_t { Row, Col, Rowgroup, Colgroup };
|
|
} // namespace
|
|
|
|
NS_IMPL_NS_NEW_HTML_ELEMENT(TableCell)
|
|
|
|
namespace mozilla::dom {
|
|
|
|
HTMLTableCellElement::~HTMLTableCellElement() = default;
|
|
|
|
JSObject* HTMLTableCellElement::WrapNode(JSContext* aCx,
|
|
JS::Handle<JSObject*> aGivenProto) {
|
|
return HTMLTableCellElement_Binding::Wrap(aCx, this, aGivenProto);
|
|
}
|
|
|
|
NS_IMPL_ELEMENT_CLONE(HTMLTableCellElement)
|
|
|
|
// protected method
|
|
HTMLTableRowElement* HTMLTableCellElement::GetRow() const {
|
|
return HTMLTableRowElement::FromNodeOrNull(GetParent());
|
|
}
|
|
|
|
// protected method
|
|
HTMLTableElement* HTMLTableCellElement::GetTable() const {
|
|
nsIContent* parent = GetParent();
|
|
if (!parent) {
|
|
return nullptr;
|
|
}
|
|
|
|
// parent should be a row.
|
|
nsIContent* section = parent->GetParent();
|
|
if (!section) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (section->IsHTMLElement(nsGkAtoms::table)) {
|
|
// XHTML, without a row group.
|
|
return static_cast<HTMLTableElement*>(section);
|
|
}
|
|
|
|
// We have a row group.
|
|
nsIContent* result = section->GetParent();
|
|
if (result && result->IsHTMLElement(nsGkAtoms::table)) {
|
|
return static_cast<HTMLTableElement*>(result);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
int32_t HTMLTableCellElement::CellIndex() const {
|
|
HTMLTableRowElement* row = GetRow();
|
|
if (!row) {
|
|
return -1;
|
|
}
|
|
|
|
nsIHTMLCollection* cells = row->Cells();
|
|
if (!cells) {
|
|
return -1;
|
|
}
|
|
|
|
uint32_t numCells = cells->Length();
|
|
for (uint32_t i = 0; i < numCells; i++) {
|
|
if (cells->Item(i) == this) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
StyleLockedDeclarationBlock*
|
|
HTMLTableCellElement::GetMappedAttributesInheritedFromTable() const {
|
|
if (HTMLTableElement* table = GetTable()) {
|
|
return table->GetAttributesMappedForCell();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void HTMLTableCellElement::GetAlign(DOMString& aValue) {
|
|
if (!GetAttr(nsGkAtoms::align, aValue)) {
|
|
// There's no align attribute, ask the row for the alignment.
|
|
HTMLTableRowElement* row = GetRow();
|
|
if (row) {
|
|
row->GetAlign(aValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
static constexpr nsAttrValue::EnumTableEntry kCellScopeTable[] = {
|
|
{"row", StyleCellScope::Row},
|
|
{"col", StyleCellScope::Col},
|
|
{"rowgroup", StyleCellScope::Rowgroup},
|
|
{"colgroup", StyleCellScope::Colgroup},
|
|
};
|
|
|
|
void HTMLTableCellElement::GetScope(DOMString& aScope) {
|
|
GetEnumAttr(nsGkAtoms::scope, nullptr, aScope);
|
|
}
|
|
|
|
bool HTMLTableCellElement::ParseAttribute(int32_t aNamespaceID,
|
|
nsAtom* aAttribute,
|
|
const nsAString& aValue,
|
|
nsIPrincipal* aMaybeScriptedPrincipal,
|
|
nsAttrValue& aResult) {
|
|
if (aNamespaceID == kNameSpaceID_None) {
|
|
/* ignore these attributes, stored simply as strings
|
|
abbr, axis, ch, headers
|
|
*/
|
|
if (aAttribute == nsGkAtoms::colspan) {
|
|
aResult.ParseClampedNonNegativeInt(aValue, 1, 1, MAX_COLSPAN);
|
|
return true;
|
|
}
|
|
if (aAttribute == nsGkAtoms::rowspan) {
|
|
aResult.ParseClampedNonNegativeInt(aValue, 1, 0, MAX_ROWSPAN);
|
|
// quirks mode does not honor the special html 4 value of 0
|
|
if (aResult.GetIntegerValue() == 0 && InNavQuirksMode(OwnerDoc())) {
|
|
aResult.SetTo(1, &aValue);
|
|
}
|
|
return true;
|
|
}
|
|
if (aAttribute == nsGkAtoms::height) {
|
|
return aResult.ParseNonzeroHTMLDimension(aValue);
|
|
}
|
|
if (aAttribute == nsGkAtoms::width) {
|
|
return aResult.ParseNonzeroHTMLDimension(aValue);
|
|
}
|
|
if (aAttribute == nsGkAtoms::align) {
|
|
return ParseTableCellHAlignValue(aValue, aResult);
|
|
}
|
|
if (aAttribute == nsGkAtoms::bgcolor) {
|
|
return aResult.ParseColor(aValue);
|
|
}
|
|
if (aAttribute == nsGkAtoms::scope) {
|
|
return aResult.ParseEnumValue(aValue, kCellScopeTable, false);
|
|
}
|
|
if (aAttribute == nsGkAtoms::valign) {
|
|
return ParseTableVAlignValue(aValue, aResult);
|
|
}
|
|
}
|
|
|
|
return nsGenericHTMLElement::ParseBackgroundAttribute(
|
|
aNamespaceID, aAttribute, aValue, aResult) ||
|
|
nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
|
|
aMaybeScriptedPrincipal, aResult);
|
|
}
|
|
|
|
void HTMLTableCellElement::MapAttributesIntoRule(
|
|
MappedDeclarationsBuilder& aBuilder) {
|
|
MapImageSizeAttributesInto(aBuilder);
|
|
|
|
if (!aBuilder.PropertyIsSet(eCSSProperty_text_wrap_mode)) {
|
|
// nowrap: enum
|
|
if (aBuilder.GetAttr(nsGkAtoms::nowrap)) {
|
|
// See if our width is not a nonzero integer width.
|
|
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::width);
|
|
nsCompatibility mode = aBuilder.Document().GetCompatibilityMode();
|
|
if (!value || value->Type() != nsAttrValue::eInteger ||
|
|
value->GetIntegerValue() == 0 || eCompatibility_NavQuirks != mode) {
|
|
aBuilder.SetKeywordValue(eCSSProperty_text_wrap_mode,
|
|
StyleTextWrapMode::Nowrap);
|
|
}
|
|
}
|
|
}
|
|
|
|
nsGenericHTMLElement::MapTableCellHAlignAttributeInto(aBuilder);
|
|
nsGenericHTMLElement::MapTableVAlignAttributeInto(aBuilder);
|
|
nsGenericHTMLElement::MapBackgroundAttributesInto(aBuilder);
|
|
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
|
|
}
|
|
|
|
NS_IMETHODIMP_(bool)
|
|
HTMLTableCellElement::IsAttributeMapped(const nsAtom* aAttribute) const {
|
|
static const MappedAttributeEntry attributes[] = {
|
|
{nsGkAtoms::align}, {nsGkAtoms::valign}, {nsGkAtoms::nowrap},
|
|
#if 0
|
|
// XXXldb If these are implemented, they might need to move to
|
|
// GetAttributeChangeHint (depending on how, and preferably not).
|
|
{ nsGkAtoms::abbr },
|
|
{ nsGkAtoms::axis },
|
|
{ nsGkAtoms::headers },
|
|
{ nsGkAtoms::scope },
|
|
#endif
|
|
{nsGkAtoms::width}, {nsGkAtoms::height}, {nullptr}};
|
|
|
|
static const MappedAttributeEntry* const map[] = {
|
|
attributes,
|
|
sCommonAttributeMap,
|
|
sBackgroundAttributeMap,
|
|
};
|
|
|
|
return FindAttributeDependence(aAttribute, map);
|
|
}
|
|
|
|
nsMapRuleToAttributesFunc HTMLTableCellElement::GetAttributeMappingFunction()
|
|
const {
|
|
return &MapAttributesIntoRule;
|
|
}
|
|
|
|
} // namespace mozilla::dom
|