Diff
Modified: trunk/Source/WebCore/ChangeLog (226167 => 226168)
--- trunk/Source/WebCore/ChangeLog 2017-12-20 01:44:07 UTC (rev 226167)
+++ trunk/Source/WebCore/ChangeLog 2017-12-20 01:44:37 UTC (rev 226168)
@@ -1,3 +1,42 @@
+2017-12-19 Antti Koivisto <[email protected]>
+
+ Move first-letter building code to RenderTreeBuilder
+ https://bugs.webkit.org/show_bug.cgi?id=180992
+
+ Reviewed by Zalan Bujtas.
+
+ All special case tree building logic should go to RenderTreeBuilder.
+
+ - RenderTreeUpdater::FirstLetter -> RenderTreeBuilder::FirstLetter
+ - Make the builder non-static and stop using RenderTreeBuilder::current() there.
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * rendering/TextAutoSizing.cpp:
+ (WebCore::TextAutoSizingValue::adjustTextNodeSizes):
+ * rendering/updating/RenderTreeBuilder.cpp:
+ (WebCore::RenderTreeBuilder::RenderTreeBuilder):
+ (WebCore::RenderTreeBuilder::insertChild):
+ (WebCore::RenderTreeBuilder::updateAfterDescendants):
+ * rendering/updating/RenderTreeBuilder.h:
+ (WebCore::RenderTreeBuilder::firstLetterBuilder):
+ (WebCore::RenderTreeBuilder::tableBuilder):
+ * rendering/updating/RenderTreeBuilderFirstLetter.cpp: Copied from rendering/updating/RenderTreeUpdaterFirstLetter.cpp.
+ (WebCore::supportsFirstLetter):
+ (WebCore::RenderTreeBuilder::FirstLetter::FirstLetter):
+ (WebCore::RenderTreeBuilder::FirstLetter::updateAfterDescendants):
+ (WebCore::RenderTreeBuilder::FirstLetter::updateStyle):
+ (WebCore::RenderTreeBuilder::FirstLetter::createRenderers):
+ (WebCore::updateFirstLetterStyle): Deleted.
+ (WebCore::createFirstLetterRenderer): Deleted.
+ (WebCore::RenderTreeUpdater::FirstLetter::update): Deleted.
+ * rendering/updating/RenderTreeBuilderFirstLetter.h: Copied from rendering/updating/RenderTreeUpdaterFirstLetter.h.
+ * rendering/updating/RenderTreeUpdater.cpp:
+ (WebCore::RenderTreeUpdater::updateAfterDescendants):
+ * rendering/updating/RenderTreeUpdater.h:
+ * rendering/updating/RenderTreeUpdaterFirstLetter.cpp: Removed.
+ * rendering/updating/RenderTreeUpdaterFirstLetter.h: Removed.
+
2017-12-19 Chris Dumez <[email protected]>
[Fetch] Extracting a body of type Blob should not set Content-Type to the empty string
Modified: trunk/Source/WebCore/Sources.txt (226167 => 226168)
--- trunk/Source/WebCore/Sources.txt 2017-12-20 01:44:07 UTC (rev 226167)
+++ trunk/Source/WebCore/Sources.txt 2017-12-20 01:44:37 UTC (rev 226168)
@@ -1980,10 +1980,10 @@
rendering/svg/SVGTextQuery.cpp
rendering/updating/RenderTreeBuilder.cpp
+rendering/updating/RenderTreeBuilderFirstLetter.cpp
rendering/updating/RenderTreeBuilderTable.cpp
rendering/updating/RenderTreePosition.cpp
rendering/updating/RenderTreeUpdater.cpp
-rendering/updating/RenderTreeUpdaterFirstLetter.cpp
rendering/updating/RenderTreeUpdaterGeneratedContent.cpp
rendering/updating/RenderTreeUpdaterListItem.cpp
rendering/updating/RenderTreeUpdaterMultiColumn.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (226167 => 226168)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-12-20 01:44:07 UTC (rev 226167)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-12-20 01:44:37 UTC (rev 226168)
@@ -4579,7 +4579,7 @@
E47C392D1FE6E0F300BBBC6B /* RenderTreeBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = E47C392A1FE6E0DE00BBBC6B /* RenderTreeBuilder.h */; };
E47C392E1FE6E0F700BBBC6B /* RenderTreePosition.h in Headers */ = {isa = PBXBuildFile; fileRef = E47C39241FE6E0DB00BBBC6B /* RenderTreePosition.h */; };
E47C392F1FE6E0F900BBBC6B /* RenderTreeUpdater.h in Headers */ = {isa = PBXBuildFile; fileRef = E47C392C1FE6E0DF00BBBC6B /* RenderTreeUpdater.h */; };
- E47C39301FE6E0FD00BBBC6B /* RenderTreeUpdaterFirstLetter.h in Headers */ = {isa = PBXBuildFile; fileRef = E47C39261FE6E0DC00BBBC6B /* RenderTreeUpdaterFirstLetter.h */; };
+ E47C39301FE6E0FD00BBBC6B /* RenderTreeBuilderFirstLetter.h in Headers */ = {isa = PBXBuildFile; fileRef = E47C39261FE6E0DC00BBBC6B /* RenderTreeBuilderFirstLetter.h */; };
E47C39311FE6E10200BBBC6B /* RenderTreeUpdaterGeneratedContent.h in Headers */ = {isa = PBXBuildFile; fileRef = E47C39251FE6E0DB00BBBC6B /* RenderTreeUpdaterGeneratedContent.h */; };
E47C39321FE6E10500BBBC6B /* RenderTreeUpdaterListItem.h in Headers */ = {isa = PBXBuildFile; fileRef = E47C39281FE6E0DD00BBBC6B /* RenderTreeUpdaterListItem.h */; };
E47C39331FE6E10800BBBC6B /* RenderTreeUpdaterMultiColumn.h in Headers */ = {isa = PBXBuildFile; fileRef = E47C39271FE6E0DC00BBBC6B /* RenderTreeUpdaterMultiColumn.h */; };
@@ -13908,12 +13908,12 @@
E47B4BE70E71241600038854 /* CachedResourceHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CachedResourceHandle.cpp; sourceTree = "<group>"; };
E47C391F1FE6E0D800BBBC6B /* RenderTreeUpdater.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeUpdater.cpp; sourceTree = "<group>"; };
E47C39201FE6E0D900BBBC6B /* RenderTreeBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeBuilder.cpp; sourceTree = "<group>"; };
- E47C39211FE6E0DA00BBBC6B /* RenderTreeUpdaterFirstLetter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeUpdaterFirstLetter.cpp; sourceTree = "<group>"; };
+ E47C39211FE6E0DA00BBBC6B /* RenderTreeBuilderFirstLetter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeBuilderFirstLetter.cpp; sourceTree = "<group>"; };
E47C39221FE6E0DA00BBBC6B /* RenderTreeUpdaterGeneratedContent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeUpdaterGeneratedContent.cpp; sourceTree = "<group>"; };
E47C39231FE6E0DA00BBBC6B /* RenderTreeUpdaterMultiColumn.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeUpdaterMultiColumn.cpp; sourceTree = "<group>"; };
E47C39241FE6E0DB00BBBC6B /* RenderTreePosition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderTreePosition.h; sourceTree = "<group>"; };
E47C39251FE6E0DB00BBBC6B /* RenderTreeUpdaterGeneratedContent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderTreeUpdaterGeneratedContent.h; sourceTree = "<group>"; };
- E47C39261FE6E0DC00BBBC6B /* RenderTreeUpdaterFirstLetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderTreeUpdaterFirstLetter.h; sourceTree = "<group>"; };
+ E47C39261FE6E0DC00BBBC6B /* RenderTreeBuilderFirstLetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderTreeBuilderFirstLetter.h; sourceTree = "<group>"; };
E47C39271FE6E0DC00BBBC6B /* RenderTreeUpdaterMultiColumn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderTreeUpdaterMultiColumn.h; sourceTree = "<group>"; };
E47C39281FE6E0DD00BBBC6B /* RenderTreeUpdaterListItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderTreeUpdaterListItem.h; sourceTree = "<group>"; };
E47C39291FE6E0DE00BBBC6B /* RenderTreePosition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreePosition.cpp; sourceTree = "<group>"; };
@@ -24516,6 +24516,8 @@
children = (
E47C39201FE6E0D900BBBC6B /* RenderTreeBuilder.cpp */,
E47C392A1FE6E0DE00BBBC6B /* RenderTreeBuilder.h */,
+ E47C39211FE6E0DA00BBBC6B /* RenderTreeBuilderFirstLetter.cpp */,
+ E47C39261FE6E0DC00BBBC6B /* RenderTreeBuilderFirstLetter.h */,
119340761FE8B92300935F1E /* RenderTreeBuilderTable.cpp */,
119340771FE8B92300935F1E /* RenderTreeBuilderTable.h */,
E47C39291FE6E0DE00BBBC6B /* RenderTreePosition.cpp */,
@@ -24522,8 +24524,6 @@
E47C39241FE6E0DB00BBBC6B /* RenderTreePosition.h */,
E47C391F1FE6E0D800BBBC6B /* RenderTreeUpdater.cpp */,
E47C392C1FE6E0DF00BBBC6B /* RenderTreeUpdater.h */,
- E47C39211FE6E0DA00BBBC6B /* RenderTreeUpdaterFirstLetter.cpp */,
- E47C39261FE6E0DC00BBBC6B /* RenderTreeUpdaterFirstLetter.h */,
E47C39221FE6E0DA00BBBC6B /* RenderTreeUpdaterGeneratedContent.cpp */,
E47C39251FE6E0DB00BBBC6B /* RenderTreeUpdaterGeneratedContent.h */,
E47C392B1FE6E0DF00BBBC6B /* RenderTreeUpdaterListItem.cpp */,
@@ -27242,6 +27242,7 @@
977B3878122883E900B81FF8 /* HTMLTokenizer.h in Headers */,
0707568C142262D600414161 /* HTMLTrackElement.h in Headers */,
977B37261228721700B81FF8 /* HTMLTreeBuilder.h in Headers */,
+ E47C39301FE6E0FD00BBBC6B /* RenderTreeBuilderFirstLetter.h in Headers */,
A8EA79F20A1916DF00A8EF5F /* HTMLUListElement.h in Headers */,
AD49914318F0815100BF0092 /* HTMLUnknownElement.h in Headers */,
E44613AB0CD6331000FADA75 /* HTMLVideoElement.h in Headers */,
@@ -28932,7 +28933,6 @@
119340791FE8B92300935F1E /* RenderTreeBuilderTable.h in Headers */,
E47C392E1FE6E0F700BBBC6B /* RenderTreePosition.h in Headers */,
E47C392F1FE6E0F900BBBC6B /* RenderTreeUpdater.h in Headers */,
- E47C39301FE6E0FD00BBBC6B /* RenderTreeUpdaterFirstLetter.h in Headers */,
E47C39311FE6E10200BBBC6B /* RenderTreeUpdaterGeneratedContent.h in Headers */,
E47C39321FE6E10500BBBC6B /* RenderTreeUpdaterListItem.h in Headers */,
E47C39331FE6E10800BBBC6B /* RenderTreeUpdaterMultiColumn.h in Headers */,
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj.orig (226167 => 226168)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj.orig 2017-12-20 01:44:07 UTC (rev 226167)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj.orig 2017-12-20 01:44:37 UTC (rev 226168)
@@ -169,6 +169,7 @@
078E094417D16E1C00420AA1 /* RTCSessionDescriptionRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 07221BAD17CF0AD400848E51 /* RTCSessionDescriptionRequest.h */; settings = {ATTRIBUTES = (Private, ); }; };
078E094717D16E1C00420AA1 /* RTCVoidRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 07221BB017CF0AD400848E51 /* RTCVoidRequest.h */; settings = {ATTRIBUTES = (Private, ); }; };
078E094C17D1709600420AA1 /* MediaStreamAudioDestinationNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 078E094917D1709600420AA1 /* MediaStreamAudioDestinationNode.h */; };
+ 078E3CC01FE1C73C00483C1D /* MediaStreamRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 078E3CBE1FE19F3000483C1D /* MediaStreamRequest.h */; settings = {ATTRIBUTES = (Private, ); }; };
078E43DA1ABB6C7E001C2FA6 /* MediaPlaybackTargetPicker.h in Headers */ = {isa = PBXBuildFile; fileRef = 078E43D81ABB6C7E001C2FA6 /* MediaPlaybackTargetPicker.h */; settings = {ATTRIBUTES = (Private, ); }; };
078E43DD1ABB6F6F001C2FA6 /* MediaPlaybackTargetPickerMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 078E43DB1ABB6F6F001C2FA6 /* MediaPlaybackTargetPickerMac.h */; settings = {ATTRIBUTES = (Private, ); }; };
078E43DE1ABB6F6F001C2FA6 /* MediaPlaybackTargetPickerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 078E43DC1ABB6F6F001C2FA6 /* MediaPlaybackTargetPickerMac.mm */; };
@@ -5174,6 +5175,7 @@
078E094817D1709600420AA1 /* MediaStreamAudioDestinationNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaStreamAudioDestinationNode.cpp; sourceTree = "<group>"; };
078E094917D1709600420AA1 /* MediaStreamAudioDestinationNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaStreamAudioDestinationNode.h; sourceTree = "<group>"; };
078E094A17D1709600420AA1 /* MediaStreamAudioDestinationNode.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MediaStreamAudioDestinationNode.idl; sourceTree = "<group>"; };
+ 078E3CBE1FE19F3000483C1D /* MediaStreamRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaStreamRequest.h; sourceTree = "<group>"; };
078E43D71ABB6C7E001C2FA6 /* MediaPlaybackTargetPicker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaPlaybackTargetPicker.cpp; sourceTree = "<group>"; };
078E43D81ABB6C7E001C2FA6 /* MediaPlaybackTargetPicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaPlaybackTargetPicker.h; sourceTree = "<group>"; };
078E43DB1ABB6F6F001C2FA6 /* MediaPlaybackTargetPickerMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaPlaybackTargetPickerMac.h; sourceTree = "<group>"; };
@@ -14717,6 +14719,7 @@
070F549717F12F6B00169E04 /* MediaStreamConstraintsValidationClient.h */,
0711588F17DF633700EDFE2B /* MediaStreamPrivate.cpp */,
07221B9D17CF0AD400848E51 /* MediaStreamPrivate.h */,
+ 078E3CBE1FE19F3000483C1D /* MediaStreamRequest.h */,
07FFDE66181AED420072D409 /* MediaStreamTrackPrivate.cpp */,
07FFDE67181AED420072D409 /* MediaStreamTrackPrivate.h */,
5EBB89381C77BDA400C65D41 /* PeerMediaDescription.h */,
@@ -26928,6 +26931,7 @@
517A535B1F588A4C00DCDC0A /* FetchBodyConsumer.h in Headers */,
4129C9971F59B963009D7403 /* FetchBodySource.h in Headers */,
41D129DB1F3D143800D15E47 /* FetchHeaders.h in Headers */,
+ 4161E2D51FE48DC500EC2E96 /* FetchLoader.h in Headers */,
517A53581F5889E800DCDC0A /* FetchLoaderClient.h in Headers */,
41AD753A1CEF6BD100A31486 /* FetchOptions.h in Headers */,
7CE1914D1F2A9AFB00272F78 /* FetchReferrerPolicy.h in Headers */,
@@ -27389,7 +27393,6 @@
7A54858014E02D51006AE05A /* InspectorHistory.h in Headers */,
A5B81CAE1FAA44620037D1E6 /* InspectorIndexedDBAgent.h in Headers */,
20D629271253690B00081543 /* InspectorInstrumentation.h in Headers */,
- 4161E2D51FE48DC500EC2E96 /* FetchLoader.h in Headers */,
A5840E1D187B74D500843B10 /* InspectorInstrumentationCookie.h in Headers */,
A5B81CAF1FAA44620037D1E6 /* InspectorLayerTreeAgent.h in Headers */,
A5B81CB01FAA44620037D1E6 /* InspectorMemoryAgent.h in Headers */,
@@ -28420,6 +28423,7 @@
078E091617D14D1C00420AA1 /* MediaStreamEvent.h in Headers */,
078E093717D16B2C00420AA1 /* MediaStreamPrivate.h in Headers */,
078E091717D14D1C00420AA1 /* MediaStreamRegistry.h in Headers */,
+ 078E3CC01FE1C73C00483C1D /* MediaStreamRequest.h in Headers */,
078E091817D14D1C00420AA1 /* MediaStreamTrack.h in Headers */,
078E091917D14D1C00420AA1 /* MediaStreamTrackEvent.h in Headers */,
07FFDE69181AED420072D409 /* MediaStreamTrackPrivate.h in Headers */,
Modified: trunk/Source/WebCore/rendering/TextAutoSizing.cpp (226167 => 226168)
--- trunk/Source/WebCore/rendering/TextAutoSizing.cpp 2017-12-20 01:44:07 UTC (rev 226167)
+++ trunk/Source/WebCore/rendering/TextAutoSizing.cpp 2017-12-20 01:44:37 UTC (rev 226168)
@@ -37,7 +37,7 @@
#include "RenderText.h"
#include "RenderTextFragment.h"
#include "RenderTreeBuilder.h"
-#include "RenderTreeUpdaterFirstLetter.h"
+#include "RenderTreeBuilderFirstLetter.h"
#include "RenderTreeUpdaterListItem.h"
#include "StyleResolver.h"
@@ -173,8 +173,7 @@
auto* block = downcast<RenderTextFragment>(textRenderer).blockForAccompanyingFirstLetter();
if (!block)
continue;
- // FIXME: All render tree mutations should be done by RenderTreeUpdater commit.
- RenderTreeUpdater::FirstLetter::update(*block);
+ builder.updateAfterDescendants(*block);
}
return stillHasNodes;
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp (226167 => 226168)
--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp 2017-12-20 01:44:07 UTC (rev 226167)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp 2017-12-20 01:44:37 UTC (rev 226168)
@@ -32,8 +32,8 @@
#include "RenderRubyRun.h"
#include "RenderTableRow.h"
#include "RenderText.h"
+#include "RenderTreeBuilderFirstLetter.h"
#include "RenderTreeBuilderTable.h"
-#include "RenderTreeUpdater.h"
namespace WebCore {
@@ -41,6 +41,7 @@
RenderTreeBuilder::RenderTreeBuilder(RenderView& view)
: m_view(view)
+ , m_firstLetterBuilder(std::make_unique<FirstLetter>(*this))
, m_tableBuilder(std::make_unique<Table>(*this))
{
RELEASE_ASSERT(!s_current || &m_view != &s_current->m_view);
@@ -63,12 +64,12 @@
}
if (is<RenderTableRow>(parent)) {
- m_tableBuilder->findOrCreateParentForChild(downcast<RenderTableRow>(parent), *child, beforeChild).addChild(*this, WTFMove(child), beforeChild);
+ tableBuilder().findOrCreateParentForChild(downcast<RenderTableRow>(parent), *child, beforeChild).addChild(*this, WTFMove(child), beforeChild);
return;
}
if (is<RenderTableSection>(parent)) {
- auto& parentCandidate = m_tableBuilder->findOrCreateParentForChild(downcast<RenderTableSection>(parent), *child, beforeChild);
+ auto& parentCandidate = tableBuilder().findOrCreateParentForChild(downcast<RenderTableSection>(parent), *child, beforeChild);
if (&parent != &parentCandidate) {
insertChild(parentCandidate, WTFMove(child), beforeChild);
return;
@@ -90,6 +91,12 @@
insertChild(position.parent(), WTFMove(child), position.nextSibling());
}
+void RenderTreeBuilder::updateAfterDescendants(RenderElement& renderer)
+{
+ if (is<RenderBlock>(renderer))
+ firstLetterBuilder().updateAfterDescendants(downcast<RenderBlock>(renderer));
+}
+
void RenderTreeBuilder::rubyRunInsertChild(RenderRubyRun& parent, RenderPtr<RenderObject> child, RenderObject* beforeChild)
{
if (child->isRubyText()) {
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.h (226167 => 226168)
--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.h 2017-12-20 01:44:07 UTC (rev 226167)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.h 2017-12-20 01:44:37 UTC (rev 226168)
@@ -40,20 +40,28 @@
void insertChild(RenderElement& parent, RenderPtr<RenderObject>, RenderObject* beforeChild = nullptr);
void insertChild(RenderTreePosition&, RenderPtr<RenderObject>);
+ void updateAfterDescendants(RenderElement&);
+
// This avoids having to convert all sites that need RenderTreeBuilder in one go.
// FIXME: Remove.
static RenderTreeBuilder* current() { return s_current; }
private:
+ class FirstLetter;
class Table;
void rubyRunInsertChild(RenderRubyRun&, RenderPtr<RenderObject> child, RenderObject* beforeChild);
+ FirstLetter& firstLetterBuilder() { return *m_firstLetterBuilder; }
+ Table& tableBuilder() { return *m_tableBuilder; }
+
RenderView& m_view;
RenderTreeBuilder* m_previous { nullptr };
+ static RenderTreeBuilder* s_current;
+
+ std::unique_ptr<FirstLetter> m_firstLetterBuilder;
std::unique_ptr<Table> m_tableBuilder;
- static RenderTreeBuilder* s_current;
};
}
Copied: trunk/Source/WebCore/rendering/updating/RenderTreeBuilderFirstLetter.cpp (from rev 226165, trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterFirstLetter.cpp) (0 => 226168)
--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilderFirstLetter.cpp (rev 0)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilderFirstLetter.cpp 2017-12-20 01:44:37 UTC (rev 226168)
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 1999 Lars Knoll ([email protected])
+ * (C) 1999 Antti Koivisto ([email protected])
+ * (C) 2007 David Smith ([email protected])
+ * Copyright (C) 2003-2011, 2017 Apple Inc. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "RenderTreeBuilderFirstLetter.h"
+
+#include "FontCascade.h"
+#include "RenderBlock.h"
+#include "RenderButton.h"
+#include "RenderInline.h"
+#include "RenderRubyRun.h"
+#include "RenderSVGText.h"
+#include "RenderStyle.h"
+#include "RenderTable.h"
+#include "RenderTextFragment.h"
+#include "RenderTreeBuilder.h"
+
+namespace WebCore {
+
+static RenderStyle styleForFirstLetter(const RenderBlock& firstLetterBlock, const RenderObject& firstLetterContainer)
+{
+ auto* containerFirstLetterStyle = firstLetterBlock.getCachedPseudoStyle(FIRST_LETTER, &firstLetterContainer.firstLineStyle());
+ // FIXME: There appears to be some path where we have a first letter renderer without first letter style.
+ ASSERT(containerFirstLetterStyle);
+ auto firstLetterStyle = RenderStyle::clone(containerFirstLetterStyle ? *containerFirstLetterStyle : firstLetterContainer.firstLineStyle());
+
+ // If we have an initial letter drop that is >= 1, then we need to force floating to be on.
+ if (firstLetterStyle.initialLetterDrop() >= 1 && !firstLetterStyle.isFloating())
+ firstLetterStyle.setFloating(firstLetterStyle.isLeftToRightDirection() ? LeftFloat : RightFloat);
+
+ // We have to compute the correct font-size for the first-letter if it has an initial letter height set.
+ auto* paragraph = firstLetterContainer.isRenderBlockFlow() ? &firstLetterContainer : firstLetterContainer.containingBlock();
+ if (firstLetterStyle.initialLetterHeight() >= 1 && firstLetterStyle.fontMetrics().hasCapHeight() && paragraph->style().fontMetrics().hasCapHeight()) {
+ // FIXME: For ideographic baselines, we want to go from line edge to line edge. This is equivalent to (N-1)*line-height + the font height.
+ // We don't yet support ideographic baselines.
+ // For an N-line first-letter and for alphabetic baselines, the cap-height of the first letter needs to equal (N-1)*line-height of paragraph lines + cap-height of the paragraph
+ // Mathematically we can't rely on font-size, since font().height() doesn't necessarily match. For reliability, the best approach is simply to
+ // compare the final measured cap-heights of the two fonts in order to get to the closest possible value.
+ firstLetterStyle.setLineBoxContain(LineBoxContainInitialLetter);
+ int lineHeight = paragraph->style().computedLineHeight();
+
+ // Set the font to be one line too big and then ratchet back to get to a precise fit. We can't just set the desired font size based off font height metrics
+ // because many fonts bake ascent into the font metrics. Therefore we have to look at actual measured cap height values in order to know when we have a good fit.
+ auto newFontDescription = firstLetterStyle.fontDescription();
+ float capRatio = firstLetterStyle.fontMetrics().floatCapHeight() / firstLetterStyle.computedFontPixelSize();
+ float startingFontSize = ((firstLetterStyle.initialLetterHeight() - 1) * lineHeight + paragraph->style().fontMetrics().capHeight()) / capRatio;
+ newFontDescription.setSpecifiedSize(startingFontSize);
+ newFontDescription.setComputedSize(startingFontSize);
+ firstLetterStyle.setFontDescription(newFontDescription);
+ firstLetterStyle.fontCascade().update(firstLetterStyle.fontCascade().fontSelector());
+
+ int desiredCapHeight = (firstLetterStyle.initialLetterHeight() - 1) * lineHeight + paragraph->style().fontMetrics().capHeight();
+ int actualCapHeight = firstLetterStyle.fontMetrics().capHeight();
+ while (actualCapHeight > desiredCapHeight) {
+ auto newFontDescription = firstLetterStyle.fontDescription();
+ newFontDescription.setSpecifiedSize(newFontDescription.specifiedSize() - 1);
+ newFontDescription.setComputedSize(newFontDescription.computedSize() -1);
+ firstLetterStyle.setFontDescription(newFontDescription);
+ firstLetterStyle.fontCascade().update(firstLetterStyle.fontCascade().fontSelector());
+ actualCapHeight = firstLetterStyle.fontMetrics().capHeight();
+ }
+ }
+
+ // Force inline display (except for floating first-letters).
+ firstLetterStyle.setDisplay(firstLetterStyle.isFloating() ? BLOCK : INLINE);
+ // CSS2 says first-letter can't be positioned.
+ firstLetterStyle.setPosition(StaticPosition);
+ return firstLetterStyle;
+}
+
+// CSS 2.1 http://www.w3.org/TR/CSS21/selector.html#first-letter
+// "Punctuation (i.e, characters defined in Unicode [UNICODE] in the "open" (Ps), "close" (Pe),
+// "initial" (Pi). "final" (Pf) and "other" (Po) punctuation classes), that precedes or follows the first letter should be included"
+static inline bool isPunctuationForFirstLetter(UChar c)
+{
+ return U_GET_GC_MASK(c) & (U_GC_PS_MASK | U_GC_PE_MASK | U_GC_PI_MASK | U_GC_PF_MASK | U_GC_PO_MASK);
+}
+
+static inline bool shouldSkipForFirstLetter(UChar c)
+{
+ return isSpaceOrNewline(c) || c == noBreakSpace || isPunctuationForFirstLetter(c);
+}
+
+static bool supportsFirstLetter(RenderBlock& block)
+{
+ if (is<RenderButton>(block))
+ return true;
+ if (!is<RenderBlockFlow>(block))
+ return false;
+ if (is<RenderSVGText>(block))
+ return false;
+ if (is<RenderRubyRun>(block))
+ return false;
+ return block.canHaveGeneratedChildren();
+}
+
+RenderTreeBuilder::FirstLetter::FirstLetter(RenderTreeBuilder& builder)
+ : m_builder(builder)
+{
+}
+
+void RenderTreeBuilder::FirstLetter::updateAfterDescendants(RenderBlock& block)
+{
+ if (!block.style().hasPseudoStyle(FIRST_LETTER))
+ return;
+ if (!supportsFirstLetter(block))
+ return;
+
+ // FIXME: This should be refactored, firstLetterContainer is not needed.
+ RenderObject* firstLetterRenderer;
+ RenderElement* firstLetterContainer;
+ block.getFirstLetter(firstLetterRenderer, firstLetterContainer);
+
+ if (!firstLetterRenderer)
+ return;
+
+ // Other containers are handled when updating their renderers.
+ if (&block != firstLetterContainer)
+ return;
+
+ // If the child already has style, then it has already been created, so we just want
+ // to update it.
+ if (firstLetterRenderer->parent()->style().styleType() == FIRST_LETTER) {
+ updateStyle(block, *firstLetterRenderer);
+ return;
+ }
+
+ if (!is<RenderText>(firstLetterRenderer))
+ return;
+
+ createRenderers(block, downcast<RenderText>(*firstLetterRenderer));
+}
+
+void RenderTreeBuilder::FirstLetter::updateStyle(RenderBlock& firstLetterBlock, RenderObject& currentChild)
+{
+ RenderElement* firstLetter = currentChild.parent();
+ ASSERT(firstLetter->isFirstLetter());
+
+ RenderElement* firstLetterContainer = firstLetter->parent();
+ auto pseudoStyle = styleForFirstLetter(firstLetterBlock, *firstLetterContainer);
+ ASSERT(firstLetter->isFloating() || firstLetter->isInline());
+
+ if (Style::determineChange(firstLetter->style(), pseudoStyle) == Style::Detach) {
+ // The first-letter renderer needs to be replaced. Create a new renderer of the right type.
+ RenderPtr<RenderBoxModelObject> newFirstLetter;
+ if (pseudoStyle.display() == INLINE)
+ newFirstLetter = createRenderer<RenderInline>(firstLetterBlock.document(), WTFMove(pseudoStyle));
+ else
+ newFirstLetter = createRenderer<RenderBlockFlow>(firstLetterBlock.document(), WTFMove(pseudoStyle));
+ newFirstLetter->initializeStyle();
+ newFirstLetter->setIsFirstLetter();
+
+ // Move the first letter into the new renderer.
+ while (RenderObject* child = firstLetter->firstChild()) {
+ if (is<RenderText>(*child))
+ downcast<RenderText>(*child).removeAndDestroyTextBoxes();
+ auto toMove = firstLetter->takeChild(*child);
+ m_builder.insertChild(*newFirstLetter, WTFMove(toMove));
+ }
+
+ RenderObject* nextSibling = firstLetter->nextSibling();
+ if (RenderTextFragment* remainingText = downcast<RenderBoxModelObject>(*firstLetter).firstLetterRemainingText()) {
+ ASSERT(remainingText->isAnonymous() || remainingText->textNode()->renderer() == remainingText);
+ // Replace the old renderer with the new one.
+ remainingText->setFirstLetter(*newFirstLetter);
+ newFirstLetter->setFirstLetterRemainingText(*remainingText);
+ }
+ firstLetterContainer->removeAndDestroyChild(*firstLetter);
+ m_builder.insertChild(*firstLetterContainer, WTFMove(newFirstLetter), nextSibling);
+ return;
+ }
+
+ firstLetter->setStyle(WTFMove(pseudoStyle));
+}
+
+void RenderTreeBuilder::FirstLetter::createRenderers(RenderBlock& firstLetterBlock, RenderText& currentTextChild)
+{
+ RenderElement* firstLetterContainer = currentTextChild.parent();
+ auto pseudoStyle = styleForFirstLetter(firstLetterBlock, *firstLetterContainer);
+ RenderPtr<RenderBoxModelObject> newFirstLetter;
+ if (pseudoStyle.display() == INLINE)
+ newFirstLetter = createRenderer<RenderInline>(firstLetterBlock.document(), WTFMove(pseudoStyle));
+ else
+ newFirstLetter = createRenderer<RenderBlockFlow>(firstLetterBlock.document(), WTFMove(pseudoStyle));
+ newFirstLetter->initializeStyle();
+ newFirstLetter->setIsFirstLetter();
+
+ auto& firstLetter = *newFirstLetter;
+ m_builder.insertChild(*firstLetterContainer, WTFMove(newFirstLetter), ¤tTextChild);
+
+ // The original string is going to be either a generated content string or a DOM node's
+ // string. We want the original string before it got transformed in case first-letter has
+ // no text-transform or a different text-transform applied to it.
+ String oldText = currentTextChild.originalText();
+ ASSERT(!oldText.isNull());
+
+ if (!oldText.isEmpty()) {
+ unsigned length = 0;
+
+ // Account for leading spaces and punctuation.
+ while (length < oldText.length() && shouldSkipForFirstLetter(oldText[length]))
+ length++;
+
+ // Account for first grapheme cluster.
+ length += numCharactersInGraphemeClusters(StringView(oldText).substring(length), 1);
+
+ // Keep looking for whitespace and allowed punctuation, but avoid
+ // accumulating just whitespace into the :first-letter.
+ for (unsigned scanLength = length; scanLength < oldText.length(); ++scanLength) {
+ UChar c = oldText[scanLength];
+
+ if (!shouldSkipForFirstLetter(c))
+ break;
+
+ if (isPunctuationForFirstLetter(c))
+ length = scanLength + 1;
+ }
+
+ auto* textNode = currentTextChild.textNode();
+ auto* beforeChild = currentTextChild.nextSibling();
+ firstLetterContainer->removeAndDestroyChild(currentTextChild);
+
+ // Construct a text fragment for the text after the first letter.
+ // This text fragment might be empty.
+ RenderPtr<RenderTextFragment> newRemainingText;
+ if (textNode) {
+ newRemainingText = createRenderer<RenderTextFragment>(*textNode, oldText, length, oldText.length() - length);
+ textNode->setRenderer(newRemainingText.get());
+ } else
+ newRemainingText = createRenderer<RenderTextFragment>(firstLetterBlock.document(), oldText, length, oldText.length() - length);
+
+ RenderTextFragment& remainingText = *newRemainingText;
+ m_builder.insertChild(*firstLetterContainer, WTFMove(newRemainingText), beforeChild);
+ remainingText.setFirstLetter(firstLetter);
+ firstLetter.setFirstLetterRemainingText(remainingText);
+
+ // construct text fragment for the first letter
+ auto letter = createRenderer<RenderTextFragment>(firstLetterBlock.document(), oldText, 0, length);
+
+ m_builder.insertChild(firstLetter, WTFMove(letter));
+ }
+}
+
+};
Copied: trunk/Source/WebCore/rendering/updating/RenderTreeBuilderFirstLetter.h (from rev 226165, trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterFirstLetter.h) (0 => 226168)
--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilderFirstLetter.h (rev 0)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilderFirstLetter.h 2017-12-20 01:44:37 UTC (rev 226168)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 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
+
+#include "RenderTreeBuilder.h"
+
+namespace WebCore {
+
+class RenderElement;
+
+class RenderTreeBuilder::FirstLetter {
+public:
+ FirstLetter(RenderTreeBuilder&);
+
+ void updateAfterDescendants(RenderBlock&);
+
+private:
+ void updateStyle(RenderBlock& firstLetterBlock, RenderObject& currentChild);
+ void createRenderers(RenderBlock& firstLetterBlock, RenderText& currentTextChild);
+
+ RenderTreeBuilder& m_builder;
+};
+
+}
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp (226167 => 226168)
--- trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp 2017-12-20 01:44:07 UTC (rev 226167)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp 2017-12-20 01:44:37 UTC (rev 226168)
@@ -41,7 +41,7 @@
#include "RenderFullScreen.h"
#include "RenderInline.h"
#include "RenderListItem.h"
-#include "RenderTreeUpdaterFirstLetter.h"
+#include "RenderTreeBuilderFirstLetter.h"
#include "RenderTreeUpdaterGeneratedContent.h"
#include "RenderTreeUpdaterListItem.h"
#include "RenderTreeUpdaterMultiColumn.h"
@@ -271,9 +271,9 @@
if (!renderer)
return;
+ m_builder.updateAfterDescendants(*renderer);
+
// These functions do render tree mutations that require descendant renderers.
- if (is<RenderBlock>(*renderer))
- FirstLetter::update(downcast<RenderBlock>(*renderer));
if (is<RenderListItem>(*renderer))
ListItem::updateMarker(m_builder, downcast<RenderListItem>(*renderer));
if (is<RenderBlockFlow>(*renderer))
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.h (226167 => 226168)
--- trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.h 2017-12-20 01:44:07 UTC (rev 226167)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.h 2017-12-20 01:44:37 UTC (rev 226168)
@@ -51,7 +51,6 @@
static void tearDownRenderers(Element&);
static void tearDownRenderer(Text&);
- class FirstLetter;
class ListItem;
private:
Deleted: trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterFirstLetter.cpp (226167 => 226168)
--- trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterFirstLetter.cpp 2017-12-20 01:44:07 UTC (rev 226167)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterFirstLetter.cpp 2017-12-20 01:44:37 UTC (rev 226168)
@@ -1,257 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll ([email protected])
- * (C) 1999 Antti Koivisto ([email protected])
- * (C) 2007 David Smith ([email protected])
- * Copyright (C) 2003-2011, 2017 Apple Inc. All rights reserved.
- * Copyright (C) Research In Motion Limited 2010. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "RenderTreeUpdaterFirstLetter.h"
-
-#include "FontCascade.h"
-#include "RenderBlock.h"
-#include "RenderButton.h"
-#include "RenderInline.h"
-#include "RenderRubyRun.h"
-#include "RenderSVGText.h"
-#include "RenderStyle.h"
-#include "RenderTable.h"
-#include "RenderTextFragment.h"
-#include "RenderTreeBuilder.h"
-
-namespace WebCore {
-
-static RenderStyle styleForFirstLetter(const RenderBlock& firstLetterBlock, const RenderObject& firstLetterContainer)
-{
- auto* containerFirstLetterStyle = firstLetterBlock.getCachedPseudoStyle(FIRST_LETTER, &firstLetterContainer.firstLineStyle());
- // FIXME: There appears to be some path where we have a first letter renderer without first letter style.
- ASSERT(containerFirstLetterStyle);
- auto firstLetterStyle = RenderStyle::clone(containerFirstLetterStyle ? *containerFirstLetterStyle : firstLetterContainer.firstLineStyle());
-
- // If we have an initial letter drop that is >= 1, then we need to force floating to be on.
- if (firstLetterStyle.initialLetterDrop() >= 1 && !firstLetterStyle.isFloating())
- firstLetterStyle.setFloating(firstLetterStyle.isLeftToRightDirection() ? LeftFloat : RightFloat);
-
- // We have to compute the correct font-size for the first-letter if it has an initial letter height set.
- auto* paragraph = firstLetterContainer.isRenderBlockFlow() ? &firstLetterContainer : firstLetterContainer.containingBlock();
- if (firstLetterStyle.initialLetterHeight() >= 1 && firstLetterStyle.fontMetrics().hasCapHeight() && paragraph->style().fontMetrics().hasCapHeight()) {
- // FIXME: For ideographic baselines, we want to go from line edge to line edge. This is equivalent to (N-1)*line-height + the font height.
- // We don't yet support ideographic baselines.
- // For an N-line first-letter and for alphabetic baselines, the cap-height of the first letter needs to equal (N-1)*line-height of paragraph lines + cap-height of the paragraph
- // Mathematically we can't rely on font-size, since font().height() doesn't necessarily match. For reliability, the best approach is simply to
- // compare the final measured cap-heights of the two fonts in order to get to the closest possible value.
- firstLetterStyle.setLineBoxContain(LineBoxContainInitialLetter);
- int lineHeight = paragraph->style().computedLineHeight();
-
- // Set the font to be one line too big and then ratchet back to get to a precise fit. We can't just set the desired font size based off font height metrics
- // because many fonts bake ascent into the font metrics. Therefore we have to look at actual measured cap height values in order to know when we have a good fit.
- auto newFontDescription = firstLetterStyle.fontDescription();
- float capRatio = firstLetterStyle.fontMetrics().floatCapHeight() / firstLetterStyle.computedFontPixelSize();
- float startingFontSize = ((firstLetterStyle.initialLetterHeight() - 1) * lineHeight + paragraph->style().fontMetrics().capHeight()) / capRatio;
- newFontDescription.setSpecifiedSize(startingFontSize);
- newFontDescription.setComputedSize(startingFontSize);
- firstLetterStyle.setFontDescription(newFontDescription);
- firstLetterStyle.fontCascade().update(firstLetterStyle.fontCascade().fontSelector());
-
- int desiredCapHeight = (firstLetterStyle.initialLetterHeight() - 1) * lineHeight + paragraph->style().fontMetrics().capHeight();
- int actualCapHeight = firstLetterStyle.fontMetrics().capHeight();
- while (actualCapHeight > desiredCapHeight) {
- auto newFontDescription = firstLetterStyle.fontDescription();
- newFontDescription.setSpecifiedSize(newFontDescription.specifiedSize() - 1);
- newFontDescription.setComputedSize(newFontDescription.computedSize() -1);
- firstLetterStyle.setFontDescription(newFontDescription);
- firstLetterStyle.fontCascade().update(firstLetterStyle.fontCascade().fontSelector());
- actualCapHeight = firstLetterStyle.fontMetrics().capHeight();
- }
- }
-
- // Force inline display (except for floating first-letters).
- firstLetterStyle.setDisplay(firstLetterStyle.isFloating() ? BLOCK : INLINE);
- // CSS2 says first-letter can't be positioned.
- firstLetterStyle.setPosition(StaticPosition);
- return firstLetterStyle;
-}
-
-// CSS 2.1 http://www.w3.org/TR/CSS21/selector.html#first-letter
-// "Punctuation (i.e, characters defined in Unicode [UNICODE] in the "open" (Ps), "close" (Pe),
-// "initial" (Pi). "final" (Pf) and "other" (Po) punctuation classes), that precedes or follows the first letter should be included"
-static inline bool isPunctuationForFirstLetter(UChar c)
-{
- return U_GET_GC_MASK(c) & (U_GC_PS_MASK | U_GC_PE_MASK | U_GC_PI_MASK | U_GC_PF_MASK | U_GC_PO_MASK);
-}
-
-static inline bool shouldSkipForFirstLetter(UChar c)
-{
- return isSpaceOrNewline(c) || c == noBreakSpace || isPunctuationForFirstLetter(c);
-}
-
-static void updateFirstLetterStyle(RenderBlock& firstLetterBlock, RenderObject& currentChild)
-{
- RenderElement* firstLetter = currentChild.parent();
- ASSERT(firstLetter->isFirstLetter());
-
- RenderElement* firstLetterContainer = firstLetter->parent();
- auto pseudoStyle = styleForFirstLetter(firstLetterBlock, *firstLetterContainer);
- ASSERT(firstLetter->isFloating() || firstLetter->isInline());
-
- if (Style::determineChange(firstLetter->style(), pseudoStyle) == Style::Detach) {
- // The first-letter renderer needs to be replaced. Create a new renderer of the right type.
- RenderPtr<RenderBoxModelObject> newFirstLetter;
- if (pseudoStyle.display() == INLINE)
- newFirstLetter = createRenderer<RenderInline>(firstLetterBlock.document(), WTFMove(pseudoStyle));
- else
- newFirstLetter = createRenderer<RenderBlockFlow>(firstLetterBlock.document(), WTFMove(pseudoStyle));
- newFirstLetter->initializeStyle();
- newFirstLetter->setIsFirstLetter();
-
- // Move the first letter into the new renderer.
- while (RenderObject* child = firstLetter->firstChild()) {
- if (is<RenderText>(*child))
- downcast<RenderText>(*child).removeAndDestroyTextBoxes();
- auto toMove = firstLetter->takeChild(*child);
- RenderTreeBuilder::current()->insertChild(*newFirstLetter, WTFMove(toMove));
- }
-
- RenderObject* nextSibling = firstLetter->nextSibling();
- if (RenderTextFragment* remainingText = downcast<RenderBoxModelObject>(*firstLetter).firstLetterRemainingText()) {
- ASSERT(remainingText->isAnonymous() || remainingText->textNode()->renderer() == remainingText);
- // Replace the old renderer with the new one.
- remainingText->setFirstLetter(*newFirstLetter);
- newFirstLetter->setFirstLetterRemainingText(*remainingText);
- }
- firstLetterContainer->removeAndDestroyChild(*firstLetter);
- RenderTreeBuilder::current()->insertChild(*firstLetterContainer, WTFMove(newFirstLetter), nextSibling);
- } else
- firstLetter->setStyle(WTFMove(pseudoStyle));
-}
-
-static void createFirstLetterRenderer(RenderBlock& firstLetterBlock, RenderText& currentTextChild)
-{
- RenderElement* firstLetterContainer = currentTextChild.parent();
- auto pseudoStyle = styleForFirstLetter(firstLetterBlock, *firstLetterContainer);
- RenderPtr<RenderBoxModelObject> newFirstLetter;
- if (pseudoStyle.display() == INLINE)
- newFirstLetter = createRenderer<RenderInline>(firstLetterBlock.document(), WTFMove(pseudoStyle));
- else
- newFirstLetter = createRenderer<RenderBlockFlow>(firstLetterBlock.document(), WTFMove(pseudoStyle));
- newFirstLetter->initializeStyle();
- newFirstLetter->setIsFirstLetter();
-
- auto& firstLetter = *newFirstLetter;
- RenderTreeBuilder::current()->insertChild(*firstLetterContainer, WTFMove(newFirstLetter), ¤tTextChild);
-
- // The original string is going to be either a generated content string or a DOM node's
- // string. We want the original string before it got transformed in case first-letter has
- // no text-transform or a different text-transform applied to it.
- String oldText = currentTextChild.originalText();
- ASSERT(!oldText.isNull());
-
- if (!oldText.isEmpty()) {
- unsigned length = 0;
-
- // Account for leading spaces and punctuation.
- while (length < oldText.length() && shouldSkipForFirstLetter(oldText[length]))
- length++;
-
- // Account for first grapheme cluster.
- length += numCharactersInGraphemeClusters(StringView(oldText).substring(length), 1);
-
- // Keep looking for whitespace and allowed punctuation, but avoid
- // accumulating just whitespace into the :first-letter.
- for (unsigned scanLength = length; scanLength < oldText.length(); ++scanLength) {
- UChar c = oldText[scanLength];
-
- if (!shouldSkipForFirstLetter(c))
- break;
-
- if (isPunctuationForFirstLetter(c))
- length = scanLength + 1;
- }
-
- auto* textNode = currentTextChild.textNode();
- auto* beforeChild = currentTextChild.nextSibling();
- firstLetterContainer->removeAndDestroyChild(currentTextChild);
-
- // Construct a text fragment for the text after the first letter.
- // This text fragment might be empty.
- RenderPtr<RenderTextFragment> newRemainingText;
- if (textNode) {
- newRemainingText = createRenderer<RenderTextFragment>(*textNode, oldText, length, oldText.length() - length);
- textNode->setRenderer(newRemainingText.get());
- } else
- newRemainingText = createRenderer<RenderTextFragment>(firstLetterBlock.document(), oldText, length, oldText.length() - length);
-
- RenderTextFragment& remainingText = *newRemainingText;
- RenderTreeBuilder::current()->insertChild(*firstLetterContainer, WTFMove(newRemainingText), beforeChild);
- remainingText.setFirstLetter(firstLetter);
- firstLetter.setFirstLetterRemainingText(remainingText);
-
- // construct text fragment for the first letter
- auto letter = createRenderer<RenderTextFragment>(firstLetterBlock.document(), oldText, 0, length);
-
- RenderTreeBuilder::current()->insertChild(firstLetter, WTFMove(letter));
- }
-}
-
-static bool supportsFirstLetter(RenderBlock& block)
-{
- if (is<RenderButton>(block))
- return true;
- if (!is<RenderBlockFlow>(block))
- return false;
- if (is<RenderSVGText>(block))
- return false;
- if (is<RenderRubyRun>(block))
- return false;
- return block.canHaveGeneratedChildren();
-}
-
-void RenderTreeUpdater::FirstLetter::update(RenderBlock& block)
-{
- if (!block.style().hasPseudoStyle(FIRST_LETTER))
- return;
- if (!supportsFirstLetter(block))
- return;
-
- // FIXME: This should be refactored, firstLetterContainer is not needed.
- RenderObject* firstLetterRenderer;
- RenderElement* firstLetterContainer;
- block.getFirstLetter(firstLetterRenderer, firstLetterContainer);
-
- if (!firstLetterRenderer)
- return;
-
- // Other containers are handled when updating their renderers.
- if (&block != firstLetterContainer)
- return;
-
- // If the child already has style, then it has already been created, so we just want
- // to update it.
- if (firstLetterRenderer->parent()->style().styleType() == FIRST_LETTER) {
- updateFirstLetterStyle(block, *firstLetterRenderer);
- return;
- }
-
- if (!is<RenderText>(firstLetterRenderer))
- return;
-
- createFirstLetterRenderer(block, downcast<RenderText>(*firstLetterRenderer));
-}
-
-};
Deleted: trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterFirstLetter.h (226167 => 226168)
--- trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterFirstLetter.h 2017-12-20 01:44:07 UTC (rev 226167)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeUpdaterFirstLetter.h 2017-12-20 01:44:37 UTC (rev 226168)
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2017 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
-
-#include "RenderTreeUpdater.h"
-
-namespace WebCore {
-
-class RenderBlock;
-
-class RenderTreeUpdater::FirstLetter {
-public:
- static void update(RenderBlock&);
-};
-
-}