163 lines
6.2 KiB
C++
163 lines
6.2 KiB
C++
/*
|
|
* Copyright (C) 2020 Apple Inc. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "DisplayBoxDecorationData.h"
|
|
|
|
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
|
|
|
|
#include "RenderStyle.h"
|
|
|
|
namespace WebCore {
|
|
namespace Display {
|
|
|
|
DEFINE_ALLOCATOR_WITH_HEAP_IDENTIFIER(BoxDecorationData);
|
|
|
|
BorderEdge::BorderEdge(float width, float innerWidth, float outerWidth, Color color, BorderStyle style, bool isTransparent, bool isPresent)
|
|
: m_color(color)
|
|
, m_width(width)
|
|
, m_innerWidth(innerWidth)
|
|
, m_outerWidth(outerWidth)
|
|
, m_style(style)
|
|
, m_isTransparent(isTransparent)
|
|
, m_isPresent(isPresent)
|
|
{
|
|
}
|
|
|
|
bool BorderEdge::obscuresBackground() const
|
|
{
|
|
if (!m_isPresent || m_isTransparent || !m_color.isOpaque() || m_style == BorderStyle::Hidden)
|
|
return false;
|
|
|
|
if (m_style == BorderStyle::Dotted || m_style == BorderStyle::Dashed || m_style == BorderStyle::Double)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool BorderEdge::obscuresBackgroundEdge(float scale) const
|
|
{
|
|
if (!m_isPresent || m_isTransparent || (m_width * scale) < floorToDevicePixel(2, scale) || !m_color.isOpaque() || m_style == BorderStyle::Hidden)
|
|
return false;
|
|
|
|
if (m_style == BorderStyle::Dotted || m_style == BorderStyle::Dashed)
|
|
return false;
|
|
|
|
if (m_style == BorderStyle::Double)
|
|
return m_width >= scale * floorToDevicePixel(5, scale); // The outer band needs to be >= 2px wide at unit scale.
|
|
|
|
return true;
|
|
}
|
|
|
|
RectEdges<BorderEdge> calculateBorderEdges(const RenderStyle& style, float pixelSnappingFactor, bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
|
|
{
|
|
bool horizontal = style.isHorizontalWritingMode();
|
|
|
|
auto constructBorderEdge = [&](float width, CSSPropertyID colorProperty, BorderStyle borderStyle, bool isTransparent, bool isPresent) ->BorderEdge {
|
|
float innerWidth = 0.f;
|
|
float outerWidth = 0.f;
|
|
|
|
if (borderStyle == BorderStyle::Double) {
|
|
if (borderStyle == BorderStyle::Double && width < floorToDevicePixel(3, pixelSnappingFactor))
|
|
borderStyle = BorderStyle::Solid;
|
|
else {
|
|
innerWidth = ceilToDevicePixel(width * 2 / 3, pixelSnappingFactor);
|
|
outerWidth = floorToDevicePixel(width / 3, pixelSnappingFactor);
|
|
}
|
|
}
|
|
|
|
float snappedWidth = floorToDevicePixel(width, pixelSnappingFactor);
|
|
return { snappedWidth, innerWidth, outerWidth, style.visitedDependentColorWithColorFilter(colorProperty), borderStyle, isTransparent, isPresent };
|
|
};
|
|
|
|
return {
|
|
constructBorderEdge(style.borderTopWidth(), CSSPropertyBorderTopColor, style.borderTopStyle(), style.borderTopIsTransparent(), !horizontal || includeLogicalRightEdge),
|
|
constructBorderEdge(style.borderRightWidth(), CSSPropertyBorderRightColor, style.borderRightStyle(), style.borderRightIsTransparent(), !horizontal || includeLogicalRightEdge),
|
|
constructBorderEdge(style.borderBottomWidth(), CSSPropertyBorderBottomColor, style.borderBottomStyle(), style.borderBottomIsTransparent(), horizontal || includeLogicalRightEdge),
|
|
constructBorderEdge(style.borderLeftWidth(), CSSPropertyBorderLeftColor, style.borderLeftStyle(), style.borderLeftIsTransparent(), !horizontal || includeLogicalLeftEdge)
|
|
};
|
|
}
|
|
|
|
std::pair<BoxSide, BoxSide> adjacentSidesForSide(BoxSide side)
|
|
{
|
|
switch (side) {
|
|
case BoxSide::Top: return { BoxSide::Left, BoxSide::Right };
|
|
case BoxSide::Bottom: return { BoxSide::Left, BoxSide::Right };
|
|
case BoxSide::Left: return { BoxSide::Top, BoxSide::Bottom };
|
|
case BoxSide::Right: return { BoxSide::Top, BoxSide::Bottom };
|
|
}
|
|
return { BoxSide::Left, BoxSide::Right };
|
|
}
|
|
|
|
BoxDecorationData::BoxDecorationData() = default;
|
|
|
|
bool BoxDecorationData::hasBorder() const
|
|
{
|
|
// FIXME: There's a tricky interaction between borders and border-image here: webkit.org/b/217900.
|
|
if (hasBorderImage())
|
|
return true;
|
|
|
|
for (auto side : allBoxSides) {
|
|
auto& edge = m_borderEdges[side];
|
|
if (edge.style() != BorderStyle::None && edge.width())
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool BoxDecorationData::borderObscuresBackground() const
|
|
{
|
|
if (!hasBorder())
|
|
return false;
|
|
|
|
// Bail if we have any border-image for now. We could look at the image alpha to improve this.
|
|
// FIXME: Check border-image.
|
|
|
|
for (auto side : allBoxSides) {
|
|
if (!m_borderEdges.at(side).obscuresBackground())
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool BoxDecorationData::borderObscuresBackgroundEdge(const FloatSize& contextScale) const
|
|
{
|
|
for (auto side : allBoxSides) {
|
|
auto& currEdge = m_borderEdges.at(side);
|
|
// FIXME: for vertical text
|
|
float axisScale = (side == BoxSide::Top || side == BoxSide::Bottom) ? contextScale.height() : contextScale.width();
|
|
if (!currEdge.obscuresBackgroundEdge(axisScale))
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
} // namespace Display
|
|
} // namespace WebCore
|
|
|
|
#endif // ENABLE(LAYOUT_FORMATTING_CONTEXT)
|