Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (267467 => 267468)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2020-09-23 10:27:14 UTC (rev 267467)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2020-09-23 12:03:57 UTC (rev 267468)
@@ -4975,6 +4975,8 @@
E3FA38641D71812D00AA5950 /* PendingScriptClient.h in Headers */ = {isa = PBXBuildFile; fileRef = E3FA38611D716E7600AA5950 /* PendingScriptClient.h */; };
E401C27517CE53EC00C41A35 /* ElementIteratorAssertions.h in Headers */ = {isa = PBXBuildFile; fileRef = E401C27417CE53EC00C41A35 /* ElementIteratorAssertions.h */; settings = {ATTRIBUTES = (Private, ); }; };
E401E0A41C3C0B8300F34D10 /* StyleChange.h in Headers */ = {isa = PBXBuildFile; fileRef = E401E0A31C3C0B8300F34D10 /* StyleChange.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ E403B7A2251B11930019E800 /* LayoutIntegrationCoverage.h in Headers */ = {isa = PBXBuildFile; fileRef = E403B7A1251B11930019E800 /* LayoutIntegrationCoverage.h */; };
+ E403B7A3251B11C10019E800 /* LayoutIntegrationPagination.h in Headers */ = {isa = PBXBuildFile; fileRef = E4312AB724B3265600678349 /* LayoutIntegrationPagination.h */; };
E418025523D4549B00FFB071 /* LayoutIntegrationBoxTree.h in Headers */ = {isa = PBXBuildFile; fileRef = E418025323D4549A00FFB071 /* LayoutIntegrationBoxTree.h */; settings = {ATTRIBUTES = (Private, ); }; };
E419041F1CC6486B00C35F5D /* FontSelectorClient.h in Headers */ = {isa = PBXBuildFile; fileRef = E419041E1CC6486B00C35F5D /* FontSelectorClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
E42050172141901B0066EF3B /* ProcessWarming.h in Headers */ = {isa = PBXBuildFile; fileRef = E42050142141901A0066EF3B /* ProcessWarming.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -15814,6 +15816,8 @@
E401C27417CE53EC00C41A35 /* ElementIteratorAssertions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementIteratorAssertions.h; sourceTree = "<group>"; };
E401E0A31C3C0B8300F34D10 /* StyleChange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleChange.h; sourceTree = "<group>"; };
E401E0A51C3C0CF700F34D10 /* StyleChange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleChange.cpp; sourceTree = "<group>"; };
+ E403B79F251B118B0019E800 /* LayoutIntegrationCoverage.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LayoutIntegrationCoverage.cpp; sourceTree = "<group>"; };
+ E403B7A1251B11930019E800 /* LayoutIntegrationCoverage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LayoutIntegrationCoverage.h; sourceTree = "<group>"; };
E406F3FB1198307D009D59D6 /* ColorData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ColorData.cpp; path = DerivedSources/WebCore/ColorData.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
E418025323D4549A00FFB071 /* LayoutIntegrationBoxTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LayoutIntegrationBoxTree.h; sourceTree = "<group>"; };
E418025623D454B500FFB071 /* LayoutIntegrationBoxTree.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LayoutIntegrationBoxTree.cpp; sourceTree = "<group>"; };
@@ -28443,12 +28447,14 @@
E4FB4B1E2395356F003C336A /* integration */ = {
isa = PBXGroup;
children = (
- E4312AB524B3265600678349 /* LayoutIntegrationPagination.cpp */,
- E4312AB724B3265600678349 /* LayoutIntegrationPagination.h */,
E418025623D454B500FFB071 /* LayoutIntegrationBoxTree.cpp */,
E418025323D4549A00FFB071 /* LayoutIntegrationBoxTree.h */,
+ E403B79F251B118B0019E800 /* LayoutIntegrationCoverage.cpp */,
+ E403B7A1251B11930019E800 /* LayoutIntegrationCoverage.h */,
E4ABABDE2360893D00FA4345 /* LayoutIntegrationLineLayout.cpp */,
E4ABABDB236088FD00FA4345 /* LayoutIntegrationLineLayout.h */,
+ E4312AB524B3265600678349 /* LayoutIntegrationPagination.cpp */,
+ E4312AB724B3265600678349 /* LayoutIntegrationPagination.h */,
);
path = integration;
sourceTree = "<group>";
@@ -32783,6 +32789,7 @@
B22279650D00BF220071B782 /* LinearGradientAttributes.h in Headers */,
AB31C91E10AE1B8E000C7B92 /* LineClampValue.h in Headers */,
FFEFAB2A18380DA000514534 /* LineLayoutState.h in Headers */,
+ E403B7A2251B11930019E800 /* LayoutIntegrationCoverage.h in Headers */,
E484A33E23055325009ADE6A /* LineLayoutTraversal.h in Headers */,
E4343D252392779000EBBB66 /* LineLayoutTraversalComplexPath.h in Headers */,
E451C628239293EC00993190 /* LineLayoutTraversalDisplayRunPath.h in Headers */,
@@ -33651,6 +33658,7 @@
228C284510D82500009D0D0E /* ScriptWrappable.h in Headers */,
1400D7A817136EA70077CE05 /* ScriptWrappableInlines.h in Headers */,
BC8AE34F12EA096A00EB3AE6 /* ScrollableArea.h in Headers */,
+ E403B7A3251B11C10019E800 /* LayoutIntegrationPagination.h in Headers */,
5D925B680F64D4DD00B847F0 /* ScrollAlignment.h in Headers */,
CA3BF67E10D99BAE00E6CE53 /* ScrollAnimator.h in Headers */,
0F1774801378B772009DA76A /* ScrollAnimatorIOS.h in Headers */,
Added: trunk/Source/WebCore/layout/integration/LayoutIntegrationCoverage.cpp (0 => 267468)
--- trunk/Source/WebCore/layout/integration/LayoutIntegrationCoverage.cpp (rev 0)
+++ trunk/Source/WebCore/layout/integration/LayoutIntegrationCoverage.cpp 2020-09-23 12:03:57 UTC (rev 267468)
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2013-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 "LayoutIntegrationCoverage.h"
+
+#include "DocumentMarkerController.h"
+#include "HTMLTextFormControlElement.h"
+#include "Logging.h"
+#include "RenderBlockFlow.h"
+#include "RenderMultiColumnFlow.h"
+#include "RenderTextControl.h"
+#include "RenderView.h"
+#include "RuntimeEnabledFeatures.h"
+#include "Settings.h"
+
+#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+
+#ifndef NDEBUG
+#define SET_REASON_AND_RETURN_IF_NEEDED(reason, reasons, includeReasons) { \
+ reasons.add(AvoidanceReason::reason); \
+ if (includeReasons == IncludeReasons::First) \
+ return reasons; \
+ }
+#else
+#define SET_REASON_AND_RETURN_IF_NEEDED(reason, reasons, includeReasons) { \
+ ASSERT_UNUSED(includeReasons, includeReasons == IncludeReasons::First); \
+ reasons.add(AvoidanceReason::reason); \
+ return reasons; \
+ }
+#endif
+
+#ifndef NDEBUG
+#define ADD_REASONS_AND_RETURN_IF_NEEDED(newReasons, reasons, includeReasons) { \
+ reasons.add(newReasons); \
+ if (includeReasons == IncludeReasons::First) \
+ return reasons; \
+ }
+#else
+#define ADD_REASONS_AND_RETURN_IF_NEEDED(newReasons, reasons, includeReasons) { \
+ ASSERT_UNUSED(includeReasons, includeReasons == IncludeReasons::First); \
+ reasons.add(newReasons); \
+ return reasons; \
+ }
+#endif
+
+namespace WebCore {
+namespace LayoutIntegration {
+
+template <typename CharacterType> OptionSet<AvoidanceReason> canUseForCharacter(CharacterType, bool textIsJustified, IncludeReasons);
+
+template<> OptionSet<AvoidanceReason> canUseForCharacter(UChar character, bool textIsJustified, IncludeReasons includeReasons)
+{
+ OptionSet<AvoidanceReason> reasons;
+ if (textIsJustified) {
+ // Include characters up to Latin Extended-B and some punctuation range when text is justified.
+ bool isLatinIncludingExtendedB = character <= 0x01FF;
+ bool isPunctuationRange = character >= 0x2010 && character <= 0x2027;
+ if (!(isLatinIncludingExtendedB || isPunctuationRange))
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasJustifiedNonLatinText, reasons, includeReasons);
+ }
+
+ if (U16_IS_SURROGATE(character))
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowTextHasSurrogatePair, reasons, includeReasons);
+
+ UCharDirection direction = u_charDirection(character);
+ if (direction == U_RIGHT_TO_LEFT || direction == U_RIGHT_TO_LEFT_ARABIC
+ || direction == U_RIGHT_TO_LEFT_EMBEDDING || direction == U_RIGHT_TO_LEFT_OVERRIDE
+ || direction == U_LEFT_TO_RIGHT_EMBEDDING || direction == U_LEFT_TO_RIGHT_OVERRIDE
+ || direction == U_POP_DIRECTIONAL_FORMAT || direction == U_BOUNDARY_NEUTRAL)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowTextHasDirectionCharacter, reasons, includeReasons);
+
+ return reasons;
+}
+
+template<> OptionSet<AvoidanceReason> canUseForCharacter(LChar, bool, IncludeReasons)
+{
+ return { };
+}
+
+template <typename CharacterType>
+static OptionSet<AvoidanceReason> canUseForText(const CharacterType* text, unsigned length, const FontCascade& fontCascade, Optional<float> lineHeightConstraint,
+ bool textIsJustified, IncludeReasons includeReasons)
+{
+ OptionSet<AvoidanceReason> reasons;
+ auto& primaryFont = fontCascade.primaryFont();
+ auto& fontMetrics = primaryFont.fontMetrics();
+ auto availableSpaceForGlyphAscent = fontMetrics.ascent();
+ auto availableSpaceForGlyphDescent = fontMetrics.descent();
+ if (lineHeightConstraint) {
+ auto lineHeightPadding = *lineHeightConstraint - fontMetrics.height();
+ availableSpaceForGlyphAscent += lineHeightPadding / 2;
+ availableSpaceForGlyphDescent += lineHeightPadding / 2;
+ }
+
+ for (unsigned i = 0; i < length; ++i) {
+ auto character = text[i];
+ if (FontCascade::treatAsSpace(character))
+ continue;
+
+ if (character == softHyphen)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowTextHasSoftHyphen, reasons, includeReasons);
+
+ auto characterReasons = canUseForCharacter(character, textIsJustified, includeReasons);
+ if (characterReasons)
+ ADD_REASONS_AND_RETURN_IF_NEEDED(characterReasons, reasons, includeReasons);
+
+ auto glyphData = fontCascade.glyphDataForCharacter(character, false);
+ if (!glyphData.isValid() || glyphData.font != &primaryFont)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowPrimaryFontIsInsufficient, reasons, includeReasons);
+
+ if (lineHeightConstraint) {
+ auto bounds = primaryFont.boundsForGlyph(glyphData.glyph);
+ if (ceilf(-bounds.y()) > availableSpaceForGlyphAscent || ceilf(bounds.maxY()) > availableSpaceForGlyphDescent)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowFontHasOverflowGlyph, reasons, includeReasons);
+ }
+ }
+ return reasons;
+}
+
+static OptionSet<AvoidanceReason> canUseForText(StringView text, const FontCascade& fontCascade, Optional<float> lineHeightConstraint, bool textIsJustified, IncludeReasons includeReasons)
+{
+ if (text.is8Bit())
+ return canUseForText(text.characters8(), text.length(), fontCascade, lineHeightConstraint, textIsJustified, includeReasons);
+ return canUseForText(text.characters16(), text.length(), fontCascade, lineHeightConstraint, textIsJustified, includeReasons);
+}
+
+static OptionSet<AvoidanceReason> canUseForFontAndText(const RenderBlockFlow& flow, IncludeReasons includeReasons)
+{
+ OptionSet<AvoidanceReason> reasons;
+ // We assume that all lines have metrics based purely on the primary font.
+ const auto& style = flow.style();
+ auto& fontCascade = style.fontCascade();
+ if (fontCascade.primaryFont().isInterstitial())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowIsMissingPrimaryFont, reasons, includeReasons);
+ Optional<float> lineHeightConstraint;
+ if (style.lineBoxContain().contains(LineBoxContain::Glyphs))
+ lineHeightConstraint = flow.lineHeight(false, HorizontalLine, PositionOfInteriorLineBoxes).toFloat();
+ bool flowIsJustified = style.textAlign() == TextAlignMode::Justify;
+ for (const auto& textRenderer : childrenOfType<RenderText>(flow)) {
+ // FIXME: Do not return until after checking all children.
+ if (textRenderer.text().isEmpty())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowTextIsEmpty, reasons, includeReasons);
+ if (textRenderer.isCombineText())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowTextIsCombineText, reasons, includeReasons);
+ if (textRenderer.isCounter())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowTextIsRenderCounter, reasons, includeReasons);
+ if (textRenderer.isQuote())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowTextIsRenderQuote, reasons, includeReasons);
+ if (textRenderer.isTextFragment())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowTextIsTextFragment, reasons, includeReasons);
+ if (textRenderer.isSVGInlineText())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowTextIsSVGInlineText, reasons, includeReasons);
+ if (!textRenderer.canUseSimpleFontCodePath()) {
+ // No need to check the code path at this point. We already know it can't be simple.
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasComplexFontCodePath, reasons, includeReasons);
+ } else {
+ TextRun run(String(textRenderer.text()));
+ run.setCharacterScanForCodePath(false);
+ if (style.fontCascade().codePath(run) != FontCascade::Simple)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasComplexFontCodePath, reasons, includeReasons);
+ }
+
+ auto textReasons = canUseForText(textRenderer.stringView(), fontCascade, lineHeightConstraint, flowIsJustified, includeReasons);
+ if (textReasons)
+ ADD_REASONS_AND_RETURN_IF_NEEDED(textReasons, reasons, includeReasons);
+ }
+ return reasons;
+}
+
+static OptionSet<AvoidanceReason> canUseForStyle(const RenderStyle& style, IncludeReasons includeReasons)
+{
+ OptionSet<AvoidanceReason> reasons;
+ if (style.textOverflow() == TextOverflow::Ellipsis)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasTextOverflow, reasons, includeReasons);
+ if (style.textUnderlinePosition() != TextUnderlinePosition::Auto || !style.textUnderlineOffset().isAuto() || !style.textDecorationThickness().isAuto())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasUnsupportedUnderlineDecoration, reasons, includeReasons);
+ // Non-visible overflow should be pretty easy to support.
+ if (style.overflowX() != Overflow::Visible || style.overflowY() != Overflow::Visible)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasOverflowNotVisible, reasons, includeReasons);
+ if (!style.isLeftToRightDirection())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowIsNotLTR, reasons, includeReasons);
+ if (!(style.lineBoxContain().contains(LineBoxContain::Block)))
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasLineBoxContainProperty, reasons, includeReasons);
+ if (style.writingMode() != WritingMode::TopToBottom)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowIsNotTopToBottom, reasons, includeReasons);
+ if (style.lineBreak() != LineBreak::Auto)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasLineBreak, reasons, includeReasons);
+ if (style.unicodeBidi() != UBNormal)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasNonNormalUnicodeBiDi, reasons, includeReasons);
+ if (style.rtlOrdering() != Order::Logical)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasRTLOrdering, reasons, includeReasons);
+ if (style.lineAlign() != LineAlign::None)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasLineAlignEdges, reasons, includeReasons);
+ if (style.lineSnap() != LineSnap::None)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasLineSnap, reasons, includeReasons);
+ if (style.textEmphasisFill() != TextEmphasisFill::Filled || style.textEmphasisMark() != TextEmphasisMark::None)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasTextEmphasisFillOrMark, reasons, includeReasons);
+ if (style.textShadow())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasTextShadow, reasons, includeReasons);
+ if (style.hasPseudoStyle(PseudoId::FirstLine))
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasPseudoFirstLine, reasons, includeReasons);
+ if (style.hasPseudoStyle(PseudoId::FirstLetter))
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasPseudoFirstLetter, reasons, includeReasons);
+ if (style.hasTextCombine())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasTextCombine, reasons, includeReasons);
+ if (style.backgroundClip() == FillBox::Text)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasTextFillBox, reasons, includeReasons);
+ if (style.borderFit() == BorderFit::Lines)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasBorderFitLines, reasons, includeReasons);
+ if (style.lineBreak() != LineBreak::Auto)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasNonAutoLineBreak, reasons, includeReasons);
+ if (style.nbspMode() != NBSPMode::Normal)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasWebKitNBSPMode, reasons, includeReasons);
+ // Special handling of text-security:disc is not yet implemented in the simple line layout code path.
+ // See RenderBlock::updateSecurityDiscCharacters.
+ if (style.textSecurity() != TextSecurity::None)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasTextSecurity, reasons, includeReasons);
+ if (style.hyphens() == Hyphens::Auto) {
+ auto textReasons = canUseForText(style.hyphenString(), style.fontCascade(), WTF::nullopt, false, includeReasons);
+ if (textReasons)
+ ADD_REASONS_AND_RETURN_IF_NEEDED(textReasons, reasons, includeReasons);
+ }
+ return reasons;
+}
+
+OptionSet<AvoidanceReason> canUseForLineLayoutWithReason(const RenderBlockFlow& flow, IncludeReasons includeReasons)
+{
+ OptionSet<AvoidanceReason> reasons;
+ // FIXME: For tests that disable SLL and expect to get CLL.
+ if (!flow.settings().simpleLineLayoutEnabled())
+ SET_REASON_AND_RETURN_IF_NEEDED(FeatureIsDisabled, reasons, includeReasons);
+ if (!flow.parent())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasNoParent, reasons, includeReasons);
+ if (!flow.firstChild())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasNoChild, reasons, includeReasons);
+ if (flow.fragmentedFlowState() != RenderObject::NotInsideFragmentedFlow) {
+ auto* fragmentedFlow = flow.enclosingFragmentedFlow();
+ if (!is<RenderMultiColumnFlow>(fragmentedFlow))
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowIsInsideANonMultiColumnThread, reasons, includeReasons);
+ auto& columnThread = downcast<RenderMultiColumnFlow>(*fragmentedFlow);
+ if (columnThread.parent() != &flow.view())
+ SET_REASON_AND_RETURN_IF_NEEDED(MultiColumnFlowIsNotTopLevel, reasons, includeReasons);
+ if (columnThread.hasColumnSpanner())
+ SET_REASON_AND_RETURN_IF_NEEDED(MultiColumnFlowHasColumnSpanner, reasons, includeReasons);
+ auto& style = flow.style();
+ if (style.verticalAlign() != VerticalAlign::Baseline)
+ SET_REASON_AND_RETURN_IF_NEEDED(MultiColumnFlowVerticalAlign, reasons, includeReasons);
+ if (style.isFloating())
+ SET_REASON_AND_RETURN_IF_NEEDED(MultiColumnFlowIsFloating, reasons, includeReasons);
+ }
+ if (!flow.isHorizontalWritingMode())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasHorizonalWritingMode, reasons, includeReasons);
+ if (flow.hasOutline())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasOutline, reasons, includeReasons);
+ if (flow.isRubyText() || flow.isRubyBase())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowIsRuby, reasons, includeReasons);
+ if (!flow.style().hangingPunctuation().isEmpty())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasHangingPunctuation, reasons, includeReasons);
+
+ // Printing does pagination without a flow thread.
+ if (flow.document().paginated())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowIsPaginated, reasons, includeReasons);
+ if (flow.firstLineBlock())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasPseudoFirstLine, reasons, includeReasons);
+ if (flow.isAnonymousBlock() && flow.parent()->style().textOverflow() == TextOverflow::Ellipsis)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasTextOverflow, reasons, includeReasons);
+ if (flow.parent()->isDeprecatedFlexibleBox())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowIsDepricatedFlexBox, reasons, includeReasons);
+ // FIXME: Placeholders do something strange.
+ if (is<RenderTextControl>(*flow.parent()) && downcast<RenderTextControl>(*flow.parent()).textFormControlElement().placeholderElement())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowParentIsPlaceholderElement, reasons, includeReasons);
+ // FIXME: Implementation of wrap=hard looks into lineboxes.
+ if (flow.parent()->isTextArea() && flow.parent()->element()->hasAttributeWithoutSynchronization(HTMLNames::wrapAttr))
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowParentIsTextAreaWithWrapping, reasons, includeReasons);
+ // This currently covers <blockflow>#text</blockflow>, <blockflow>#text<br></blockflow> and mutiple (sibling) RenderText cases.
+ // The <blockflow><inline>#text</inline></blockflow> case is also popular and should be relatively easy to cover.
+ for (const auto* child = flow.firstChild(); child;) {
+ if (child->selectionState() != RenderObject::HighlightState::None)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowChildIsSelected, reasons, includeReasons);
+ if (is<RenderText>(*child)) {
+ const auto& renderText = downcast<RenderText>(*child);
+ if (renderText.textNode() && !renderText.document().markers().markersFor(*renderText.textNode()).isEmpty())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowIncludesDocumentMarkers, reasons, includeReasons);
+ child = child->nextSibling();
+ continue;
+ }
+ if (is<RenderLineBreak>(child) && !downcast<RenderLineBreak>(*child).isWBR() && child->style().clear() == Clear::None) {
+ child = child->nextSibling();
+ continue;
+ }
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasNonSupportedChild, reasons, includeReasons);
+ break;
+ }
+ auto styleReasons = canUseForStyle(flow.style(), includeReasons);
+ if (styleReasons)
+ ADD_REASONS_AND_RETURN_IF_NEEDED(styleReasons, reasons, includeReasons);
+ // We can't use the code path if any lines would need to be shifted below floats. This is because we don't keep per-line y coordinates.
+ if (flow.containsFloats()) {
+ float minimumWidthNeeded = std::numeric_limits<float>::max();
+ for (const auto& textRenderer : childrenOfType<RenderText>(flow)) {
+ minimumWidthNeeded = std::min(minimumWidthNeeded, textRenderer.minLogicalWidth());
+
+ for (auto& floatingObject : *flow.floatingObjectSet()) {
+ ASSERT(floatingObject);
+ // if a float has a shape, we cannot tell if content will need to be shifted until after we lay it out,
+ // since the amount of space is not uniform for the height of the float.
+ if (floatingObject->renderer().shapeOutsideInfo())
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasUnsupportedFloat, reasons, includeReasons);
+ float availableWidth = flow.availableLogicalWidthForLine(floatingObject->y(), DoNotIndentText);
+ if (availableWidth < minimumWidthNeeded)
+ SET_REASON_AND_RETURN_IF_NEEDED(FlowHasUnsupportedFloat, reasons, includeReasons);
+ }
+ }
+ }
+ auto fontAndTextReasons = canUseForFontAndText(flow, includeReasons);
+ if (fontAndTextReasons)
+ ADD_REASONS_AND_RETURN_IF_NEEDED(fontAndTextReasons, reasons, includeReasons);
+ return reasons;
+}
+
+bool canUseForLineLayout(const RenderBlockFlow& flow)
+{
+ return canUseForLineLayoutWithReason(flow, IncludeReasons::First).isEmpty();
+}
+
+bool canUseForLineLayoutAfterStyleChange(const RenderBlockFlow& blockContainer, StyleDifference diff)
+{
+ switch (diff) {
+ case StyleDifference::Equal:
+ case StyleDifference::RecompositeLayer:
+ return true;
+ case StyleDifference::Repaint:
+ case StyleDifference::RepaintIfTextOrBorderOrOutline:
+ case StyleDifference::RepaintLayer:
+ // FIXME: We could do a more focused style check by matching RendererStyle::changeRequiresRepaint&co.
+ return canUseForStyle(blockContainer.style(), IncludeReasons::First).isEmpty();
+ case StyleDifference::LayoutPositionedMovementOnly:
+ return true;
+ case StyleDifference::SimplifiedLayout:
+ case StyleDifference::SimplifiedLayoutAndPositionedMovement:
+ return canUseForStyle(blockContainer.style(), IncludeReasons::First).isEmpty();
+ case StyleDifference::Layout:
+ case StyleDifference::NewStyle:
+ return canUseForLineLayout(blockContainer);
+ }
+ ASSERT_NOT_REACHED();
+ return canUseForLineLayout(blockContainer);
+}
+
+}
+}
+
+#endif
Added: trunk/Source/WebCore/layout/integration/LayoutIntegrationCoverage.h (0 => 267468)
--- trunk/Source/WebCore/layout/integration/LayoutIntegrationCoverage.h (rev 0)
+++ trunk/Source/WebCore/layout/integration/LayoutIntegrationCoverage.h 2020-09-23 12:03:57 UTC (rev 267468)
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+
+#include "RenderStyleConstants.h"
+
+namespace WebCore {
+
+class RenderBlockFlow;
+
+namespace LayoutIntegration {
+
+enum class AvoidanceReason : uint64_t {
+ FlowIsInsideANonMultiColumnThread = 1LLU << 0,
+ FlowHasHorizonalWritingMode = 1LLU << 1,
+ FlowHasOutline = 1LLU << 2,
+ FlowIsRuby = 1LLU << 3,
+ FlowIsPaginated = 1LLU << 4,
+ FlowHasTextOverflow = 1LLU << 5,
+ FlowIsDepricatedFlexBox = 1LLU << 6,
+ FlowParentIsPlaceholderElement = 1LLU << 7,
+ FlowParentIsTextAreaWithWrapping = 1LLU << 8,
+ FlowHasNonSupportedChild = 1LLU << 9,
+ FlowHasUnsupportedFloat = 1LLU << 10,
+ FlowHasUnsupportedUnderlineDecoration = 1LLU << 11,
+ FlowHasJustifiedNonLatinText = 1LLU << 12,
+ FlowHasOverflowNotVisible = 1LLU << 13,
+ FlowHasWebKitNBSPMode = 1LLU << 14,
+ FlowIsNotLTR = 1LLU << 15,
+ FlowHasLineBoxContainProperty = 1LLU << 16,
+ FlowIsNotTopToBottom = 1LLU << 17,
+ FlowHasLineBreak = 1LLU << 18,
+ FlowHasNonNormalUnicodeBiDi = 1LLU << 19,
+ FlowHasRTLOrdering = 1LLU << 20,
+ FlowHasLineAlignEdges = 1LLU << 21,
+ FlowHasLineSnap = 1LLU << 22,
+ FlowHasTextEmphasisFillOrMark = 1LLU << 23,
+ FlowHasTextShadow = 1LLU << 24,
+ FlowHasPseudoFirstLine = 1LLU << 25,
+ FlowHasPseudoFirstLetter = 1LLU << 26,
+ FlowHasTextCombine = 1LLU << 27,
+ FlowHasTextFillBox = 1LLU << 28,
+ FlowHasBorderFitLines = 1LLU << 29,
+ FlowHasNonAutoLineBreak = 1LLU << 30,
+ FlowHasTextSecurity = 1LLU << 31,
+ FlowHasSVGFont = 1LLU << 32,
+ FlowTextIsEmpty = 1LLU << 33,
+ FlowTextHasSoftHyphen = 1LLU << 34,
+ FlowTextHasDirectionCharacter = 1LLU << 35,
+ FlowIsMissingPrimaryFont = 1LLU << 36,
+ FlowPrimaryFontIsInsufficient = 1LLU << 37,
+ FlowTextIsCombineText = 1LLU << 38,
+ FlowTextIsRenderCounter = 1LLU << 39,
+ FlowTextIsRenderQuote = 1LLU << 40,
+ FlowTextIsTextFragment = 1LLU << 41,
+ FlowTextIsSVGInlineText = 1LLU << 42,
+ FlowHasComplexFontCodePath = 1LLU << 43,
+ FeatureIsDisabled = 1LLU << 44,
+ FlowHasNoParent = 1LLU << 45,
+ FlowHasNoChild = 1LLU << 46,
+ FlowChildIsSelected = 1LLU << 47,
+ FlowHasHangingPunctuation = 1LLU << 48,
+ FlowFontHasOverflowGlyph = 1LLU << 49,
+ FlowTextHasSurrogatePair = 1LLU << 50,
+ MultiColumnFlowIsNotTopLevel = 1LLU << 51,
+ MultiColumnFlowHasColumnSpanner = 1LLU << 52,
+ MultiColumnFlowVerticalAlign = 1LLU << 53,
+ MultiColumnFlowIsFloating = 1LLU << 54,
+ FlowIncludesDocumentMarkers = 1LLU << 55,
+ EndOfReasons = 1LLU << 56
+};
+
+bool canUseForLineLayout(const RenderBlockFlow&);
+bool canUseForLineLayoutAfterStyleChange(const RenderBlockFlow&, StyleDifference);
+
+enum class IncludeReasons { First , All };
+OptionSet<AvoidanceReason> canUseForLineLayoutWithReason(const RenderBlockFlow&, IncludeReasons);
+
+}
+}
+
+#endif