[css-multicol] Support percentages in column-gap
authorrego@igalia.com <rego@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 26 Jan 2018 14:57:47 +0000 (14:57 +0000)
committerrego@igalia.com <rego@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 26 Jan 2018 14:57:47 +0000 (14:57 +0000)
https://bugs.webkit.org/show_bug.cgi?id=182004

Reviewed by Javier Fernandez.

LayoutTests/imported/w3c:

New expected results for a few tests that are passing now.
One is the test for this specific patch, the other are tests related to animations
of "normal" and initial value, that were fixed with the introduction of GapLength.

* web-platform-tests/css/css-multicol/multicol-gap-animation-002-expected.txt:
* web-platform-tests/css/css-multicol/multicol-gap-animation-003-expected.txt:
* web-platform-tests/css/css-multicol/multicol-gap-percentage-001-expected.txt:

Source/WebCore:

This patch adds percentage support to column-gap property.

Most of the changes are related to the parsing logic,
the column-gap property now accepts both length and percentages,
on top of the "normal" initial value.
A new utility class GapLength has been added, as it'll be useful
to implement row-gap in the future.

Apart from that the muticolumn layout code has been modified
to resolve the percentage gaps (treating them as zero while computing
preferred widths) and resolving them during layout.
This doesn't follow the current text on the spec, but there is an
ongoing discussion that might cause the text is changed:
https://github.com/w3c/csswg-drafts/issues/509#issuecomment-355242101
We could update the implementation once we have a definitive answer
from the CSS WG.

Test: web-platform-tests/css/css-multicol/multicol-gap-percentage-001.html

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* css/CSSComputedStyleDeclaration.cpp:
(WebCore::ComputedStyleExtractor::valueForPropertyinStyle):
* css/CSSProperties.json:
* css/StyleBuilderConverter.h:
(WebCore::StyleBuilderConverter::convertGapLength):
* css/StyleBuilderCustom.h:
(WebCore::forwardInheritedValue):
* css/parser/CSSPropertyParser.cpp:
(WebCore::consumeGapLength):
(WebCore::CSSPropertyParser::parseSingleValue):
* page/FrameView.cpp:
(WebCore::FrameView::applyPaginationToViewport):
* page/animation/CSSPropertyAnimation.cpp:
(WebCore::blendFunc):
(WebCore::CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap):
* rendering/RenderBlockFlow.cpp:
(WebCore::RenderBlockFlow::columnGap const):
* rendering/RenderMultiColumnSet.cpp:
(WebCore::RenderMultiColumnSet::columnGap const):
* rendering/style/GapLength.cpp: Added.
(WebCore::operator<<):
* rendering/style/GapLength.h: Added.
(WebCore::GapLength::GapLength):
(WebCore::GapLength::isNormal const):
(WebCore::GapLength::length const):
(WebCore::GapLength::operator== const):
* rendering/style/RenderStyle.h:
(WebCore::RenderStyle::columnGap const):
(WebCore::RenderStyle::setColumnGap):
(WebCore::RenderStyle::initialColumnGap):
* rendering/style/StyleMultiColData.cpp:
(WebCore::StyleMultiColData::StyleMultiColData):
(WebCore::StyleMultiColData::operator== const):
* rendering/style/StyleMultiColData.h:
* style/StyleResolveForDocument.cpp:
(WebCore::Style::resolveForDocument):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@227676 268f45cc-cd09-0410-ab3c-d52691b4dbfc

22 files changed:
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/css/css-multicol/multicol-gap-animation-002-expected.txt
LayoutTests/imported/w3c/web-platform-tests/css/css-multicol/multicol-gap-animation-003-expected.txt
LayoutTests/imported/w3c/web-platform-tests/css/css-multicol/multicol-gap-percentage-001-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSComputedStyleDeclaration.cpp
Source/WebCore/css/CSSProperties.json
Source/WebCore/css/StyleBuilderConverter.h
Source/WebCore/css/StyleBuilderCustom.h
Source/WebCore/css/parser/CSSPropertyParser.cpp
Source/WebCore/page/FrameView.cpp
Source/WebCore/page/animation/CSSPropertyAnimation.cpp
Source/WebCore/rendering/RenderBlockFlow.cpp
Source/WebCore/rendering/RenderMultiColumnSet.cpp
Source/WebCore/rendering/style/GapLength.cpp [new file with mode: 0644]
Source/WebCore/rendering/style/GapLength.h [new file with mode: 0644]
Source/WebCore/rendering/style/RenderStyle.h
Source/WebCore/rendering/style/StyleMultiColData.cpp
Source/WebCore/rendering/style/StyleMultiColData.h
Source/WebCore/style/StyleResolveForDocument.cpp

index c64fbce..1b41f9a 100644 (file)
@@ -1,3 +1,18 @@
+2018-01-26  Manuel Rego Casasnovas  <rego@igalia.com>
+
+        [css-multicol] Support percentages in column-gap
+        https://bugs.webkit.org/show_bug.cgi?id=182004
+
+        Reviewed by Javier Fernandez.
+
+        New expected results for a few tests that are passing now.
+        One is the test for this specific patch, the other are tests related to animations
+        of "normal" and initial value, that were fixed with the introduction of GapLength.
+
+        * web-platform-tests/css/css-multicol/multicol-gap-animation-002-expected.txt:
+        * web-platform-tests/css/css-multicol/multicol-gap-animation-003-expected.txt:
+        * web-platform-tests/css/css-multicol/multicol-gap-percentage-001-expected.txt:
+
 2018-01-25  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/errorhandling.html crashes
index a24225b..ebfa3dd 100644 (file)
@@ -1,76 +1,16 @@
 
-FAIL .multicol 1 assert_equals: 
-<div class="multicol marginTopBottom" data-expected-width="8" data-expected-height="20">
-    <div data-offset-x="0" data-offset-y="0" data-expected-width="3" data-expected-height="20">XXXXX</div>
-    <div data-offset-x="5" data-offset-y="0" data-expected-width="3" data-expected-height="20">XXXXX</div>
-  </div>
-width expected 3 but got 0
-FAIL .multicol 2 assert_equals: 
-<div class="multicol marginTopBottom" data-expected-width="8" data-expected-height="60">
-    <div data-offset-x="0" data-offset-y="0" data-expected-width="3" data-expected-height="60">XX X X</div>
-    <div data-offset-x="5" data-offset-y="0" data-expected-width="3" data-expected-height="60">XX X X</div>
-  </div>
-width expected 3 but got 0
-FAIL .multicol 3 assert_equals: 
-<div class="multicol marginTopBottom" data-expected-width="8" data-expected-height="20">
-    <div data-offset-x="0" data-offset-y="0" data-expected-width="3" data-expected-height="20">X</div>
-    <div data-offset-x="5" data-offset-y="0" data-expected-width="3" data-expected-height="20">X</div>
-  </div>
-width expected 3 but got 0
-FAIL .multicol 4 assert_equals: 
-<div class="multicol marginTopBottom" data-expected-width="200" data-expected-height="20">
-    <div data-offset-x="0" data-offset-y="0" data-expected-width="75" data-expected-height="20">XXXXX</div>
-    <div data-offset-x="125" data-offset-y="0" data-expected-width="75" data-expected-height="20">XXXXX</div>
-  </div>
-width expected 75 but got 90
-FAIL .multicol 5 assert_equals: 
-<div class="multicol marginTopBottom" data-expected-width="200" data-expected-height="40">
-    <div data-offset-x="0" data-offset-y="0" data-expected-width="75" data-expected-height="40">XX X X</div>
-    <div data-offset-x="125" data-offset-y="0" data-expected-width="75" data-expected-height="40">XX X X</div>
-  </div>
-width expected 75 but got 90
-FAIL .multicol 6 assert_equals: 
-<div class="multicol marginTopBottom" data-expected-width="200" data-expected-height="20">
-    <div data-offset-x="0" data-offset-y="0" data-expected-width="75" data-expected-height="20">X</div>
-    <div data-offset-x="125" data-offset-y="0" data-expected-width="75" data-expected-height="20">X</div>
-  </div>
-width expected 75 but got 90
-FAIL .multicol 7 assert_equals: 
-<div class="multicol inlineBlock" data-expected-width="200" data-expected-height="20">
-  <div data-offset-x="0" data-offset-y="0" data-expected-width="75" data-expected-height="20">XXXXX</div>
-  <div data-offset-x="125" data-offset-y="0" data-expected-width="75" data-expected-height="20">XXXXX</div>
-</div>
-width expected 200 but got 220
-FAIL .multicol 8 assert_equals: 
-<div class="multicol inlineBlock" data-expected-width="240" data-expected-height="40">
-  <div data-offset-x="0" data-offset-y="0" data-expected-width="90" data-expected-height="40">XX X X</div>
-  <div data-offset-x="150" data-offset-y="0" data-expected-width="90" data-expected-height="40">XX X X</div>
-</div>
-width expected 240 but got 260
-FAIL .multicol 9 assert_equals: 
-<div class="multicol inlineBlock" data-expected-width="40" data-expected-height="20">
-  <div data-offset-x="0" data-offset-y="0" data-expected-width="15" data-expected-height="20">X</div>
-  <div data-offset-x="25" data-offset-y="0" data-expected-width="15" data-expected-height="20">X</div>
-</div>
-width expected 40 but got 60
-FAIL .multicol 10 assert_equals: 
-<div class="multicol fixed200" data-expected-width="200" data-expected-height="20">
-  <div data-offset-x="0" data-offset-y="0" data-expected-width="75" data-expected-height="20">XXXXX</div>
-  <div data-offset-x="125" data-offset-y="0" data-expected-width="75" data-expected-height="20">XXXXX</div>
-</div>
-width expected 75 but got 90
-FAIL .multicol 11 assert_equals: 
-<div class="multicol fixed200" data-expected-width="200" data-expected-height="40">
-  <div data-offset-x="0" data-offset-y="0" data-expected-width="75" data-expected-height="40">XX X X</div>
-  <div data-offset-x="125" data-offset-y="0" data-expected-width="75" data-expected-height="40">XX X X</div>
-</div>
-width expected 75 but got 90
-FAIL .multicol 12 assert_equals: 
-<div class="multicol fixed200" data-expected-width="200" data-expected-height="20">
-  <div data-offset-x="0" data-offset-y="0" data-expected-width="75" data-expected-height="20">X</div>
-  <div data-offset-x="125" data-offset-y="0" data-expected-width="75" data-expected-height="20">X</div>
-</div>
-width expected 75 but got 90
+PASS .multicol 1 
+PASS .multicol 2 
+PASS .multicol 3 
+PASS .multicol 4 
+PASS .multicol 5 
+PASS .multicol 6 
+PASS .multicol 7 
+PASS .multicol 8 
+PASS .multicol 9 
+PASS .multicol 10 
+PASS .multicol 11 
+PASS .multicol 12 
 Multicol container: fixed width
 
 X
index 3258624..2c1ebd7 100644 (file)
@@ -1,3 +1,68 @@
+2018-01-26  Manuel Rego Casasnovas  <rego@igalia.com>
+
+        [css-multicol] Support percentages in column-gap
+        https://bugs.webkit.org/show_bug.cgi?id=182004
+
+        Reviewed by Javier Fernandez.
+
+        This patch adds percentage support to column-gap property.
+
+        Most of the changes are related to the parsing logic,
+        the column-gap property now accepts both length and percentages,
+        on top of the "normal" initial value.
+        A new utility class GapLength has been added, as it'll be useful
+        to implement row-gap in the future.
+
+        Apart from that the muticolumn layout code has been modified
+        to resolve the percentage gaps (treating them as zero while computing
+        preferred widths) and resolving them during layout.
+        This doesn't follow the current text on the spec, but there is an
+        ongoing discussion that might cause the text is changed:
+        https://github.com/w3c/csswg-drafts/issues/509#issuecomment-355242101
+        We could update the implementation once we have a definitive answer
+        from the CSS WG.
+
+        Test: web-platform-tests/css/css-multicol/multicol-gap-percentage-001.html
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/CSSComputedStyleDeclaration.cpp:
+        (WebCore::ComputedStyleExtractor::valueForPropertyinStyle):
+        * css/CSSProperties.json:
+        * css/StyleBuilderConverter.h:
+        (WebCore::StyleBuilderConverter::convertGapLength):
+        * css/StyleBuilderCustom.h:
+        (WebCore::forwardInheritedValue):
+        * css/parser/CSSPropertyParser.cpp:
+        (WebCore::consumeGapLength):
+        (WebCore::CSSPropertyParser::parseSingleValue):
+        * page/FrameView.cpp:
+        (WebCore::FrameView::applyPaginationToViewport):
+        * page/animation/CSSPropertyAnimation.cpp:
+        (WebCore::blendFunc):
+        (WebCore::CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap):
+        * rendering/RenderBlockFlow.cpp:
+        (WebCore::RenderBlockFlow::columnGap const):
+        * rendering/RenderMultiColumnSet.cpp:
+        (WebCore::RenderMultiColumnSet::columnGap const):
+        * rendering/style/GapLength.cpp: Added.
+        (WebCore::operator<<):
+        * rendering/style/GapLength.h: Added.
+        (WebCore::GapLength::GapLength):
+        (WebCore::GapLength::isNormal const):
+        (WebCore::GapLength::length const):
+        (WebCore::GapLength::operator== const):
+        * rendering/style/RenderStyle.h:
+        (WebCore::RenderStyle::columnGap const):
+        (WebCore::RenderStyle::setColumnGap):
+        (WebCore::RenderStyle::initialColumnGap):
+        * rendering/style/StyleMultiColData.cpp:
+        (WebCore::StyleMultiColData::StyleMultiColData):
+        (WebCore::StyleMultiColData::operator== const):
+        * rendering/style/StyleMultiColData.h:
+        * style/StyleResolveForDocument.cpp:
+        (WebCore::Style::resolveForDocument):
+
 2018-01-26  Emilio Cobos Ãlvarez  <emilio@crisal.io>
 
         Remove unused RenderFragmentedFlow::createFragmentedFlowStyle.
index a8b821d..37eb959 100644 (file)
@@ -1916,6 +1916,7 @@ rendering/shapes/ShapeOutsideInfo.cpp
 rendering/style/BasicShapes.cpp
 rendering/style/ContentData.cpp
 rendering/style/FillLayer.cpp
+rendering/style/GapLength.cpp
 rendering/style/GridPosition.cpp
 rendering/style/GridPositionsResolver.cpp
 rendering/style/KeyframeList.cpp
index a493fc9..3b008e3 100644 (file)
                8AF4E55611DC5A36000ED3DE /* PerformanceNavigation.h in Headers */ = {isa = PBXBuildFile; fileRef = 8AF4E55311DC5A36000ED3DE /* PerformanceNavigation.h */; };
                8AF4E55C11DC5A63000ED3DE /* PerformanceTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 8AF4E55911DC5A63000ED3DE /* PerformanceTiming.h */; };
                8E4C96DD1AD4483500365A50 /* JSFetchResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E4C96D91AD4483500365A50 /* JSFetchResponse.h */; };
+               8EC6C963201A251600FBFA53 /* GapLength.h in Headers */ = {isa = PBXBuildFile; fileRef = 8EC6C961201A250100FBFA53 /* GapLength.h */; settings = {ATTRIBUTES = (Private, ); }; };
                8F67561B1288B17B0047ACA3 /* EventQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F6756191288B17B0047ACA3 /* EventQueue.h */; settings = {ATTRIBUTES = (Private, ); }; };
                9001774012E0347800648462 /* OESStandardDerivatives.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9001773D12E0347800648462 /* OESStandardDerivatives.cpp */; };
                9001774112E0347800648462 /* OESStandardDerivatives.h in Headers */ = {isa = PBXBuildFile; fileRef = 9001773E12E0347800648462 /* OESStandardDerivatives.h */; };
                8AF4E55411DC5A36000ED3DE /* PerformanceNavigation.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PerformanceNavigation.idl; sourceTree = "<group>"; };
                8AF4E55911DC5A63000ED3DE /* PerformanceTiming.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PerformanceTiming.h; sourceTree = "<group>"; };
                8AF4E55A11DC5A63000ED3DE /* PerformanceTiming.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PerformanceTiming.idl; sourceTree = "<group>"; };
+               8E33CD93201A29C100E39093 /* GapLength.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GapLength.cpp; sourceTree = "<group>"; };
                8E4C96D81AD4483500365A50 /* JSFetchResponse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFetchResponse.cpp; sourceTree = "<group>"; };
                8E4C96D91AD4483500365A50 /* JSFetchResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSFetchResponse.h; sourceTree = "<group>"; };
+               8EC6C961201A250100FBFA53 /* GapLength.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GapLength.h; sourceTree = "<group>"; };
                8F6756191288B17B0047ACA3 /* EventQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventQueue.h; sourceTree = "<group>"; };
                8F934D831189F1EE00508D5D /* JSMainThreadExecState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMainThreadExecState.h; sourceTree = "<group>"; };
                8F934D841189F1EE00508D5D /* JSMainThreadExecState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMainThreadExecState.cpp; sourceTree = "<group>"; };
                                BC22746E0E83664500E7F975 /* DataRef.h */,
                                BC5EB69C0E81DAEB00B25965 /* FillLayer.cpp */,
                                BC5EB69D0E81DAEB00B25965 /* FillLayer.h */,
+                               8E33CD93201A29C100E39093 /* GapLength.cpp */,
+                               8EC6C961201A250100FBFA53 /* GapLength.h */,
                                CD3E251B18046B0600E27F56 /* GridArea.h */,
                                CDEF4FD617E85C8F00AEE24B /* GridLength.h */,
                                E1F817451E897A5200F22CD0 /* GridPosition.cpp */,
                                51A9D9EA195B931F001B2B5C /* GamepadManager.h in Headers */,
                                515BE1921D54F5FB00DD7C68 /* GamepadProvider.h in Headers */,
                                515BE1931D54F5FB00DD7C68 /* GamepadProviderClient.h in Headers */,
+                               8EC6C963201A251600FBFA53 /* GapLength.h in Headers */,
                                935C477509AC4D8E00A6AAB4 /* GapRects.h in Headers */,
                                1432E8470C51493800B1500F /* GCController.h in Headers */,
                                C0C054CC1118C8E400CE2636 /* generate-bindings.pl in Headers */,
                                935207BE09BD410A00F2038D /* LocalizedStrings.h in Headers */,
                                BCE1C41B0D982980003B02F2 /* Location.h in Headers */,
                                A8239E0109B3CF8A00B60641 /* Logging.h in Headers */,
-                               94CFD60D1FEACEFE002488AD /* RenderLinesClampSet.h in Headers */,
                                9BA273F4172206BB0097CE47 /* LogicalSelectionOffsetCaches.h in Headers */,
                                0FDCD7F31D47E655009F08BC /* LogInitialization.h in Headers */,
                                93A806171E03B51C008A1F26 /* LongRange.h in Headers */,
                                3C244FEAA375AC633F88BE6F /* RenderLayerModelObject.h in Headers */,
                                0BE030A20F3112FB003C1A46 /* RenderLineBoxList.h in Headers */,
                                BCEA4864097D93020094C9E4 /* RenderLineBreak.h in Headers */,
+                               94CFD60A1FE9867E002488AD /* RenderLinesClampFlow.h in Headers */,
+                               94CFD60D1FEACEFE002488AD /* RenderLinesClampSet.h in Headers */,
                                ABB5419F0ACDDFE4002820EB /* RenderListBox.h in Headers */,
                                A8EA7A520A191A5200A8EF5F /* RenderListItem.h in Headers */,
                                A8EA7A500A191A5200A8EF5F /* RenderListMarker.h in Headers */,
                                A5CE9F3F1E4C4174001BBE7C /* ResourceTiming.h in Headers */,
                                CBC2D2301CE5B8A100D1880B /* ResourceTimingInformation.h in Headers */,
                                A5071E851C56D0DC009951BE /* ResourceUsageData.h in Headers */,
-                               94CFD60A1FE9867E002488AD /* RenderLinesClampFlow.h in Headers */,
                                ADBAD6EF1BCDD95700381325 /* ResourceUsageOverlay.h in Headers */,
                                A5071E871C56D0E1009951BE /* ResourceUsageThread.h in Headers */,
                                FD3160A512B026F700C1A359 /* Reverb.h in Headers */,
index 974fa6f..0a4716d 100644 (file)
@@ -2926,9 +2926,9 @@ RefPtr<CSSValue> ComputedStyleExtractor::valueForPropertyinStyle(const RenderSty
         case CSSPropertyColumnFill:
             return cssValuePool.createValue(style.columnFill());
         case CSSPropertyColumnGap:
-            if (style.hasNormalColumnGap())
+            if (style.columnGap().isNormal())
                 return cssValuePool.createIdentifierValue(CSSValueNormal);
-            return zoomAdjustedPixelValue(style.columnGap(), style);
+            return zoomAdjustedPixelValueForLength(style.columnGap().length(), style);
         case CSSPropertyWebkitColumnProgression:
             return cssValuePool.createValue(style.columnProgression());
         case CSSPropertyColumnRuleColor:
index 1b6c5f9..bbc0a59 100644 (file)
                 "aliases": [
                     "-webkit-column-gap"
                 ],
-                "custom": "All"
+                "converter": "GapLength"
             },
             "specification":  {
                 "category": "css-multicol",
-                "url": ""
+                "url": "https://drafts.csswg.org/css-multicol/#column-gap"
             }
         },
         "-webkit-column-progression": {
index 20d794d..9d60b10 100644 (file)
@@ -150,6 +150,8 @@ public:
 
     static Length convertPositionComponentX(StyleResolver&, const CSSValue&);
     static Length convertPositionComponentY(StyleResolver&, const CSSValue&);
+
+    static GapLength convertGapLength(StyleResolver&, const CSSValue&);
     
 private:
     friend class StyleBuilderCustom;
@@ -1538,4 +1540,9 @@ inline HangingPunctuation StyleBuilderConverter::convertHangingPunctuation(Style
     return result;
 }
 
+inline GapLength StyleBuilderConverter::convertGapLength(StyleResolver& styleResolver, const CSSValue& value)
+{
+    return (downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNormal) ? GapLength() : GapLength(convertLength(styleResolver, value));
+}
+
 } // namespace WebCore
index d48ed6d..54f1624 100644 (file)
@@ -62,6 +62,7 @@ template<typename T> inline T forwardInheritedValue(T&& value) { return std::for
 inline Length forwardInheritedValue(const Length& value) { auto copy = value; return copy; }
 inline LengthSize forwardInheritedValue(const LengthSize& value) { auto copy = value; return copy; }
 inline LengthBox forwardInheritedValue(const LengthBox& value) { auto copy = value; return copy; }
+inline GapLength forwardInheritedValue(const GapLength& value) { auto copy = value; return copy; }
 
 // Note that we assume the CSS parser only allows valid CSSValue types.
 class StyleBuilderCustom {
@@ -73,7 +74,6 @@ public:
     DECLARE_PROPERTY_CUSTOM_HANDLERS(BorderImageWidth);
     DECLARE_PROPERTY_CUSTOM_HANDLERS(BoxShadow);
     DECLARE_PROPERTY_CUSTOM_HANDLERS(Clip);
-    DECLARE_PROPERTY_CUSTOM_HANDLERS(ColumnGap);
     DECLARE_PROPERTY_CUSTOM_HANDLERS(Content);
     DECLARE_PROPERTY_CUSTOM_HANDLERS(CounterIncrement);
     DECLARE_PROPERTY_CUSTOM_HANDLERS(CounterReset);
@@ -1366,27 +1366,6 @@ inline void StyleBuilderCustom::applyValueWebkitSvgShadow(StyleResolver& styleRe
     svgStyle.setShadow(std::make_unique<ShadowData>(location, blur, 0, Normal, false, color.isValid() ? color : Color::transparent));
 }
 
-inline void StyleBuilderCustom::applyInitialColumnGap(StyleResolver& styleResolver)
-{
-    styleResolver.style()->setHasNormalColumnGap();
-}
-
-inline void StyleBuilderCustom::applyInheritColumnGap(StyleResolver& styleResolver)
-{
-    if (styleResolver.parentStyle()->hasNormalColumnGap())
-        styleResolver.style()->setHasNormalColumnGap();
-    else
-        styleResolver.style()->setColumnGap(styleResolver.parentStyle()->columnGap());
-}
-
-inline void StyleBuilderCustom::applyValueColumnGap(StyleResolver& styleResolver, CSSValue& value)
-{
-    if (downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNormal)
-        styleResolver.style()->setHasNormalColumnGap();
-    else
-        styleResolver.style()->setColumnGap(StyleBuilderConverter::convertComputedLength<float>(styleResolver, value));
-}
-
 inline void StyleBuilderCustom::applyInitialContent(StyleResolver& styleResolver)
 {
     styleResolver.style()->clearContent();
index 0d343c9..1892356 100644 (file)
@@ -1392,11 +1392,11 @@ static RefPtr<CSSValue> consumeColumnCount(CSSParserTokenRange& range)
     return consumePositiveInteger(range);
 }
 
-static RefPtr<CSSValue> consumeColumnGap(CSSParserTokenRange& range, CSSParserMode cssParserMode)
+static RefPtr<CSSValue> consumeGapLength(CSSParserTokenRange& range, CSSParserMode cssParserMode)
 {
     if (range.peek().id() == CSSValueNormal)
         return consumeIdent(range);
-    return consumeLength(range, cssParserMode, ValueRangeNonNegative);
+    return consumeLengthOrPercent(range, cssParserMode, ValueRangeNonNegative);
 }
 
 static RefPtr<CSSValue> consumeColumnSpan(CSSParserTokenRange& range)
@@ -4035,7 +4035,7 @@ RefPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSPropertyID property, CSS
     case CSSPropertyColumnCount:
         return consumeColumnCount(m_range);
     case CSSPropertyColumnGap:
-        return consumeColumnGap(m_range, m_context.mode);
+        return consumeGapLength(m_range, m_context.mode);
     case CSSPropertyColumnSpan:
         return consumeColumnSpan(m_range);
     case CSSPropertyZoom:
index 9af164b..b6a7026 100644 (file)
@@ -720,7 +720,8 @@ void FrameView::applyPaginationToViewport()
     EOverflow overflowY = documentOrBodyRenderer->style().overflowY();
     if (overflowY == OPAGEDX || overflowY == OPAGEDY) {
         pagination.mode = WebCore::paginationModeForRenderStyle(documentOrBodyRenderer->style());
-        pagination.gap = static_cast<unsigned>(documentOrBodyRenderer->style().columnGap());
+        GapLength columnGapLength = documentOrBodyRenderer->style().columnGap();
+        pagination.gap = columnGapLength.isNormal() ? 0 : valueForLength(columnGapLength.length(), downcast<RenderBox>(documentOrBodyRenderer)->availableLogicalWidth()).toUnsigned();
     }
     setPagination(pagination);
 }
index ea12189..33b841c 100644 (file)
@@ -44,6 +44,7 @@
 #include "FloatConversion.h"
 #include "FontSelectionAlgorithm.h"
 #include "FontTaggedSettings.h"
+#include "GapLength.h"
 #include "IdentityTransformOperation.h"
 #include "Logging.h"
 #include "Matrix3DTransformOperation.h"
@@ -90,6 +91,11 @@ static inline Length blendFunc(const CSSPropertyBlendingClient*, const Length& f
     return blend(from, to, progress);
 }
 
+static inline GapLength blendFunc(const CSSPropertyBlendingClient*, const GapLength& from, const GapLength& to, double progress)
+{
+    return (from.isNormal() || to.isNormal()) ? to : blend(from.length(), to.length(), progress);
+}
+
 static inline LengthSize blendFunc(const CSSPropertyBlendingClient* anim, const LengthSize& from, const LengthSize& to, double progress)
 {
     return { blendFunc(anim, from.width, to.width, progress), blendFunc(anim, from.height, to.height, progress) };
@@ -1519,7 +1525,7 @@ CSSPropertyAnimationWrapperMap::CSSPropertyAnimationWrapperMap()
 
         new PropertyWrapper<float>(CSSPropertyFontSize, &RenderStyle::computedFontSize, &RenderStyle::setFontSize),
         new PropertyWrapper<unsigned short>(CSSPropertyColumnRuleWidth, &RenderStyle::columnRuleWidth, &RenderStyle::setColumnRuleWidth),
-        new PropertyWrapper<float>(CSSPropertyColumnGap, &RenderStyle::columnGap, &RenderStyle::setColumnGap),
+        new LengthPropertyWrapper<GapLength>(CSSPropertyColumnGap, &RenderStyle::columnGap, &RenderStyle::setColumnGap),
         new PropertyWrapper<unsigned short>(CSSPropertyColumnCount, &RenderStyle::columnCount, &RenderStyle::setColumnCount),
         new PropertyWrapper<float>(CSSPropertyColumnWidth, &RenderStyle::columnWidth, &RenderStyle::setColumnWidth),
         new PropertyWrapper<float>(CSSPropertyWebkitBorderHorizontalSpacing, &RenderStyle::horizontalBorderSpacing, &RenderStyle::setHorizontalBorderSpacing),
index 07d81d0..a6e078a 100644 (file)
@@ -366,9 +366,9 @@ bool RenderBlockFlow::recomputeLogicalWidthAndColumnWidth()
 
 LayoutUnit RenderBlockFlow::columnGap() const
 {
-    if (style().hasNormalColumnGap())
+    if (style().columnGap().isNormal())
         return style().fontDescription().computedPixelSize(); // "1em" is recommended as the normal gap setting. Matches <p> margins.
-    return style().columnGap();
+    return valueForLength(style().columnGap().length(), availableLogicalWidth());
 }
 
 void RenderBlockFlow::computeColumnCountAndWidth()
index a82c1fa..ceb85f7 100644 (file)
@@ -429,9 +429,9 @@ LayoutUnit RenderMultiColumnSet::columnGap() const
     // FIXME: Eventually we will cache the column gap when the widths of columns start varying, but for now we just
     // go to the parent block to get the gap.
     RenderBlockFlow& parentBlock = downcast<RenderBlockFlow>(*parent());
-    if (parentBlock.style().hasNormalColumnGap())
+    if (parentBlock.style().columnGap().isNormal())
         return parentBlock.style().fontDescription().computedPixelSize(); // "1em" is recommended as the normal gap setting. Matches <p> margins.
-    return parentBlock.style().columnGap();
+    return valueForLength(parentBlock.style().columnGap().length(), parentBlock.availableLogicalWidth());
 }
 
 unsigned RenderMultiColumnSet::columnCount() const
diff --git a/Source/WebCore/rendering/style/GapLength.cpp b/Source/WebCore/rendering/style/GapLength.cpp
new file mode 100644 (file)
index 0000000..28683dd
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER OR 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 "GapLength.h"
+
+#include <wtf/text/TextStream.h>
+
+namespace WebCore {
+
+TextStream& operator<<(TextStream& ts, const GapLength& gapLength)
+{
+    if (gapLength.isNormal())
+        ts << "normal";
+    else
+        ts << gapLength.length();
+    return ts;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/style/GapLength.h b/Source/WebCore/rendering/style/GapLength.h
new file mode 100644 (file)
index 0000000..3e10b05
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER OR 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
+
+#include "Length.h"
+
+namespace WTF {
+class TextStream;
+}
+
+namespace WebCore {
+
+// This class wraps the lenght of a gap used by properties column-gap and row-gap.
+// The valid values are "normal" or a non-negative <length-percentage>.
+class GapLength {
+public:
+    GapLength()
+        : m_isNormal(true)
+    {
+    }
+
+    GapLength(const Length& length)
+        : m_isNormal(false)
+        , m_length(length)
+    {
+    }
+
+    bool isNormal() const { return m_isNormal; }
+    const Length& length() const { ASSERT(!m_isNormal); return m_length; }
+
+    bool operator==(const GapLength& o) const
+    {
+        return m_isNormal == o.m_isNormal && m_length == o.m_length;
+    }
+
+private:
+    bool m_isNormal;
+    Length m_length;
+};
+
+WTF::TextStream& operator<<(WTF::TextStream&, const GapLength&);
+
+} // namespace WebCore
index 1396d3f..9479e8a 100644 (file)
@@ -34,6 +34,7 @@
 #include "DataRef.h"
 #include "FilterOperations.h"
 #include "FontDescription.h"
+#include "GapLength.h"
 #include "GraphicsTypes.h"
 #include "Length.h"
 #include "LengthBox.h"
@@ -604,8 +605,7 @@ public:
     bool hasAutoColumnCount() const { return m_rareNonInheritedData->multiCol->autoCount; }
     bool specifiesColumns() const { return !hasAutoColumnCount() || !hasAutoColumnWidth() || !hasInlineColumnAxis(); }
     ColumnFill columnFill() const { return static_cast<ColumnFill>(m_rareNonInheritedData->multiCol->fill); }
-    float columnGap() const { return m_rareNonInheritedData->multiCol->gap; }
-    bool hasNormalColumnGap() const { return m_rareNonInheritedData->multiCol->normalGap; }
+    const GapLength& columnGap() const { return m_rareNonInheritedData->multiCol->columnGap; }
     EBorderStyle columnRuleStyle() const { return m_rareNonInheritedData->multiCol->rule.style(); }
     unsigned short columnRuleWidth() const { return m_rareNonInheritedData->multiCol->ruleWidth(); }
     bool columnRuleIsTransparent() const { return m_rareNonInheritedData->multiCol->rule.isTransparent(); }
@@ -1129,8 +1129,7 @@ public:
     void setColumnCount(unsigned short c) { SET_NESTED_VAR(m_rareNonInheritedData, multiCol, autoCount, false); SET_NESTED_VAR(m_rareNonInheritedData, multiCol, count, c); }
     void setHasAutoColumnCount() { SET_NESTED_VAR(m_rareNonInheritedData, multiCol, autoCount, true); SET_NESTED_VAR(m_rareNonInheritedData, multiCol, count, 0); }
     void setColumnFill(ColumnFill columnFill) { SET_NESTED_VAR(m_rareNonInheritedData, multiCol, fill, columnFill); }
-    void setColumnGap(float f) { SET_NESTED_VAR(m_rareNonInheritedData, multiCol, normalGap, false); SET_NESTED_VAR(m_rareNonInheritedData, multiCol, gap, f); }
-    void setHasNormalColumnGap() { SET_NESTED_VAR(m_rareNonInheritedData, multiCol, normalGap, true); SET_NESTED_VAR(m_rareNonInheritedData, multiCol, gap, 0); }
+    void setColumnGap(GapLength&& gapLength) { SET_NESTED_VAR(m_rareNonInheritedData, multiCol, columnGap, WTFMove(gapLength)); }
     void setColumnRuleColor(const Color& c) { SET_BORDERVALUE_COLOR(m_rareNonInheritedData.access().multiCol, rule, c); }
     void setColumnRuleStyle(EBorderStyle b) { SET_NESTED_VAR(m_rareNonInheritedData, multiCol, rule.m_style, b); }
     void setColumnRuleWidth(unsigned short w) { SET_NESTED_VAR(m_rareNonInheritedData, multiCol, rule.m_width, w); }
@@ -1533,6 +1532,7 @@ public:
     static unsigned short initialColumnCount() { return 1; }
     static ColumnFill initialColumnFill() { return ColumnFillBalance; }
     static ColumnSpan initialColumnSpan() { return ColumnSpanNone; }
+    static GapLength initialColumnGap() { return GapLength(); }
     static const TransformOperations& initialTransform() { static NeverDestroyed<TransformOperations> ops; return ops; }
     static Length initialTransformOriginX() { return Length(50.0f, Percent); }
     static Length initialTransformOriginY() { return Length(50.0f, Percent); }
index b7e794f..4dc2791 100644 (file)
@@ -30,7 +30,6 @@ StyleMultiColData::StyleMultiColData()
     : count(RenderStyle::initialColumnCount())
     , autoWidth(true)
     , autoCount(true)
-    , normalGap(true)
     , fill(RenderStyle::initialColumnFill())
     , columnSpan(false)
     , axis(RenderStyle::initialColumnAxis())
@@ -42,12 +41,11 @@ inline StyleMultiColData::StyleMultiColData(const StyleMultiColData& other)
     : RefCounted<StyleMultiColData>()
     , width(other.width)
     , count(other.count)
-    , gap(other.gap)
+    , columnGap(other.columnGap)
     , rule(other.rule)
     , visitedLinkColumnRuleColor(other.visitedLinkColumnRuleColor)
     , autoWidth(other.autoWidth)
     , autoCount(other.autoCount)
-    , normalGap(other.normalGap)
     , fill(other.fill)
     , columnSpan(other.columnSpan)
     , axis(other.axis)
@@ -62,9 +60,9 @@ Ref<StyleMultiColData> StyleMultiColData::copy() const
 
 bool StyleMultiColData::operator==(const StyleMultiColData& other) const
 {
-    return width == other.width && count == other.count && gap == other.gap
+    return width == other.width && count == other.count && columnGap == other.columnGap
         && rule == other.rule && visitedLinkColumnRuleColor == other.visitedLinkColumnRuleColor
-        && autoWidth == other.autoWidth && autoCount == other.autoCount && normalGap == other.normalGap
+        && autoWidth == other.autoWidth && autoCount == other.autoCount
         && fill == other.fill && columnSpan == other.columnSpan
         && axis == other.axis && progression == other.progression;
 }
index f92d23c..a6de1ef 100644 (file)
@@ -25,6 +25,7 @@
 #pragma once
 
 #include "BorderValue.h"
+#include "GapLength.h"
 #include "RenderStyleConstants.h"
 #include <wtf/RefCounted.h>
 
@@ -49,13 +50,12 @@ public:
 
     float width { 0 };
     unsigned short count;
-    float gap { 0 };
+    GapLength columnGap;
     BorderValue rule;
     Color visitedLinkColumnRuleColor;
 
     bool autoWidth : 1;
     bool autoCount : 1;
-    bool normalGap : 1;
     unsigned fill : 1; // ColumnFill
     unsigned columnSpan : 1;
     unsigned axis : 2; // ColumnAxis
index b6e7204..40132cf 100644 (file)
@@ -94,7 +94,7 @@ RenderStyle resolveForDocument(const Document& document)
     const Pagination& pagination = renderView.frameView().pagination();
     if (pagination.mode != Pagination::Unpaginated) {
         documentStyle.setColumnStylesFromPaginationMode(pagination.mode);
-        documentStyle.setColumnGap(pagination.gap);
+        documentStyle.setColumnGap(GapLength(Length((int) pagination.gap, Fixed)));
         if (renderView.multiColumnFlow())
             renderView.updateColumnProgressionFromStyle(documentStyle);
         if (renderView.page().paginationLineGridEnabled()) {