Source/WebCore/ChangeLog

 12022-04-25 Nikolas Zimmermann <nzimmermann@igalia.com>
 2
 3 [LBSE] Activate text rendering, by re-using RenderSVGText
 4 https://bugs.webkit.org/show_bug.cgi?id=239743
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Adapt RenderSVGText to be usable at the same time from legacy SVG engine (as
 9 it is right now) and from LBSE. This requires minimal effort, since RenderSVGText
 10 already inherited from RenderLayerModelObject, so there's no need for the creation
 11 of LegacyRenderSVGText / RenderSVGText as separated legacy/LBSE implementations.
 12
 13 Most SVG 1.1 <text> testcases already pass out of the box with this change.
 14 The next patch after text support will add a new 'macos-wk2-lbse-xxx' specific
 15 platform baseline, so that we can run tests LBSE againt iself (finally we can
 16 include the progressions in the form of TestExpectation file changes, once a certain
 17 patch implements a new feature in LBSE. This makes sense now as enough is upstreamed
 18 that a considerable amount of the SVG 1.1 testsuite already passes pixel perfect.
 19
 20 Covered by existing tests, no change in behaviour. (However testability for LBSE is ready soon!).
 21
 22 * rendering/RenderLayerModelObject.cpp:
 23 (WebCore::RenderLayerModelObject::computeVisibleRectInSVGContainer const):
 24 * rendering/RenderObject.cpp:
 25 (WebCore::objectIsRelayoutBoundary):
 26 * rendering/svg/RenderSVGBlock.cpp:
 27 (WebCore::RenderSVGBlock::updateFromStyle):
 28 (WebCore::RenderSVGBlock::absoluteRects const):
 29 (WebCore::RenderSVGBlock::absoluteQuads const):
 30 (WebCore::RenderSVGBlock::styleDidChange):
 31 (WebCore::RenderSVGBlock::computeOverflow):
 32 (WebCore::RenderSVGBlock::clippedOverflowRect const):
 33 (WebCore::RenderSVGBlock::computeVisibleRectInContainer const):
 34 (WebCore::RenderSVGBlock::computeFloatVisibleRectInContainer const):
 35 (WebCore::RenderSVGBlock::pushMappingToContainer const):
 36 (WebCore::RenderSVGBlock::offsetFromContainer const):
 37 (WebCore::RenderSVGBlock::nodeAtPoint): Deleted.
 38 * rendering/svg/RenderSVGBlock.h:
 39 * rendering/svg/RenderSVGText.cpp:
 40 (WebCore::RenderSVGText::RenderSVGText):
 41 (WebCore::RenderSVGText::layout):
 42 (WebCore::RenderSVGText::nodeAtFloatPoint):
 43 (WebCore::RenderSVGText::nodeAtPoint):
 44 (WebCore::RenderSVGText::paint):
 45 (WebCore::RenderSVGText::repaintRectInLocalCoordinates const):
 46 (WebCore::RenderSVGText::updatePositionAndOverflow):
 47 (WebCore::RenderSVGText::absoluteQuads const): Deleted.
 48 * rendering/svg/RenderSVGText.h:
 49 * rendering/svg/SVGRootInlineBox.cpp:
 50 (WebCore::SVGRootInlineBox::renderSVGText const):
 51 (WebCore::SVGRootInlineBox::paint):
 52 (WebCore::SVGRootInlineBox::layoutRootBox):
 53 (WebCore::SVGRootInlineBox::renderSVGText): Deleted.
 54 * rendering/svg/SVGRootInlineBox.h:
 55 * svg/SVGElement.cpp:
 56 (WebCore::createSVGLayerAwareElementSet):
 57
1582022-04-25 Nikolas Zimmermann <nzimmermann@igalia.com>
259
360 [LBSE] Fix origin of transformations in SVG

Source/WebCore/rendering/RenderLayerModelObject.cpp

2929#include "RenderLayerBacking.h"
3030#include "RenderLayerCompositor.h"
3131#include "RenderLayerScrollableArea.h"
 32#include "RenderSVGBlock.h"
3233#include "RenderSVGModelObject.h"
3334#include "RenderView.h"
3435#include "SVGGraphicsElement.h"

@@void RenderLayerModelObject::updateLayerTransform()
245246#if ENABLE(LAYER_BASED_SVG_ENGINE)
246247std::optional<LayoutRect> RenderLayerModelObject::computeVisibleRectInSVGContainer(const LayoutRect& rect, const RenderLayerModelObject* container, RenderObject::VisibleRectContext context) const
247248{
248  // FIXME: [LBSE] Upstream RenderSVGBlock changes
249  // ASSERT(is<RenderSVGModelObject>(this) || is<RenderSVGBlock>(this));
250  ASSERT(is<RenderSVGModelObject>(this));
251 
 249 ASSERT(is<RenderSVGModelObject>(this) || is<RenderSVGBlock>(this));
252250 ASSERT(!style().hasInFlowPosition());
253251 ASSERT(!view().frameView().layoutContext().isPaintOffsetCacheEnabled());
254252

Source/WebCore/rendering/RenderObject.cpp

@@static inline bool objectIsRelayoutBoundary(const RenderElement* object)
521521 if (!object->hasNonVisibleOverflow())
522522 return false;
523523
 524#if ENABLE(LAYER_BASED_SVG_ENGINE)
 525 if (object->document().settings().layerBasedSVGEngineEnabled() && object->isSVGLayerAwareRenderer())
 526 return false;
 527#endif
 528
524529 if (object->style().width().isIntrinsicOrAuto() || object->style().height().isIntrinsicOrAuto() || object->style().height().isPercentOrCalculated())
525530 return false;
526531

Source/WebCore/rendering/svg/RenderSVGBlock.cpp

2222#include "config.h"
2323#include "RenderSVGBlock.h"
2424
 25#include "RenderSVGBlockInlines.h"
2526#include "RenderSVGResource.h"
2627#include "SVGGraphicsElement.h"
2728#include "SVGRenderSupport.h"

@@void RenderSVGBlock::updateFromStyle()
4243{
4344 RenderBlockFlow::updateFromStyle();
4445
 46#if ENABLE(LAYER_BASED_SVG_ENGINE)
 47 if (document().settings().layerBasedSVGEngineEnabled()) {
 48 updateHasSVGTransformFlags(graphicsElement());
 49 return;
 50 }
 51#endif
 52
4553 // RenderSVGlock, used by Render(SVGText|ForeignObject), is not allowed to call setHasNonVisibleOverflow(true).
4654 // RenderBlock assumes a layer to be present when the overflow clip functionality is requested. Both
4755 // Render(SVGText|ForeignObject) return 'false' on 'requiresLayer'. Fine for RenderSVGText.

@@void RenderSVGBlock::updateFromStyle()
5765 setHasNonVisibleOverflow(false);
5866}
5967
60 void RenderSVGBlock::absoluteRects(Vector<IntRect>&, const LayoutPoint&) const
 68void RenderSVGBlock::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
6169{
 70#if ENABLE(LAYER_BASED_SVG_ENGINE)
 71 if (document().settings().layerBasedSVGEngineEnabled()) {
 72 rects.append(snappedIntRect(LayoutRect(accumulatedOffset + location(), size())));
 73 return;
 74 }
 75#endif
 76
6277 // This code path should never be taken for SVG, as we're assuming useTransforms=true everywhere, absoluteQuads should be used.
6378 ASSERT_NOT_REACHED();
6479}
6580
 81void RenderSVGBlock::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
 82{
 83 quads.append(localToAbsoluteQuad(strokeBoundingBox(), UseTransforms, wasFixed));
 84}
 85
6686void RenderSVGBlock::willBeDestroyed()
6787{
6888 SVGResourcesCache::clientDestroyed(*this);

@@void RenderSVGBlock::willBeDestroyed()
7191
7292void RenderSVGBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
7393{
 94#if ENABLE(LAYER_BASED_SVG_ENGINE)
 95 if (diff == StyleDifference::Layout && !document().settings().layerBasedSVGEngineEnabled())
 96#else
7497 if (diff == StyleDifference::Layout)
 98#endif
7599 setNeedsBoundariesUpdate();
76100 RenderBlockFlow::styleDidChange(diff, oldStyle);
77101 SVGResourcesCache::clientStyleChanged(*this, diff, style());

@@void RenderSVGBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool recompu
81105{
82106 RenderBlockFlow::computeOverflow(oldClientAfterEdge, recomputeFloats);
83107
 108#if ENABLE(LAYER_BASED_SVG_ENGINE)
 109 if (document().settings().layerBasedSVGEngineEnabled())
 110 return;
 111#endif
 112
84113 const auto* textShadow = style().textShadow();
85114 if (!textShadow)
86115 return;

@@void RenderSVGBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool recompu
90119 addVisualOverflow(snappedIntRect(borderRect));
91120}
92121
93 LayoutRect RenderSVGBlock::clippedOverflowRect(const RenderLayerModelObject* repaintContainer, VisibleRectContext) const
 122LayoutRect RenderSVGBlock::clippedOverflowRect(const RenderLayerModelObject* repaintContainer, VisibleRectContext context) const
94123{
 124#if ENABLE(LAYER_BASED_SVG_ENGINE)
 125 if (document().settings().layerBasedSVGEngineEnabled()) {
 126 if (style().visibility() != Visibility::Visible && !enclosingLayer()->hasVisibleContent())
 127 return { };
 128
 129 ASSERT(!view().frameView().layoutContext().isPaintOffsetCacheEnabled());
 130 return computeRect(visualOverflowRect(), repaintContainer, context);
 131 }
 132#endif
 133
95134 return SVGRenderSupport::clippedOverflowRectForRepaint(*this, repaintContainer);
96135}
97136
98137std::optional<LayoutRect> RenderSVGBlock::computeVisibleRectInContainer(const LayoutRect& rect, const RenderLayerModelObject* container, VisibleRectContext context) const
99138{
 139#if ENABLE(LAYER_BASED_SVG_ENGINE)
 140 if (document().settings().layerBasedSVGEngineEnabled())
 141 return computeVisibleRectInSVGContainer(rect, container, context);
 142#endif
 143
100144 std::optional<FloatRect> adjustedRect = computeFloatVisibleRectInContainer(rect, container, context);
101145 if (adjustedRect)
102146 return enclosingLayoutRect(*adjustedRect);

@@std::optional<LayoutRect> RenderSVGBlock::computeVisibleRectInContainer(const La
105149
106150std::optional<FloatRect> RenderSVGBlock::computeFloatVisibleRectInContainer(const FloatRect& rect, const RenderLayerModelObject* container, VisibleRectContext context) const
107151{
 152#if ENABLE(LAYER_BASED_SVG_ENGINE)
 153 ASSERT(!document().settings().layerBasedSVGEngineEnabled());
 154#endif
108155 return SVGRenderSupport::computeFloatVisibleRectInContainer(*this, rect, container, context);
109156}
110157

@@void RenderSVGBlock::mapLocalToContainer(const RenderLayerModelObject* ancestorC
115162
116163const RenderObject* RenderSVGBlock::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
117164{
 165#if ENABLE(LAYER_BASED_SVG_ENGINE)
 166 if (document().settings().layerBasedSVGEngineEnabled())
 167 return RenderBox::pushMappingToContainer(ancestorToStopAt, geometryMap);
 168#endif
 169
118170 return SVGRenderSupport::pushMappingToContainer(*this, ancestorToStopAt, geometryMap);
119171}
120172
121 bool RenderSVGBlock::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction)
 173#if ENABLE(LAYER_BASED_SVG_ENGINE)
 174LayoutSize RenderSVGBlock::offsetFromContainer(RenderElement& container, const LayoutPoint&, bool*) const
122175{
123  ASSERT_NOT_REACHED();
124  return false;
 176 ASSERT_UNUSED(container, &container == this->container());
 177 ASSERT(!isInFlowPositioned());
 178 ASSERT(!isAbsolutelyPositioned());
 179 ASSERT(!isInline());
 180 return LayoutSize();
125181}
 182#endif
126183
127184}

Source/WebCore/rendering/svg/RenderSVGBlock.h

@@private:
4545 bool isRenderSVGBlock() const final { return true; }
4646
4747 void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const override;
48 
 48 void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const override;
4949 void styleDidChange(StyleDifference, const RenderStyle* oldStyle) final;
5050
5151#if ENABLE(LAYER_BASED_SVG_ENGINE)

@@private:
5959
6060 void mapLocalToContainer(const RenderLayerModelObject* ancestorContainer, TransformState&, OptionSet<MapCoordinatesMode>, bool* wasFixed) const final;
6161 const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const final;
62 
63  bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) final;
 62#if ENABLE(LAYER_BASED_SVG_ENGINE)
 63 LayoutSize offsetFromContainer(RenderElement&, const LayoutPoint&, bool* offsetDependsOnPoint = nullptr) const override;
 64#endif
6465};
6566
6667} // namespace WebCore

Source/WebCore/rendering/svg/RenderSVGText.cpp

4040#include "RenderSVGInline.h"
4141#include "RenderSVGInlineText.h"
4242#include "RenderSVGResource.h"
 43#include "RenderSVGRoot.h"
4344#include "SVGElementTypeHelpers.h"
4445#include "SVGLengthList.h"
4546#include "SVGResourcesCache.h"

@@WTF_MAKE_ISO_ALLOCATED_IMPL(RenderSVGText);
5758
5859RenderSVGText::RenderSVGText(SVGTextElement& element, RenderStyle&& style)
5960 : RenderSVGBlock(element, WTFMove(style))
60  , m_needsReordering(false)
61  , m_needsPositioningValuesUpdate(false)
62  , m_needsTransformUpdate(true)
63  , m_needsTextMetricsUpdate(false)
6461{
6562}
6663

@@static inline void updateFontInAllDescendants(RenderObject* start, SVGTextLayout
311308
312309void RenderSVGText::layout()
313310{
 311 auto isLayerBasedSVGEngineEnabled = [&]() {
 312#if ENABLE(LAYER_BASED_SVG_ENGINE)
 313 return document().settings().layerBasedSVGEngineEnabled();
 314#endif
 315 return false;
 316 };
 317
314318 StackStats::LayoutCheckPoint layoutCheckPoint;
315319 ASSERT(needsLayout());
316  LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(*this));
 320 LayoutRepainter repainter(*this, isLayerBasedSVGEngineEnabled() ? checkForRepaintDuringLayout() : SVGRenderSupport::checkForSVGRepaintDuringLayout(*this));
 321
 322 // FIXME: [LBSE] Upstream SVGLengthContext changes
 323 // textElement().updateLengthContext();
317324
318325 bool updateCachedBoundariesInParents = false;
319  if (m_needsTransformUpdate) {
320  m_localTransform = textElement().animatedLocalTransform();
321  m_needsTransformUpdate = false;
322  updateCachedBoundariesInParents = true;
 326 if (!isLayerBasedSVGEngineEnabled()) {
 327 if (m_needsTransformUpdate) {
 328 m_localTransform = textElement().animatedLocalTransform();
 329 m_needsTransformUpdate = false;
 330 updateCachedBoundariesInParents = true;
 331 }
323332 }
324333
325334 if (!everHadLayout()) {

@@void RenderSVGText::layout()
347356 m_needsPositioningValuesUpdate = false;
348357 updateCachedBoundariesInParents = true;
349358 } else {
350  LegacyRenderSVGRoot* rootObj = SVGRenderSupport::findTreeRootObject(*this);
351  if (m_needsTextMetricsUpdate || (rootObj && rootObj->isLayoutSizeChanged())) {
 359 bool isLayoutSizeChanged = false;
 360 if (auto* legacyRootObject = lineageOfType<LegacyRenderSVGRoot>(*this).first())
 361 isLayoutSizeChanged = legacyRootObject->isLayoutSizeChanged();
 362#if ENABLE(LAYER_BASED_SVG_ENGINE)
 363 else if (auto* rootObject = lineageOfType<RenderSVGRoot>(*this).first())
 364 isLayoutSizeChanged = rootObject->isLayoutSizeChanged();
 365#endif
 366
 367 if (m_needsTextMetricsUpdate || isLayoutSizeChanged) {
352368 // If the root layout size changed (eg. window size changes) or the transform to the root
353369 // context has changed then recompute the on-screen font size.
354370 updateFontInAllDescendants(this, &m_layoutAttributesBuilder);

@@void RenderSVGText::layout()
365381 // Reduced version of RenderBlock::layoutBlock(), which only takes care of SVG text.
366382 // All if branches that could cause early exit in RenderBlocks layoutBlock() method are turned into assertions.
367383 ASSERT(!isInline());
368  ASSERT(!simplifiedLayout());
369384 ASSERT(!scrollsOverflow());
370385 ASSERT(!hasControlClip());
371386 ASSERT(!multiColumnFlow());
372387 ASSERT(!positionedObjects());
373  ASSERT(!m_overflow);
374388 ASSERT(!isAnonymousBlock());
 389 if (!isLayerBasedSVGEngineEnabled()) {
 390 ASSERT(!simplifiedLayout());
 391 ASSERT(!m_overflow);
 392 }
375393
376394 if (!firstChild())
377395 setChildrenInline(true);
378396
379397 // FIXME: We need to find a way to only layout the child boxes, if needed.
380398 FloatRect oldBoundaries = objectBoundingBox();
 399 bool layoutChanged = everHadLayout() && selfNeedsLayout();
381400 ASSERT(childrenInline());
382401 LayoutUnit repaintLogicalTop;
383402 LayoutUnit repaintLogicalBottom;
384403 rebuildFloatingObjectSetFromIntrudingFloats();
385404 layoutInlineChildren(true, repaintLogicalTop, repaintLogicalBottom);
386405
 406 // updatePositionAndOverflow() is called by SVGRootInlineBox, after forceLayoutInlineChildren() ran, before this point is reached.
387407 if (m_needsReordering)
388408 m_needsReordering = false;
389409
390  if (!updateCachedBoundariesInParents)
 410 if (isLayerBasedSVGEngineEnabled()) {
 411 updateLayerTransform();
 412 updateCachedBoundariesInParents = false; // No longer needed for LBSE.
 413 } else if (!updateCachedBoundariesInParents)
391414 updateCachedBoundariesInParents = oldBoundaries != objectBoundingBox();
392415
393416 // Invalidate all resources of this client if our layout changed.
394  if (everHadLayout() && selfNeedsLayout())
 417 if (layoutChanged)
395418 SVGResourcesCache::clientLayoutChanged(*this);
396419
397420 // If our bounds changed, notify the parents.

@@void RenderSVGText::layout()
404427
405428bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
406429{
 430#if ENABLE(LAYER_BASED_SVG_ENGINE)
 431 ASSERT(!document().settings().layerBasedSVGEngineEnabled());
 432#endif
407433 PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, request, style().effectivePointerEvents());
408434 bool isVisible = (style().visibility() == Visibility::Visible);
409435 if (isVisible || !hitRules.requireVisible) {

@@bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResul
412438 FloatPoint localPoint = valueOrDefault(localToParentTransform().inverse()).mapPoint(pointInParent);
413439
414440 if (!SVGRenderSupport::pointInClippingArea(*this, localPoint))
415  return false;
 441 return false;
416442
417443 SVGHitTestCycleDetectionScope hitTestScope(*this);
418444

@@bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResul
424450 return false;
425451}
426452
 453#if ENABLE(LAYER_BASED_SVG_ENGINE)
 454bool RenderSVGText::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
 455{
 456 ASSERT(document().settings().layerBasedSVGEngineEnabled());
 457 auto adjustedLocation = accumulatedOffset + location();
 458
 459 PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, request, style().pointerEvents());
 460 bool isVisible = (style().visibility() == Visibility::Visible);
 461 if (isVisible || !hitRules.requireVisible) {
 462 if ((hitRules.canHitStroke && (style().svgStyle().hasStroke() || !hitRules.requireStroke))
 463 || (hitRules.canHitFill && (style().svgStyle().hasFill() || !hitRules.requireFill))) {
 464 auto localPoint = locationInContainer.point();
 465 auto coordinateSystemOriginTranslation = nominalSVGLayoutLocation() - adjustedLocation;
 466 localPoint.move(coordinateSystemOriginTranslation);
 467
 468 if (!SVGRenderSupport::pointInClippingArea(*this, localPoint))
 469 return false;
 470
 471 SVGHitTestCycleDetectionScope hitTestScope(*this);
 472 return RenderBlock::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction);
 473 }
 474 }
 475
 476 return false;
 477}
 478#endif
 479
427480VisiblePosition RenderSVGText::positionForPoint(const LayoutPoint& pointInContents, const RenderFragmentContainer* fragment)
428481{
429482 LegacyRootInlineBox* rootBox = firstRootBox();

@@VisiblePosition RenderSVGText::positionForPoint(const LayoutPoint& pointInConten
440493 return closestBox->renderer().positionForPoint({ pointInContents.x(), LayoutUnit(closestBox->y()) }, fragment);
441494}
442495
443 void RenderSVGText::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
444 {
445  quads.append(localToAbsoluteQuad(strokeBoundingBox(), UseTransforms, wasFixed));
446 }
447 
448 void RenderSVGText::paint(PaintInfo& paintInfo, const LayoutPoint&)
 496void RenderSVGText::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
449497{
450498 if (paintInfo.context().paintingDisabled())
451499 return;
452500
453  if (paintInfo.phase != PaintPhase::Foreground && paintInfo.phase != PaintPhase::Selection)
454  return;
 501 if (paintInfo.phase != PaintPhase::ClippingMask && paintInfo.phase != PaintPhase::Mask && paintInfo.phase != PaintPhase::Foreground && paintInfo.phase != PaintPhase::Outline && paintInfo.phase != PaintPhase::SelfOutline)
 502 return;
 503
 504 if (!paintInfo.shouldPaintWithinRoot(*this))
 505 return;
 506
 507#if ENABLE(LAYER_BASED_SVG_ENGINE)
 508 if (document().settings().layerBasedSVGEngineEnabled()) {
 509 if (style().visibility() == Visibility::Hidden || style().display() == DisplayType::None)
 510 return;
 511
 512 // FIXME: [LBSE] Upstream SVGRenderSupport changes
 513 // if (!SVGRenderSupport::shouldPaintHiddenRenderer(*this))
 514 // return;
 515
 516 if (paintInfo.phase == PaintPhase::ClippingMask) {
 517 // FIXME: [LBSE] Upstream SVGRenderSupport changes
 518 // SVGRenderSupport::paintSVGClippingMask(*this, paintInfo);
 519 return;
 520 }
 521
 522 auto adjustedPaintOffset = paintOffset + location();
 523 if (paintInfo.phase == PaintPhase::Mask) {
 524 // FIXME: [LBSE] Upstream SVGRenderSupport changes
 525 // SVGRenderSupport::paintSVGMask(*this, paintInfo, adjustedPaintOffset);
 526 return;
 527 }
 528
 529 if (paintInfo.phase == PaintPhase::Outline || paintInfo.phase == PaintPhase::SelfOutline) {
 530 RenderBlock::paint(paintInfo, paintOffset);
 531 return;
 532 }
 533
 534 GraphicsContextStateSaver stateSaver(paintInfo.context());
 535
 536 auto coordinateSystemOriginTranslation = adjustedPaintOffset - nominalSVGLayoutLocation();
 537 paintInfo.context().translate(coordinateSystemOriginTranslation.width(), coordinateSystemOriginTranslation.height());
 538
 539 RenderBlock::paint(paintInfo, paintOffset);
 540 return;
 541 }
 542#endif
455543
456544 PaintInfo blockInfo(paintInfo);
457545 GraphicsContextStateSaver stateSaver(blockInfo.context());

@@FloatRect RenderSVGText::strokeBoundingBox() const
479567
480568FloatRect RenderSVGText::repaintRectInLocalCoordinates() const
481569{
 570#if ENABLE(LAYER_BASED_SVG_ENGINE)
 571 if (document().settings().layerBasedSVGEngineEnabled())
 572 return SVGBoundingBoxComputation::computeRepaintBoundingBox(*this);
 573#endif
 574
482575 FloatRect repaintRect = strokeBoundingBox();
483576 SVGRenderSupport::intersectRepaintRectWithResources(*this, repaintRect);
484577

@@FloatRect RenderSVGText::repaintRectInLocalCoordinates() const
488581 return repaintRect;
489582}
490583
 584void RenderSVGText::updatePositionAndOverflow(const FloatRect& boundaries)
 585{
 586#if ENABLE(LAYER_BASED_SVG_ENGINE)
 587 if (document().settings().layerBasedSVGEngineEnabled()) {
 588 clearOverflow();
 589
 590 m_objectBoundingBox = boundaries;
 591
 592 auto boundingRect = enclosingLayoutRect(m_objectBoundingBox);
 593 setLocation(boundingRect.location());
 594 setSize(boundingRect.size());
 595
 596 auto overflowRect = visualOverflowRectEquivalent();
 597 if (const auto* textShadow = style().textShadow())
 598 textShadow->adjustRectForShadow(overflowRect);
 599
 600 addVisualOverflow(overflowRect);
 601 return;
 602 }
 603#endif
 604
 605 auto boundingRect = enclosingLayoutRect(boundaries);
 606 setLocation(boundingRect.location());
 607 setSize(boundingRect.size());
 608 m_objectBoundingBox = boundingRect;
 609 ASSERT(m_objectBoundingBox == frameRect());
 610}
 611
491612}

Source/WebCore/rendering/svg/RenderSVGText.h

2323
2424#include "AffineTransform.h"
2525#include "RenderSVGBlock.h"
 26#include "SVGBoundingBoxComputation.h"
2627#include "SVGTextLayoutAttributesBuilder.h"
2728
2829namespace WebCore {

@@public:
4243 bool isChildAllowed(const RenderObject&, const RenderStyle&) const override;
4344
4445 void setNeedsPositioningValuesUpdate() { m_needsPositioningValuesUpdate = true; }
45  void setNeedsTransformUpdate() override { m_needsTransformUpdate = true; }
4646 void setNeedsTextMetricsUpdate() { m_needsTextMetricsUpdate = true; }
47  FloatRect repaintRectInLocalCoordinates() const override;
 47
 48 // FIXME: [LBSE] Only needed for legacy SVG engine.
 49 void setNeedsTransformUpdate() override { m_needsTransformUpdate = true; }
4850
4951 static RenderSVGText* locateRenderSVGTextAncestor(RenderObject&);
5052 static const RenderSVGText* locateRenderSVGTextAncestor(const RenderObject&);

@@public:
5860 void subtreeStyleDidChange(RenderSVGInlineText*);
5961 void subtreeTextDidChange(RenderSVGInlineText*);
6062
61  FloatRect objectBoundingBox() const override { return frameRect(); }
62  FloatRect strokeBoundingBox() const override;
 63 FloatRect objectBoundingBox() const final { return m_objectBoundingBox; }
 64 FloatRect strokeBoundingBox() const final;
 65 FloatRect repaintRectInLocalCoordinates() const final;
 66
 67#if ENABLE(LAYER_BASED_SVG_ENGINE)
 68 LayoutRect visualOverflowRectEquivalent() const { return SVGBoundingBoxComputation::computeVisualOverflowRect(*this); }
 69#endif
 70 void updatePositionAndOverflow(const FloatRect&);
6371
6472private:
6573 void graphicsElement() const = delete;

@@private:
6876 bool isSVGText() const override { return true; }
6977
7078 void paint(PaintInfo&, const LayoutPoint&) override;
71  bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) override;
 79 bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
7280 VisiblePosition positionForPoint(const LayoutPoint&, const RenderFragmentContainer*) override;
7381
74  bool requiresLayer() const override { return false; }
75  void layout() override;
 82 bool requiresLayer() const override
 83 {
 84#if ENABLE(LAYER_BASED_SVG_ENGINE)
 85 if (document().settings().layerBasedSVGEngineEnabled())
 86 return true;
 87#endif
 88 return false;
 89 }
7690
77  void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const override;
 91 void layout() override;
7892
7993 void willBeDestroyed() override;
8094
 95 // FIXME: [LBSE] Begin code only needed for legacy SVG engine.
 96 bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) override;
8197 const AffineTransform& localToParentTransform() const override { return m_localTransform; }
8298 AffineTransform localTransform() const override { return m_localTransform; }
 99 // FIXME: [LBSE] End code only needed for legacy SVG engine.
83100
84101 bool shouldHandleSubtreeMutations() const;
85102
86  bool m_needsReordering : 1;
87  bool m_needsPositioningValuesUpdate : 1;
88  bool m_needsTransformUpdate : 1;
89  bool m_needsTextMetricsUpdate : 1;
90  AffineTransform m_localTransform;
 103 bool m_needsReordering : 1 { false };
 104 bool m_needsPositioningValuesUpdate : 1 { false };
 105 bool m_needsTransformUpdate : 1 { true }; // FIXME: [LBSE] Only needed for legacy SVG engine.
 106 bool m_needsTextMetricsUpdate : 1 { false };
 107 AffineTransform m_localTransform; // FIXME: [LBSE] Only needed for legacy SVG engine.
91108 SVGTextLayoutAttributesBuilder m_layoutAttributesBuilder;
92109 Vector<SVGTextLayoutAttributes*> m_layoutAttributes;
 110 FloatRect m_objectBoundingBox;
93111};
94112
95113} // namespace WebCore

Source/WebCore/rendering/svg/SVGRootInlineBox.cpp

@@SVGRootInlineBox::SVGRootInlineBox(RenderSVGText& renderSVGText)
4646{
4747}
4848
49 RenderSVGText& SVGRootInlineBox::renderSVGText()
 49RenderSVGText& SVGRootInlineBox::renderSVGText() const
5050{
5151 return downcast<RenderSVGText>(blockFlow());
5252}
5353
54 void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit)
 54void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
5555{
5656 ASSERT(paintInfo.phase == PaintPhase::Foreground || paintInfo.phase == PaintPhase::Selection);
5757 ASSERT(!paintInfo.context().paintingDisabled());
5858
 59#if ENABLE(LAYER_BASED_SVG_ENGINE)
 60 if (renderer().document().settings().layerBasedSVGEngineEnabled()) {
 61 auto overflowRect(visualOverflowRect(lineTop, lineBottom));
 62 flipForWritingMode(overflowRect);
 63 overflowRect.moveBy(paintOffset);
 64
 65 if (!paintInfo.rect.intersects(overflowRect))
 66 return;
 67 }
 68#endif
 69
5970 bool isPrinting = renderSVGText().document().printing();
6071 bool hasSelection = !isPrinting && selectionState() != RenderObject::HighlightState::None;
6172 bool shouldPaintSelectionHighlight = !(paintInfo.paintBehavior.contains(PaintBehavior::SkipSelectionHighlight));
6273
6374 PaintInfo childPaintInfo(paintInfo);
 75 childPaintInfo.updateSubtreePaintRootForChildren(&renderer());
 76
6477 if (hasSelection && shouldPaintSelectionHighlight) {
6578 for (auto* child = firstChild(); child; child = child->nextOnLine()) {
6679 if (is<SVGInlineTextBox>(*child))

@@void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse
7083 }
7184 }
7285
 86#if ENABLE(LAYER_BASED_SVG_ENGINE)
 87 if (renderer().document().settings().layerBasedSVGEngineEnabled()) {
 88 for (auto* child = firstChild(); child; child = child->nextOnLine()) {
 89 if (child->renderer().isText() || !child->boxModelObject()->hasSelfPaintingLayer())
 90 child->paint(childPaintInfo, paintOffset, lineTop, lineBottom);
 91 }
 92
 93 return;
 94 }
 95#endif
 96
7397 SVGRenderingContext renderingContext(renderSVGText(), paintInfo, SVGRenderingContext::SaveGraphicsContext);
7498 if (renderingContext.isRenderingPrepared()) {
7599 for (auto* child = firstChild(); child; child = child->nextOnLine())

@@void SVGRootInlineBox::layoutRootBox(const FloatRect& childRect)
170194 RenderSVGText& parentBlock = renderSVGText();
171195
172196 // Finally, assign the root block position, now that all content is laid out.
173  LayoutRect boundingRect = enclosingLayoutRect(childRect);
174  parentBlock.setLocation(boundingRect.location());
175  parentBlock.setSize(boundingRect.size());
 197 parentBlock.updatePositionAndOverflow(childRect);
176198
177199 // Position all children relative to the parent block.
178200 for (auto* child = firstChild(); child; child = child->nextOnLine()) {

@@void SVGRootInlineBox::layoutRootBox(const FloatRect& childRect)
187209 setY(0);
188210 setLogicalWidth(childRect.width());
189211 setLogicalHeight(childRect.height());
 212
 213 auto boundingRect = enclosingLayoutRect(childRect);
190214 setLineTopBottomPositions(0, boundingRect.height(), 0, boundingRect.height());
191215}
192216

Source/WebCore/rendering/svg/SVGRootInlineBox.h

@@class SVGRootInlineBox final : public LegacyRootInlineBox {
3535public:
3636 explicit SVGRootInlineBox(RenderSVGText&);
3737
38  RenderSVGText& renderSVGText();
39 
4038 float virtualLogicalHeight() const override { return m_logicalHeight; }
4139 void setLogicalHeight(float height) { m_logicalHeight = height; }
4240

@@public:
4947 bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom, HitTestAction) final;
5048
5149private:
 50 RenderSVGText& renderSVGText() const;
 51
5252 bool isSVGRootInlineBox() const override { return true; }
5353 void reorderValueListsToLogicalOrder(Vector<SVGTextLayoutAttributes*>&);
5454 void layoutCharactersInTextBoxes(LegacyInlineFlowBox*, SVGTextLayoutEngine&);

Source/WebCore/svg/SVGElement.cpp

@@static MemoryCompactLookupOnlyRobinHoodHashSet<AtomString> createSVGLayerAwareEl
531531 // List of all SVG elements whose renderers support the layer aware layout / painting / hit-testing mode ('LBSE-mode').
532532 using namespace SVGNames;
533533 MemoryCompactLookupOnlyRobinHoodHashSet<AtomString> set;
534  for (auto& tag : { gTag.get(), rectTag.get() })
 534 for (auto& tag : { gTag.get(), rectTag.get(), textTag.get() })
535535 set.add(tag.localName());
536536 return set;
537537}