| File: | Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/Source/WebCore/rendering/shapes/ShapeOutsideInfo.cpp |
| Warning: | line 326, column 18 Local variable 'cachedImage' is uncounted and unsafe |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* |
| 2 | * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. |
| 3 | * |
| 4 | * Redistribution and use in source and binary forms, with or without |
| 5 | * modification, are permitted provided that the following conditions |
| 6 | * are met: |
| 7 | * |
| 8 | * 1. Redistributions of source code must retain the above |
| 9 | * copyright notice, this list of conditions and the following |
| 10 | * disclaimer. |
| 11 | * 2. Redistributions in binary form must reproduce the above |
| 12 | * copyright notice, this list of conditions and the following |
| 13 | * disclaimer in the documentation and/or other materials |
| 14 | * provided with the distribution. |
| 15 | * |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY |
| 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE |
| 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, |
| 21 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |
| 25 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF |
| 26 | * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 27 | * SUCH DAMAGE. |
| 28 | */ |
| 29 | |
| 30 | #include "config.h" |
| 31 | #include "ShapeOutsideInfo.h" |
| 32 | |
| 33 | #include "BoxLayoutShape.h" |
| 34 | #include "FloatingObjects.h" |
| 35 | #include "NullGraphicsContext.h" |
| 36 | #include "RenderBlockFlowInlines.h" |
| 37 | #include "RenderBoxInlines.h" |
| 38 | #include "RenderBoxModelObjectInlines.h" |
| 39 | #include "RenderFragmentContainer.h" |
| 40 | #include "RenderImage.h" |
| 41 | #include "RenderView.h" |
| 42 | #include "StyleImage.h" |
| 43 | #include <JavaScriptCore/ConsoleTypes.h> |
| 44 | #include <wtf/TZoneMallocInlines.h> |
| 45 | #include <wtf/text/MakeString.h> |
| 46 | |
| 47 | namespace WebCore { |
| 48 | |
| 49 | WTF_MAKE_TZONE_ALLOCATED_IMPL(ShapeOutsideDeltas)::bmalloc::api::HeapRef ShapeOutsideDeltas::s_heapRef; const TZoneSpecification ShapeOutsideDeltas::s_heapSpec = { &ShapeOutsideDeltas:: s_heapRef, TZoneSpecification::encodeSize<ShapeOutsideDeltas >(), TZoneSpecification::encodeAlignment<ShapeOutsideDeltas >(), TZoneSpecification::encodeCategory<ShapeOutsideDeltas >(), ::bmalloc::api::compactAllocationMode<ShapeOutsideDeltas >(), TZoneSpecification::encodeDescriptor<ShapeOutsideDeltas >(), }; void* ShapeOutsideDeltas::operatorNewSlow(size_t size ) { if constexpr (::bmalloc::api::compactAllocationMode<ShapeOutsideDeltas >() == CompactAllocationMode::Compact) return ::bmalloc::api ::tzoneAllocateCompactSlow(size, s_heapSpec); return ::bmalloc ::api::tzoneAllocateNonCompactSlow(size, s_heapSpec); } using __makeBtzoneMallocedInlineMacroSemicolonifier __attribute__( (unused)) = int; |
| 50 | WTF_MAKE_TZONE_ALLOCATED_IMPL(ShapeOutsideInfo)::bmalloc::api::HeapRef ShapeOutsideInfo::s_heapRef; const TZoneSpecification ShapeOutsideInfo::s_heapSpec = { &ShapeOutsideInfo::s_heapRef , TZoneSpecification::encodeSize<ShapeOutsideInfo>(), TZoneSpecification ::encodeAlignment<ShapeOutsideInfo>(), TZoneSpecification ::encodeCategory<ShapeOutsideInfo>(), ::bmalloc::api::compactAllocationMode <ShapeOutsideInfo>(), TZoneSpecification::encodeDescriptor <ShapeOutsideInfo>(), }; void* ShapeOutsideInfo::operatorNewSlow (size_t size) { if constexpr (::bmalloc::api::compactAllocationMode <ShapeOutsideInfo>() == CompactAllocationMode::Compact) return ::bmalloc::api::tzoneAllocateCompactSlow(size, s_heapSpec ); return ::bmalloc::api::tzoneAllocateNonCompactSlow(size, s_heapSpec ); } using __makeBtzoneMallocedInlineMacroSemicolonifier __attribute__ ((unused)) = int; |
| 51 | |
| 52 | static LayoutUnit logicalLeftOffset(const RenderBox&); |
| 53 | static LayoutUnit logicalTopOffset(const RenderBox&); |
| 54 | |
| 55 | LayoutRect ShapeOutsideInfo::computedShapePhysicalBoundingBox() const |
| 56 | { |
| 57 | LayoutRect physicalBoundingBox = computedShape().shapeMarginLogicalBoundingBox(); |
| 58 | if (m_renderer.writingMode().isBlockFlipped()) |
| 59 | physicalBoundingBox.setY(m_renderer.logicalHeight() - physicalBoundingBox.maxY()); |
| 60 | if (!m_renderer.isHorizontalWritingMode()) |
| 61 | physicalBoundingBox = physicalBoundingBox.transposedRect(); |
| 62 | return physicalBoundingBox; |
| 63 | } |
| 64 | |
| 65 | FloatPoint ShapeOutsideInfo::shapeToRendererPoint(const FloatPoint& point) const |
| 66 | { |
| 67 | FloatPoint result = point; |
| 68 | if (m_renderer.writingMode().isBlockFlipped()) |
| 69 | result.setY(m_renderer.logicalHeight() - result.y()); |
| 70 | if (!m_renderer.isHorizontalWritingMode()) |
| 71 | result = result.transposedPoint(); |
| 72 | return result; |
| 73 | } |
| 74 | |
| 75 | static LayoutSize computeLogicalBoxSize(const RenderBox& renderer, bool isHorizontalWritingMode) |
| 76 | { |
| 77 | auto& shapeOutside = renderer.style().shapeOutside(); |
| 78 | auto size = isHorizontalWritingMode ? renderer.size() : renderer.size().transposedSize(); |
| 79 | switch (shapeOutside.effectiveCSSBox()) { |
| 80 | case CSSBoxType::MarginBox: |
| 81 | if (isHorizontalWritingMode) |
| 82 | size.expand(renderer.horizontalMarginExtent(), renderer.verticalMarginExtent()); |
| 83 | else |
| 84 | size.expand(renderer.verticalMarginExtent(), renderer.horizontalMarginExtent()); |
| 85 | break; |
| 86 | case CSSBoxType::BorderBox: |
| 87 | break; |
| 88 | case CSSBoxType::PaddingBox: |
| 89 | if (isHorizontalWritingMode) |
| 90 | size.shrink(renderer.horizontalBorderExtent(), renderer.verticalBorderExtent()); |
| 91 | else |
| 92 | size.shrink(renderer.verticalBorderExtent(), renderer.horizontalBorderExtent()); |
| 93 | break; |
| 94 | case CSSBoxType::ContentBox: |
| 95 | if (isHorizontalWritingMode) |
| 96 | size.shrink(renderer.horizontalBorderAndPaddingExtent(), renderer.verticalBorderAndPaddingExtent()); |
| 97 | else |
| 98 | size.shrink(renderer.verticalBorderAndPaddingExtent(), renderer.horizontalBorderAndPaddingExtent()); |
| 99 | break; |
| 100 | case CSSBoxType::FillBox: |
| 101 | case CSSBoxType::StrokeBox: |
| 102 | case CSSBoxType::ViewBox: |
| 103 | case CSSBoxType::BoxMissing: |
| 104 | ASSERT_NOT_REACHED()((void)0); |
| 105 | break; |
| 106 | } |
| 107 | return size; |
| 108 | } |
| 109 | |
| 110 | static inline LayoutUnit borderBeforeInWritingMode(const RenderBox& renderer, WritingMode writingMode) |
| 111 | { |
| 112 | switch (writingMode.blockDirection()) { |
| 113 | case FlowDirection::TopToBottom: return renderer.borderTop(); |
| 114 | case FlowDirection::BottomToTop: return renderer.borderBottom(); |
| 115 | case FlowDirection::LeftToRight: return renderer.borderLeft(); |
| 116 | case FlowDirection::RightToLeft: return renderer.borderRight(); |
| 117 | } |
| 118 | |
| 119 | ASSERT_NOT_REACHED()((void)0); |
| 120 | return renderer.borderBefore(); |
| 121 | } |
| 122 | |
| 123 | static inline LayoutUnit borderAndPaddingBeforeInWritingMode(const RenderBox& renderer, WritingMode writingMode) |
| 124 | { |
| 125 | switch (writingMode.blockDirection()) { |
| 126 | case FlowDirection::TopToBottom: return renderer.borderTop() + renderer.paddingTop(); |
| 127 | case FlowDirection::BottomToTop: return renderer.borderBottom() + renderer.paddingBottom(); |
| 128 | case FlowDirection::LeftToRight: return renderer.borderLeft() + renderer.paddingLeft(); |
| 129 | case FlowDirection::RightToLeft: return renderer.borderRight() + renderer.paddingRight(); |
| 130 | } |
| 131 | |
| 132 | ASSERT_NOT_REACHED()((void)0); |
| 133 | return renderer.borderAndPaddingBefore(); |
| 134 | } |
| 135 | |
| 136 | static LayoutUnit logicalTopOffset(const RenderBox& renderer) |
| 137 | { |
| 138 | switch (renderer.style().shapeOutside().effectiveCSSBox()) { |
| 139 | case CSSBoxType::MarginBox: |
| 140 | return -renderer.marginBefore(renderer.containingBlock()->writingMode()); |
| 141 | case CSSBoxType::BorderBox: |
| 142 | return 0_lu; |
| 143 | case CSSBoxType::PaddingBox: |
| 144 | return borderBeforeInWritingMode(renderer, renderer.containingBlock()->writingMode()); |
| 145 | case CSSBoxType::ContentBox: |
| 146 | return borderAndPaddingBeforeInWritingMode(renderer, renderer.containingBlock()->writingMode()); |
| 147 | case CSSBoxType::FillBox: |
| 148 | break; |
| 149 | case CSSBoxType::StrokeBox: |
| 150 | break; |
| 151 | case CSSBoxType::ViewBox: |
| 152 | break; |
| 153 | case CSSBoxType::BoxMissing: |
| 154 | break; |
| 155 | } |
| 156 | |
| 157 | ASSERT_NOT_REACHED()((void)0); |
| 158 | return 0_lu; |
| 159 | } |
| 160 | |
| 161 | static inline LayoutUnit borderStartWithStyleForWritingMode(const RenderBox& renderer, const WritingMode writingMode) |
| 162 | { |
| 163 | if (writingMode.isHorizontal()) { |
| 164 | if (writingMode.isInlineLeftToRight()) |
| 165 | return renderer.borderLeft(); |
| 166 | |
| 167 | return renderer.borderRight(); |
| 168 | } |
| 169 | if (writingMode.isInlineTopToBottom()) |
| 170 | return renderer.borderTop(); |
| 171 | |
| 172 | return renderer.borderBottom(); |
| 173 | } |
| 174 | |
| 175 | static inline LayoutUnit borderAndPaddingStartWithStyleForWritingMode(const RenderBox& renderer, const WritingMode writingMode) |
| 176 | { |
| 177 | if (writingMode.isHorizontal()) { |
| 178 | if (writingMode.isInlineLeftToRight()) |
| 179 | return renderer.borderLeft() + renderer.paddingLeft(); |
| 180 | |
| 181 | return renderer.borderRight() + renderer.paddingRight(); |
| 182 | } |
| 183 | if (writingMode.isInlineTopToBottom()) |
| 184 | return renderer.borderTop() + renderer.paddingTop(); |
| 185 | |
| 186 | return renderer.borderBottom() + renderer.paddingBottom(); |
| 187 | } |
| 188 | |
| 189 | static inline LayoutUnit marginBorderAndPaddingStartWithStyleForWritingMode(const RenderBox& renderer, WritingMode writingMode) |
| 190 | { |
| 191 | return (writingMode.isHorizontal() ? renderer.marginLeft() : renderer.marginTop()) + borderAndPaddingStartWithStyleForWritingMode(renderer, writingMode); |
| 192 | } |
| 193 | |
| 194 | static inline LayoutUnit marginBorderAndPaddingBeforeWithStyleForWritingMode(const RenderBox& renderer, WritingMode writingMode) |
| 195 | { |
| 196 | return (writingMode.isHorizontal() ? renderer.marginTop() : renderer.marginRight()) + borderAndPaddingBeforeInWritingMode(renderer, writingMode); |
| 197 | } |
| 198 | |
| 199 | static LayoutUnit logicalLeftOffset(const RenderBox& renderer) |
| 200 | { |
| 201 | if (renderer.isRenderFragmentContainer()) |
| 202 | return 0_lu; |
| 203 | |
| 204 | switch (renderer.style().shapeOutside().effectiveCSSBox()) { |
| 205 | case CSSBoxType::MarginBox: |
| 206 | return -renderer.marginStart(renderer.containingBlock()->writingMode()); |
| 207 | case CSSBoxType::BorderBox: |
| 208 | return 0_lu; |
| 209 | case CSSBoxType::PaddingBox: |
| 210 | return borderStartWithStyleForWritingMode(renderer, renderer.containingBlock()->writingMode()); |
| 211 | case CSSBoxType::ContentBox: |
| 212 | return borderAndPaddingStartWithStyleForWritingMode(renderer, renderer.containingBlock()->writingMode()); |
| 213 | case CSSBoxType::FillBox: |
| 214 | break; |
| 215 | case CSSBoxType::StrokeBox: |
| 216 | break; |
| 217 | case CSSBoxType::ViewBox: |
| 218 | break; |
| 219 | case CSSBoxType::BoxMissing: |
| 220 | break; |
| 221 | } |
| 222 | |
| 223 | ASSERT_NOT_REACHED()((void)0); |
| 224 | return 0_lu; |
| 225 | } |
| 226 | |
| 227 | void ShapeOutsideInfo::invalidateForSizeChangeIfNeeded() |
| 228 | { |
| 229 | auto newSize = computeLogicalBoxSize(m_renderer, m_renderer.containingBlock()->isHorizontalWritingMode()); |
| 230 | if (m_cachedShapeLogicalSize == newSize) |
| 231 | return; |
| 232 | |
| 233 | markShapeAsDirty(); |
| 234 | m_cachedShapeLogicalSize = newSize; |
| 235 | } |
| 236 | |
| 237 | static LayoutRect shapeImageMarginRect(const RenderBox& renderBox, const LayoutSize& referenceBoxLogicalSize) |
| 238 | { |
| 239 | auto writingMode = renderBox.containingBlock()->writingMode(); |
| 240 | auto marginBoxOffsetFromContentBox = LayoutPoint { -marginBorderAndPaddingStartWithStyleForWritingMode(renderBox, writingMode), -marginBorderAndPaddingBeforeWithStyleForWritingMode(renderBox, writingMode) }; |
| 241 | auto marginBorderAndPaddingSize = LayoutSize { renderBox.marginLogicalWidth() + renderBox.borderAndPaddingLogicalWidth(), renderBox.marginLogicalHeight() + renderBox.borderAndPaddingLogicalHeight() }; |
| 242 | |
| 243 | auto marginRectSize = LayoutSize { referenceBoxLogicalSize + marginBorderAndPaddingSize }; |
| 244 | marginRectSize.clampNegativeToZero(); |
| 245 | return LayoutRect(marginBoxOffsetFromContentBox, marginRectSize); |
| 246 | } |
| 247 | |
| 248 | Ref<const LayoutShape> makeShapeForShapeOutside(const RenderBox& renderer) |
| 249 | { |
| 250 | auto& style = renderer.style(); |
| 251 | auto& containingBlock = *renderer.containingBlock(); |
| 252 | auto writingMode = containingBlock.style().writingMode(); |
| 253 | bool isHorizontalWritingMode = containingBlock.isHorizontalWritingMode(); |
| 254 | auto shapeImageThreshold = style.shapeImageThreshold(); |
| 255 | auto& shapeOutside = style.shapeOutside(); |
| 256 | auto zoom = style.usedZoomForLength(); |
| 257 | |
| 258 | auto boxSize = computeLogicalBoxSize(renderer, isHorizontalWritingMode); |
| 259 | |
| 260 | auto logicalMargin = [&] { |
| 261 | auto shapeMargin = Style::evaluate<LayoutUnit>(style.shapeMargin(), containingBlock.contentBoxLogicalWidth(), zoom).toFloat(); |
| 262 | return isnan(shapeMargin) ? 0.0f : shapeMargin; |
| 263 | }(); |
| 264 | |
| 265 | return WTF::switchOn(shapeOutside, |
| 266 | [&](const Style::ShapeOutside::Shape& shape) { |
| 267 | auto offset = LayoutPoint { logicalLeftOffset(renderer), logicalTopOffset(renderer) }; |
| 268 | return LayoutShape::createShape(shape, offset, boxSize, writingMode, logicalMargin, zoom); |
| 269 | }, |
| 270 | [&](const Style::ShapeOutside::ShapeAndShapeBox& shapeAndShapeBox) { |
| 271 | auto offset = LayoutPoint { logicalLeftOffset(renderer), logicalTopOffset(renderer) }; |
| 272 | return LayoutShape::createShape(shapeAndShapeBox.shape, offset, boxSize, writingMode, logicalMargin, zoom); |
| 273 | }, |
| 274 | [&](const Style::ShapeOutside::Image& shapeImage) { |
| 275 | ASSERT(shapeImage.isValid())((void)0); |
| 276 | |
| 277 | Ref styleImage = shapeImage.image.value; |
| 278 | auto logicalImageSize = renderer.calculateImageIntrinsicDimensions(styleImage.ptr(), boxSize, RenderImage::ScaleByUsedZoom::Yes); |
| 279 | styleImage->setContainerContextForRenderer(renderer, logicalImageSize, style.usedZoom()); |
| 280 | |
| 281 | auto logicalMarginRect = shapeImageMarginRect(renderer, boxSize); |
| 282 | auto* renderImage = dynamicDowncast<RenderImage>(renderer); |
| 283 | auto logicalImageRect = renderImage ? renderImage->replacedContentRect() : LayoutRect { { }, logicalImageSize }; |
| 284 | |
| 285 | ASSERT(!styleImage->isPending())((void)0); |
| 286 | auto physicalImageSize = writingMode.isHorizontal() ? logicalImageSize : logicalImageSize.transposedSize(); |
| 287 | |
| 288 | RefPtr image = styleImage->image(const_cast<RenderBox*>(&renderer), physicalImageSize, NullGraphicsContext()); |
| 289 | return LayoutShape::createRasterShape(image.get(), shapeImageThreshold.value, logicalImageRect, logicalMarginRect, writingMode, logicalMargin); |
| 290 | }, |
| 291 | [&](const Style::ShapeOutside::ShapeBox&) { |
| 292 | auto shapeRect = computeRoundedRectForBoxShape(shapeOutside.effectiveCSSBox(), renderer); |
| 293 | auto flipForWritingAndInlineDirection = [&] { |
| 294 | // FIXME: We should consider this moving to LayoutRoundedRect::transposedRect. |
| 295 | if (!isHorizontalWritingMode) { |
| 296 | shapeRect = shapeRect.transposedRect(); |
| 297 | auto radiiForBlockDirection = shapeRect.radii(); |
| 298 | if (writingMode.isLineOverLeft()) // sideways-lr |
| 299 | shapeRect.setRadii({ radiiForBlockDirection.bottomLeft(), radiiForBlockDirection.topLeft(), radiiForBlockDirection.bottomRight(), radiiForBlockDirection.topRight() }); |
| 300 | else if (writingMode.isBlockLeftToRight()) // vertical-lr |
| 301 | shapeRect.setRadii({ radiiForBlockDirection.topLeft(), radiiForBlockDirection.bottomLeft(), radiiForBlockDirection.topRight(), radiiForBlockDirection.bottomRight() }); |
| 302 | else // vertical-rl, sideways-rl |
| 303 | shapeRect.setRadii({ radiiForBlockDirection.topRight(), radiiForBlockDirection.bottomRight(), radiiForBlockDirection.topLeft(), radiiForBlockDirection.bottomLeft() }); |
| 304 | } |
| 305 | if (writingMode.isBidiRTL()) { |
| 306 | auto radii = shapeRect.radii(); |
| 307 | shapeRect.setRadii({ radii.topRight(), radii.topLeft(), radii.bottomRight(), radii.bottomLeft() }); |
| 308 | } |
| 309 | }; |
| 310 | flipForWritingAndInlineDirection(); |
| 311 | return LayoutShape::createBoxShape(shapeRect, writingMode, logicalMargin); |
| 312 | }, |
| 313 | [&](const CSS::Keyword::None&) { |
| 314 | ASSERT_NOT_REACHED()((void)0); |
| 315 | return LayoutShape::createBoxShape(LayoutRoundedRect { { } }, writingMode, 0); |
| 316 | } |
| 317 | ); |
| 318 | } |
| 319 | |
| 320 | static inline bool checkShapeImageOrigin(Document& document, const Style::Image& styleImage) |
| 321 | { |
| 322 | if (styleImage.isGeneratedImage()) |
| 323 | return true; |
| 324 | |
| 325 | ASSERT(styleImage.cachedImage())((void)0); |
| 326 | CachedImage& cachedImage = *(styleImage.cachedImage()); |
Local variable 'cachedImage' is uncounted and unsafe | |
| 327 | if (cachedImage.isOriginClean(&document.securityOrigin())) |
| 328 | return true; |
| 329 | |
| 330 | const URL& url = cachedImage.url(); |
| 331 | String urlString = url.isNull() ? "''"_s : url.stringCenterEllipsizedToLength(); |
| 332 | document.addConsoleMessage(MessageSource::Security, MessageLevel::Error, makeString("Unsafe attempt to load URL "_s, urlString, '.')); |
| 333 | |
| 334 | return false; |
| 335 | } |
| 336 | |
| 337 | const LayoutShape& ShapeOutsideInfo::computedShape() const |
| 338 | { |
| 339 | if (!m_shape) |
| 340 | m_shape = makeShapeForShapeOutside(m_renderer); |
| 341 | |
| 342 | return *m_shape; |
| 343 | } |
| 344 | |
| 345 | bool ShapeOutsideInfo::isEnabledFor(const RenderBox& box) |
| 346 | { |
| 347 | if (!box.isFloating()) |
| 348 | return false; |
| 349 | |
| 350 | return WTF::switchOn(box.style().shapeOutside(), |
| 351 | [](const CSS::Keyword::None&) { return false; }, |
| 352 | [](const Style::ShapeOutside::Shape&) { return true; }, |
| 353 | [](const Style::ShapeOutside::ShapeBox&) { return true; }, |
| 354 | [](const Style::ShapeOutside::ShapeAndShapeBox&) { return true; }, |
| 355 | [&](const Style::ShapeOutside::Image& image) { return image.isValid() && checkShapeImageOrigin(box.document(), image.image.value); } |
| 356 | ); |
| 357 | } |
| 358 | |
| 359 | ShapeOutsideDeltas ShapeOutsideInfo::computeDeltasForContainingBlockLine(const RenderBlockFlow& containingBlock, const FloatingObject& floatingObject, LayoutUnit lineTop, LayoutUnit lineHeight) |
| 360 | { |
| 361 | // If we never constructed this shape during layout, we propably don't need to know about it outside of layout in the context of "containing block line". |
| 362 | if (!m_shape && !containingBlock.view().frameView().layoutContext().isInLayout()) |
| 363 | return { }; |
| 364 | |
| 365 | ASSERT(lineHeight >= 0)((void)0); |
| 366 | LayoutUnit borderBoxTop = containingBlock.logicalTopForFloat(floatingObject) + containingBlock.marginBeforeForChild(m_renderer); |
| 367 | LayoutUnit borderBoxLineTop = lineTop - borderBoxTop; |
| 368 | |
| 369 | if (isShapeDirty() || !m_shapeOutsideDeltas.isForLine(borderBoxLineTop, lineHeight)) { |
| 370 | LayoutUnit floatMarginBoxWidth = std::max<LayoutUnit>(0_lu, containingBlock.logicalWidthForFloat(floatingObject)); |
| 371 | |
| 372 | if (computedShape().lineOverlapsShapeMarginBounds(borderBoxLineTop, lineHeight)) { |
| 373 | LineSegment segment = computedShape().getExcludedInterval(borderBoxLineTop, std::min(lineHeight, shapeLogicalBottom() - borderBoxLineTop)); |
| 374 | if (segment.isValid) { |
| 375 | LayoutUnit logicalLeftMargin = containingBlock.writingMode().isLogicalLeftInlineStart() ? containingBlock.marginStartForChild(m_renderer) : containingBlock.marginEndForChild(m_renderer); |
| 376 | LayoutUnit rawLeftMarginBoxDelta { segment.logicalLeft + logicalLeftMargin }; |
| 377 | LayoutUnit leftMarginBoxDelta = clampTo<LayoutUnit>(rawLeftMarginBoxDelta, 0_lu, floatMarginBoxWidth); |
| 378 | |
| 379 | LayoutUnit logicalRightMargin = containingBlock.writingMode().isLogicalLeftInlineStart() ? containingBlock.marginEndForChild(m_renderer) : containingBlock.marginStartForChild(m_renderer); |
| 380 | LayoutUnit rawRightMarginBoxDelta { segment.logicalRight - containingBlock.logicalWidthForChild(m_renderer) - logicalRightMargin }; |
| 381 | LayoutUnit rightMarginBoxDelta = clampTo<LayoutUnit>(rawRightMarginBoxDelta, -floatMarginBoxWidth, 0_lu); |
| 382 | |
| 383 | m_shapeOutsideDeltas = ShapeOutsideDeltas(leftMarginBoxDelta, rightMarginBoxDelta, true, borderBoxLineTop, lineHeight); |
| 384 | return m_shapeOutsideDeltas; |
| 385 | } |
| 386 | } |
| 387 | |
| 388 | // Lines that do not overlap the shape should act as if the float |
| 389 | // wasn't there for layout purposes. So we set the deltas to remove the |
| 390 | // entire width of the float |
| 391 | m_shapeOutsideDeltas = ShapeOutsideDeltas(floatMarginBoxWidth, -floatMarginBoxWidth, false, borderBoxLineTop, lineHeight); |
| 392 | } |
| 393 | |
| 394 | return m_shapeOutsideDeltas; |
| 395 | } |
| 396 | |
| 397 | } |