blob: dc1b5ba7b9a4a97762f13a8f1685fadfc2190818 [file] [log] [blame]
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/layout/layout_boxes.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/layout/container_box.h"
#include "cobalt/layout/rect_layout_unit.h"
#include "cobalt/layout/size_layout_unit.h"
namespace cobalt {
namespace layout {
LayoutBoxes::LayoutBoxes() {}
LayoutBoxes::~LayoutBoxes() {}
LayoutBoxes::Type LayoutBoxes::type() const { return kLayoutLayoutBoxes; }
// Algorithm for GetClientRects:
// https://www.w3.org/TR/2013/WD-cssom-view-20131217/#dom-element-getclientrects
scoped_refptr<dom::DOMRectList> LayoutBoxes::GetClientRects() const {
// 1. If the element on which it was invoked does not have an associated
// layout box return an empty DOMRectList object and stop this algorithm.
// 2. If the element has an associated SVG layout box return a DOMRectList
// object containing a single DOMRect object that describes the bounding box
// of the element as defined by the SVG specification, applying the transforms
// that apply to the element and its ancestors.
// 3. Return a DOMRectList object containing a list of DOMRect objects in
// content order describing the bounding border boxes (including those with a
// height or width of zero) with the following constraints:
// . Apply the transforms that apply to the element and its ancestors.
// . If the element on which the method was invoked has a computed value for
// the 'display' property of 'table' or 'inline-table' include both the
// table box and the caption box, if any, but not the anonymous container
// box.
// . Replace each anonymous block box with its child box(es) and repeat this
// until no anonymous block boxes are left in the final list.
scoped_refptr<dom::DOMRectList> dom_rect_list(new dom::DOMRectList());
for (Boxes::const_iterator box_iterator = boxes_.begin();
box_iterator != boxes_.end(); ++box_iterator) {
Box* box = *box_iterator;
do {
scoped_refptr<dom::DOMRect> dom_rect(new dom::DOMRect());
// TODO: Take transforms into account and recurse into anonymous block
// boxes. Our current clients don't currently rely on GetClientRects() to
// do that.
dom_rect->set_x(box->GetBorderBoxLeftEdge().toFloat());
dom_rect->set_y(box->GetBorderBoxTopEdge().toFloat());
SizeLayoutUnit box_size = box->GetBorderBoxSize();
dom_rect->set_width(box_size.width().toFloat());
dom_rect->set_height(box_size.height().toFloat());
dom_rect_list->AppendDOMRect(dom_rect);
box = box->GetSplitSibling();
} while (box != NULL);
}
return dom_rect_list;
}
bool LayoutBoxes::IsInline() const {
DCHECK(!boxes_.empty());
return boxes_.front()->computed_style()->display() ==
cssom::KeywordValue::GetInline();
}
float LayoutBoxes::GetBorderEdgeLeft() const {
return GetBoundingBorderRectangle().x();
}
float LayoutBoxes::GetBorderEdgeTop() const {
return GetBoundingBorderRectangle().y();
}
float LayoutBoxes::GetBorderEdgeWidth() const {
return GetBoundingBorderRectangle().width();
}
float LayoutBoxes::GetBorderEdgeHeight() const {
return GetBoundingBorderRectangle().height();
}
float LayoutBoxes::GetBorderLeftWidth() const {
DCHECK(!boxes_.empty());
return boxes_.front()->border_left_width().toFloat();
}
float LayoutBoxes::GetBorderTopWidth() const {
DCHECK(!boxes_.empty());
return boxes_.front()->border_top_width().toFloat();
}
float LayoutBoxes::GetMarginEdgeWidth() const {
DCHECK(!boxes_.empty());
return boxes_.front()->GetMarginBoxWidth().toFloat();
}
float LayoutBoxes::GetMarginEdgeHeight() const {
DCHECK(!boxes_.empty());
return boxes_.front()->GetMarginBoxHeight().toFloat();
}
float LayoutBoxes::GetPaddingEdgeLeft() const {
DCHECK(!boxes_.empty());
return boxes_.front()->GetPaddingBoxLeftEdge().toFloat();
}
float LayoutBoxes::GetPaddingEdgeTop() const {
DCHECK(!boxes_.empty());
return boxes_.front()->GetPaddingBoxTopEdge().toFloat();
}
float LayoutBoxes::GetPaddingEdgeWidth() const {
DCHECK(!boxes_.empty());
return boxes_.front()->GetPaddingBoxWidth().toFloat();
}
float LayoutBoxes::GetPaddingEdgeHeight() const {
DCHECK(!boxes_.empty());
return boxes_.front()->GetPaddingBoxHeight().toFloat();
}
void LayoutBoxes::InvalidateSizes() {
for (Boxes::const_iterator box_iterator = boxes_.begin();
box_iterator != boxes_.end(); ++box_iterator) {
Box* box = *box_iterator;
do {
box->InvalidateUpdateSizeInputsOfBoxAndAncestors();
box = box->GetSplitSibling();
} while (box != NULL);
}
}
void LayoutBoxes::InvalidateCrossReferences() {
for (Boxes::const_iterator box_iterator = boxes_.begin();
box_iterator != boxes_.end(); ++box_iterator) {
Box* box = *box_iterator;
do {
box->InvalidateCrossReferencesOfBoxAndAncestors();
box = box->GetSplitSibling();
} while (box != NULL);
}
}
void LayoutBoxes::InvalidateRenderTreeNodes() {
for (Boxes::const_iterator box_iterator = boxes_.begin();
box_iterator != boxes_.end(); ++box_iterator) {
Box* box = *box_iterator;
do {
box->InvalidateRenderTreeNodesOfBoxAndAncestors();
box = box->GetSplitSibling();
} while (box != NULL);
}
}
math::RectF LayoutBoxes::GetBoundingBorderRectangle() const {
// In the CSSOM View extensions to the HTMLElement interface, at
// https://www.w3.org/TR/2013/WD-cssom-view-20131217/#extensions-to-the-htmlelement-interface,
// the standard mentions the 'first CSS layout box associated with the
// element' and links to a definition 'The term CSS layout box refers to the
// same term in CSS', which is followed by a note 'ISSUE 2' that mentions 'The
// terms CSS layout box and SVG layout box are not currently defined by CSS or
// SVG', at https://www.w3.org/TR/2013/WD-cssom-view-20131217/#css-layout-box.
// This function calculates the bounding box of the border boxes of the layout
// boxes, mirroring behavior of most other browsers for the 'first CSS layout
// box associated with the element'.
RectLayoutUnit bounding_rectangle;
for (Boxes::const_iterator box_iterator = boxes_.begin();
box_iterator != boxes_.end(); ++box_iterator) {
Box* box = *box_iterator;
do {
bounding_rectangle.Union(box->GetBorderBox());
box = box->GetSplitSibling();
} while (box != NULL);
}
return math::RectF(bounding_rectangle.x().toFloat(),
bounding_rectangle.y().toFloat(),
bounding_rectangle.width().toFloat(),
bounding_rectangle.height().toFloat());
}
} // namespace layout
} // namespace cobalt