LineInlineHeaders.h [plain text]
#ifndef LineInlineHeaders_h
#define LineInlineHeaders_h
#include "RenderLayer.h"
namespace WebCore {
enum WhitespacePosition { LeadingWhitespace, TrailingWhitespace };
inline bool hasInlineDirectionBordersPaddingOrMargin(const RenderInline& flow)
{
bool shouldApplyStartBorderPaddingOrMargin = !flow.parent()->isAnonymousBlock() || !flow.isInlineElementContinuation();
if (shouldApplyStartBorderPaddingOrMargin && (flow.borderStart() || flow.marginStart() || flow.paddingStart()))
return true;
bool shouldApplyEndBorderPaddingOrMargin = !flow.parent()->isAnonymousBlock() || flow.isInlineElementContinuation() || !flow.inlineElementContinuation();
return shouldApplyEndBorderPaddingOrMargin && (flow.borderEnd() || flow.marginEnd() || flow.paddingEnd());
}
inline const RenderStyle& lineStyle(const RenderObject& renderer, const LineInfo& lineInfo)
{
return lineInfo.isFirstLine() ? renderer.firstLineStyle() : renderer.style();
}
inline bool requiresLineBoxForContent(const RenderInline& flow, const LineInfo& lineInfo)
{
RenderElement* parent = flow.parent();
if (flow.document().inNoQuirksMode()) {
const RenderStyle& flowStyle = lineStyle(flow, lineInfo);
const RenderStyle& parentStyle = lineStyle(*parent, lineInfo);
if (flowStyle.lineHeight() != parentStyle.lineHeight()
|| flowStyle.verticalAlign() != parentStyle.verticalAlign()
|| !parentStyle.fontCascade().fontMetrics().hasIdenticalAscentDescentAndLineGap(flowStyle.fontCascade().fontMetrics()))
return true;
}
return false;
}
inline bool shouldCollapseWhiteSpace(const RenderStyle* style, const LineInfo& lineInfo, WhitespacePosition whitespacePosition)
{
return style->collapseWhiteSpace()
|| (whitespacePosition == TrailingWhitespace && style->whiteSpace() == PRE_WRAP && (!lineInfo.isEmpty() || !lineInfo.previousLineBrokeCleanly()));
}
inline bool skipNonBreakingSpace(const InlineIterator& it, const LineInfo& lineInfo)
{
if (it.renderer()->style().nbspMode() != SPACE || it.current() != noBreakSpace)
return false;
if (lineInfo.isEmpty() && lineInfo.previousLineBrokeCleanly())
return false;
return true;
}
inline bool alwaysRequiresLineBox(const RenderInline& flow)
{
return isEmptyInline(flow) && hasInlineDirectionBordersPaddingOrMargin(flow);
}
inline bool requiresLineBox(const InlineIterator& it, const LineInfo& lineInfo = LineInfo(), WhitespacePosition whitespacePosition = LeadingWhitespace)
{
if (it.renderer()->isFloatingOrOutOfFlowPositioned())
return false;
if (it.renderer()->isBR())
return true;
bool rendererIsEmptyInline = false;
if (is<RenderInline>(*it.renderer())) {
const auto& inlineRenderer = downcast<RenderInline>(*it.renderer());
if (!alwaysRequiresLineBox(inlineRenderer) && !requiresLineBoxForContent(inlineRenderer, lineInfo))
return false;
rendererIsEmptyInline = isEmptyInline(inlineRenderer);
}
if (!shouldCollapseWhiteSpace(&it.renderer()->style(), lineInfo, whitespacePosition))
return true;
UChar current = it.current();
bool notJustWhitespace = current != ' ' && current != '\t' && current != softHyphen && (current != '\n' || it.renderer()->preservesNewline()) && !skipNonBreakingSpace(it, lineInfo);
return notJustWhitespace || rendererIsEmptyInline;
}
inline void setStaticPositions(RenderBlockFlow& block, RenderBox& child)
{
RenderElement* containerBlock = child.container();
LayoutUnit blockHeight = block.logicalHeight();
if (is<RenderInline>(*containerBlock)) {
downcast<RenderInline>(*containerBlock).layer()->setStaticInlinePosition(block.startAlignedOffsetForLine(blockHeight, false));
downcast<RenderInline>(*containerBlock).layer()->setStaticBlockPosition(blockHeight);
}
block.updateStaticInlinePositionForChild(child, blockHeight);
child.layer()->setStaticBlockPosition(blockHeight);
}
}
#endif