Changeset 275128 in webkit
- Timestamp:
- Mar 26, 2021 8:27:27 PM (16 months ago)
- Location:
- trunk/Source
- Files:
-
- 5 edited
-
WebCore/ChangeLog (modified) (1 diff)
-
WebCore/inspector/InspectorOverlay.cpp (modified) (13 diffs)
-
WebCore/inspector/InspectorOverlay.h (modified) (7 diffs)
-
WebKit/ChangeLog (modified) (1 diff)
-
WebKit/UIProcess/Inspector/ios/WKInspectorHighlightView.mm (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r275126 r275128 1 2021-03-26 Patrick Angle <pangle@apple.com> 2 3 Web Inspector: Grid layout labels can be drawn outside the viewport 4 https://bugs.webkit.org/show_bug.cgi?id=221972 5 6 Reviewed by BJ Burg. 7 8 Added logic for a best-effort attempt to make sure that layout labels are drawn within the document's bounds, or 9 at least within the grid itself. Labels are measured and adjusted so that if they would be drawn outside the 10 document's bounds, they will be pulled inside the grid. This does not guarantee that all labels will be visible 11 all the time. It is still possible an entire side of a grid will be outside the document's bounds, and this does 12 not attempt to correct for this case, as the desired anchor points for labels will be outside of the visible 13 area of the document. 14 15 * inspector/InspectorOverlay.cpp: 16 (WebCore::InspectorOverlay::fontForLayoutLabel): 17 - Added helper that creates the FontCascade for layout labels, which is done in a few different places. 18 (WebCore::InspectorOverlay::backgroundPathForLayoutLabel): 19 - Added helper to create the Path for the background of layout labels, which is now used in `WebKit::WKInspectorHighlightView`. 20 (WebCore::expectedSizeForLayoutLabel): 21 - Gets the expected size of the label based on the text and arrow direction, and does so without needing to 22 create the entire label background's path. 23 (WebCore::InspectorOverlay::drawLayoutLabel): 24 - Support new `LabelArrowEdgePosition` property 25 (WebCore::InspectorOverlay::drawGridOverlay): 26 (WebCore::buildLabel): 27 (WebCore::InspectorOverlay::buildGridOverlay): 28 * inspector/InspectorOverlay.h: 29 (WebCore::InspectorOverlay::Highlight::GridHighlightOverlay::Label::encode const): 30 (WebCore::InspectorOverlay::Highlight::GridHighlightOverlay::Label::decode): 31 1 32 2021-03-26 Zalan Bujtas <zalan@apple.com> 2 33 -
trunk/Source/WebCore/inspector/InspectorOverlay.cpp
r274822 r275128 85 85 static constexpr float rulerSubStepLength = 5; 86 86 87 static constexpr float layoutLabelPadding = 3; 88 static constexpr float layoutLabelArrowSize = 4; 89 87 90 static constexpr UChar bullet = 0x2022; 88 91 static constexpr UChar ellipsis = 0x2026; … … 1200 1203 } 1201 1204 1202 void InspectorOverlay::drawLayoutLabel(GraphicsContext& context, String label, FloatPoint point, InspectorOverlay::LabelArrowDirection direction, Color backgroundColor, float maximumWidth) 1203 { 1204 GraphicsContextStateSaver saver(context); 1205 1206 context.translate(point); 1207 1205 FontCascade InspectorOverlay::fontForLayoutLabel() 1206 { 1208 1207 FontCascadeDescription fontDescription; 1209 1208 fontDescription.setFamilies({ "system-ui" }); … … 1213 1212 FontCascade font(WTFMove(fontDescription), 0, 0); 1214 1213 font.update(nullptr); 1215 1216 constexpr auto padding = 4; 1217 constexpr auto arrowSize = 4; 1214 return font; 1215 } 1216 1217 Path InspectorOverlay::backgroundPathForLayoutLabel(float width, float height, InspectorOverlay::LabelArrowDirection arrowDirection, InspectorOverlay::LabelArrowEdgePosition arrowEdgePosition, float arrowSize) 1218 { 1219 Path path; 1220 FloatSize offsetForArrowEdgePosition; 1221 1222 switch (arrowDirection) { 1223 case InspectorOverlay::LabelArrowDirection::Down: 1224 path.moveTo({ -(width / 2), -height - arrowSize}); 1225 path.addLineTo({ -(width / 2), -arrowSize }); 1226 1227 switch (arrowEdgePosition) { 1228 case InspectorOverlay::LabelArrowEdgePosition::Leading: 1229 path.addLineTo({ -(width / 2), 0 }); 1230 path.addLineTo({ -(width / 2) + arrowSize, -arrowSize }); 1231 offsetForArrowEdgePosition = { (width / 2), 0 }; 1232 break; 1233 case InspectorOverlay::LabelArrowEdgePosition::Middle: 1234 path.addLineTo({ -arrowSize, -arrowSize }); 1235 path.addLineTo({ 0, 0 }); 1236 path.addLineTo({ arrowSize, -arrowSize }); 1237 break; 1238 case InspectorOverlay::LabelArrowEdgePosition::Trailing: 1239 path.addLineTo({ (width / 2) - arrowSize, -arrowSize }); 1240 path.addLineTo({ (width / 2), 0 }); 1241 offsetForArrowEdgePosition = { -(width / 2), 0 }; 1242 break; 1243 case InspectorOverlay::LabelArrowEdgePosition::None: 1244 break; 1245 } 1246 1247 path.addLineTo({ (width / 2), -arrowSize }); 1248 path.addLineTo({ (width / 2), -height - arrowSize }); 1249 break; 1250 case InspectorOverlay::LabelArrowDirection::Up: 1251 path.moveTo({ -(width / 2), height + arrowSize }); 1252 path.addLineTo({ -(width / 2), arrowSize }); 1253 1254 switch (arrowEdgePosition) { 1255 case InspectorOverlay::LabelArrowEdgePosition::Leading: 1256 path.addLineTo({ -(width / 2), 0 }); 1257 path.addLineTo({ -(width / 2) + arrowSize, arrowSize }); 1258 offsetForArrowEdgePosition = { (width / 2), 0 }; 1259 break; 1260 case InspectorOverlay::LabelArrowEdgePosition::Middle: 1261 path.addLineTo({ -arrowSize, arrowSize }); 1262 path.addLineTo({ 0, 0 }); 1263 path.addLineTo({ arrowSize, arrowSize }); 1264 break; 1265 case InspectorOverlay::LabelArrowEdgePosition::Trailing: 1266 path.addLineTo({ (width / 2) - arrowSize, arrowSize }); 1267 path.addLineTo({ (width / 2), 0 }); 1268 offsetForArrowEdgePosition = { -(width / 2), 0 }; 1269 break; 1270 case InspectorOverlay::LabelArrowEdgePosition::None: 1271 break; 1272 } 1273 1274 path.addLineTo({ (width / 2), arrowSize }); 1275 path.addLineTo({ (width / 2), height + arrowSize }); 1276 break; 1277 case InspectorOverlay::LabelArrowDirection::Right: 1278 path.moveTo({ -width - arrowSize, (height / 2) }); 1279 path.addLineTo({ -arrowSize, (height / 2) }); 1280 1281 switch (arrowEdgePosition) { 1282 case InspectorOverlay::LabelArrowEdgePosition::Leading: 1283 path.addLineTo({ -arrowSize, -(height / 2) + arrowSize }); 1284 path.addLineTo({ 0, -(height / 2) }); 1285 offsetForArrowEdgePosition = { 0, (height / 2) }; 1286 break; 1287 case InspectorOverlay::LabelArrowEdgePosition::Middle: 1288 path.addLineTo({ -arrowSize, arrowSize }); 1289 path.addLineTo({ 0, 0 }); 1290 path.addLineTo({ -arrowSize, -arrowSize }); 1291 break; 1292 case InspectorOverlay::LabelArrowEdgePosition::Trailing: 1293 path.addLineTo({ 0, (height / 2) }); 1294 path.addLineTo({ -arrowSize, (height / 2) - arrowSize }); 1295 offsetForArrowEdgePosition = { 0, -(height / 2) }; 1296 break; 1297 case InspectorOverlay::LabelArrowEdgePosition::None: 1298 break; 1299 } 1300 1301 path.addLineTo({ -arrowSize, -(height / 2) }); 1302 path.addLineTo({ -width - arrowSize, -(height / 2) }); 1303 break; 1304 case InspectorOverlay::LabelArrowDirection::Left: 1305 path.moveTo({ width + arrowSize, (height / 2) }); 1306 path.addLineTo({ arrowSize, (height / 2) }); 1307 1308 switch (arrowEdgePosition) { 1309 case InspectorOverlay::LabelArrowEdgePosition::Leading: 1310 path.addLineTo({ arrowSize, -(height / 2) + arrowSize }); 1311 path.addLineTo({ 0, -(height / 2) }); 1312 offsetForArrowEdgePosition = { 0, (height / 2) }; 1313 break; 1314 case InspectorOverlay::LabelArrowEdgePosition::Middle: 1315 path.addLineTo({ arrowSize, arrowSize }); 1316 path.addLineTo({ 0, 0 }); 1317 path.addLineTo({ arrowSize, -arrowSize }); 1318 break; 1319 case InspectorOverlay::LabelArrowEdgePosition::Trailing: 1320 path.addLineTo({ 0, (height / 2) }); 1321 path.addLineTo({ arrowSize, (height / 2) - arrowSize }); 1322 offsetForArrowEdgePosition = { 0, -(height / 2) }; 1323 break; 1324 case InspectorOverlay::LabelArrowEdgePosition::None: 1325 break; 1326 } 1327 1328 path.addLineTo({ arrowSize, -(height / 2) }); 1329 path.addLineTo({ width + arrowSize, -(height / 2) }); 1330 break; 1331 case InspectorOverlay::LabelArrowDirection::None: 1332 path.addLineTo({ 0, height }); 1333 path.addLineTo({ width, height }); 1334 path.addLineTo({ width, 0 }); 1335 break; 1336 } 1337 1338 path.closeSubpath(); 1339 path.translate(offsetForArrowEdgePosition); 1340 1341 return path; 1342 } 1343 1344 static FloatSize expectedSizeForLayoutLabel(String label, InspectorOverlay::LabelArrowDirection direction, float maximumWidth = 0) 1345 { 1346 auto font = InspectorOverlay::fontForLayoutLabel(); 1347 1348 float textHeight = font.fontMetrics().floatHeight(); 1349 float textWidth = font.width(TextRun(label)); 1350 if (maximumWidth && textWidth + (layoutLabelPadding * 2) > maximumWidth) 1351 textWidth = maximumWidth; 1352 1353 switch (direction) { 1354 case InspectorOverlay::LabelArrowDirection::Down: 1355 case InspectorOverlay::LabelArrowDirection::Up: 1356 return { textWidth + (layoutLabelPadding * 2), textHeight + (layoutLabelPadding * 2) + layoutLabelArrowSize }; 1357 case InspectorOverlay::LabelArrowDirection::Right: 1358 case InspectorOverlay::LabelArrowDirection::Left: 1359 return { textWidth + (layoutLabelPadding * 2) + layoutLabelArrowSize, textHeight + (layoutLabelPadding * 2) }; 1360 case InspectorOverlay::LabelArrowDirection::None: 1361 return { textWidth + (layoutLabelPadding * 2), textHeight + (layoutLabelPadding * 2) }; 1362 } 1363 } 1364 1365 void InspectorOverlay::drawLayoutLabel(GraphicsContext& context, String label, FloatPoint point, InspectorOverlay::LabelArrowDirection arrowDirection, InspectorOverlay::LabelArrowEdgePosition arrowEdgePosition, Color backgroundColor, float maximumWidth) 1366 { 1367 ASSERT(arrowEdgePosition != LabelArrowEdgePosition::None || arrowDirection == LabelArrowDirection::None); 1368 1369 GraphicsContextStateSaver saver(context); 1370 1371 context.translate(point); 1372 1373 auto font = fontForLayoutLabel(); 1218 1374 float textHeight = font.fontMetrics().floatHeight(); 1219 1375 float textDescent = font.fontMetrics().floatDescent(); 1220 1376 1221 1377 float textWidth = font.width(TextRun(label)); 1222 if (maximumWidth && textWidth + ( padding * 2) > maximumWidth) {1378 if (maximumWidth && textWidth + (layoutLabelPadding * 2) > maximumWidth) { 1223 1379 label.append("..."_s); 1224 while (textWidth + ( padding * 2) > maximumWidth && label.length() >= 4) {1380 while (textWidth + (layoutLabelPadding * 2) > maximumWidth && label.length() >= 4) { 1225 1381 // Remove the fourth from last character (the character before the ellipsis) and remeasure. 1226 1382 label.remove(label.length() - 4); … … 1228 1384 } 1229 1385 } 1230 1231 Path labelPath; 1386 1232 1387 FloatPoint textPosition; 1233 1234 switch (direction) { 1388 switch (arrowDirection) { 1235 1389 case InspectorOverlay::LabelArrowDirection::Down: 1236 labelPath.moveTo({ -(textWidth / 2) - padding, -textHeight - (padding * 2) - arrowSize }); 1237 labelPath.addLineTo({ -(textWidth / 2) - padding, -arrowSize }); 1238 labelPath.addLineTo({ -arrowSize, -arrowSize }); 1239 labelPath.addLineTo({ 0, 0 }); 1240 labelPath.addLineTo({ arrowSize, -arrowSize }); 1241 labelPath.addLineTo({ (textWidth / 2) + padding, -arrowSize }); 1242 labelPath.addLineTo({ (textWidth / 2) + padding, -textHeight - (padding * 2) - arrowSize }); 1243 textPosition = FloatPoint(-(textWidth / 2), -textDescent - arrowSize - padding); 1390 switch (arrowEdgePosition) { 1391 case InspectorOverlay::LabelArrowEdgePosition::Leading: 1392 textPosition = FloatPoint(layoutLabelPadding, -textDescent - layoutLabelArrowSize - layoutLabelPadding); 1393 break; 1394 case InspectorOverlay::LabelArrowEdgePosition::Middle: 1395 textPosition = FloatPoint(-(textWidth / 2), -textDescent - layoutLabelArrowSize - layoutLabelPadding); 1396 break; 1397 case InspectorOverlay::LabelArrowEdgePosition::Trailing: 1398 textPosition = FloatPoint(-(textWidth) - layoutLabelPadding, -textDescent - layoutLabelArrowSize - layoutLabelPadding); 1399 break; 1400 case InspectorOverlay::LabelArrowEdgePosition::None: 1401 break; 1402 } 1244 1403 break; 1245 1404 case InspectorOverlay::LabelArrowDirection::Up: 1246 labelPath.moveTo({ -(textWidth / 2) - padding, textHeight + (padding * 2) + arrowSize }); 1247 labelPath.addLineTo({ -(textWidth / 2) - padding, arrowSize }); 1248 labelPath.addLineTo({ -arrowSize, arrowSize }); 1249 labelPath.addLineTo({ 0, 0 }); 1250 labelPath.addLineTo({ arrowSize, arrowSize }); 1251 labelPath.addLineTo({ (textWidth / 2) + padding, arrowSize }); 1252 labelPath.addLineTo({ (textWidth / 2) + padding, textHeight + (padding * 2) + arrowSize }); 1253 textPosition = FloatPoint(-(textWidth / 2), textHeight - textDescent + arrowSize + padding); 1405 switch (arrowEdgePosition) { 1406 case InspectorOverlay::LabelArrowEdgePosition::Leading: 1407 textPosition = FloatPoint(layoutLabelPadding, textHeight - textDescent + layoutLabelArrowSize + layoutLabelPadding); 1408 break; 1409 case InspectorOverlay::LabelArrowEdgePosition::Middle: 1410 textPosition = FloatPoint(-(textWidth / 2), textHeight - textDescent + layoutLabelArrowSize + layoutLabelPadding); 1411 break; 1412 case InspectorOverlay::LabelArrowEdgePosition::Trailing: 1413 textPosition = FloatPoint(-(textWidth) - layoutLabelPadding, textHeight - textDescent + layoutLabelArrowSize + layoutLabelPadding); 1414 break; 1415 case InspectorOverlay::LabelArrowEdgePosition::None: 1416 break; 1417 } 1254 1418 break; 1255 1419 case InspectorOverlay::LabelArrowDirection::Right: 1256 labelPath.moveTo({ -textWidth - (padding * 2) - arrowSize, (textHeight / 2) + padding }); 1257 labelPath.addLineTo({ -arrowSize, (textHeight / 2) + padding }); 1258 labelPath.addLineTo({ -arrowSize, arrowSize }); 1259 labelPath.addLineTo({ 0, 0 }); 1260 labelPath.addLineTo({ -arrowSize, -arrowSize }); 1261 labelPath.addLineTo({ -arrowSize, -(textHeight / 2) - padding }); 1262 labelPath.addLineTo({ -textWidth - (padding * 2) - arrowSize, -(textHeight / 2) - padding }); 1263 textPosition = FloatPoint(-textWidth - arrowSize - padding, (textHeight / 2) - textDescent); 1420 switch (arrowEdgePosition) { 1421 case InspectorOverlay::LabelArrowEdgePosition::Leading: 1422 textPosition = FloatPoint(-textWidth - layoutLabelArrowSize - layoutLabelPadding, layoutLabelPadding + textHeight - textDescent); 1423 break; 1424 case InspectorOverlay::LabelArrowEdgePosition::Middle: 1425 textPosition = FloatPoint(-textWidth - layoutLabelArrowSize - layoutLabelPadding, (textHeight / 2) - textDescent); 1426 break; 1427 case InspectorOverlay::LabelArrowEdgePosition::Trailing: 1428 textPosition = FloatPoint(-textWidth - layoutLabelArrowSize - layoutLabelPadding, -layoutLabelPadding - textDescent); 1429 break; 1430 case InspectorOverlay::LabelArrowEdgePosition::None: 1431 break; 1432 } 1264 1433 break; 1265 1434 case InspectorOverlay::LabelArrowDirection::Left: 1266 labelPath.moveTo({ textWidth + (padding * 2) + arrowSize, (textHeight / 2) + padding }); 1267 labelPath.addLineTo({ arrowSize, (textHeight / 2) + padding }); 1268 labelPath.addLineTo({ arrowSize, arrowSize }); 1269 labelPath.addLineTo({ 0, 0 }); 1270 labelPath.addLineTo({ arrowSize, -arrowSize }); 1271 labelPath.addLineTo({ arrowSize, -(textHeight / 2) - padding }); 1272 labelPath.addLineTo({ textWidth + (padding * 2) + arrowSize, -(textHeight / 2) - padding }); 1273 textPosition = FloatPoint(arrowSize + padding, (textHeight / 2) - textDescent); 1435 switch (arrowEdgePosition) { 1436 case InspectorOverlay::LabelArrowEdgePosition::Leading: 1437 textPosition = FloatPoint(layoutLabelArrowSize + layoutLabelPadding, layoutLabelPadding + textHeight - textDescent); 1438 break; 1439 case InspectorOverlay::LabelArrowEdgePosition::Middle: 1440 textPosition = FloatPoint(layoutLabelArrowSize + layoutLabelPadding, (textHeight / 2) - textDescent); 1441 break; 1442 case InspectorOverlay::LabelArrowEdgePosition::Trailing: 1443 textPosition = FloatPoint(layoutLabelArrowSize + layoutLabelPadding, -layoutLabelPadding - textDescent); 1444 break; 1445 case InspectorOverlay::LabelArrowEdgePosition::None: 1446 break; 1447 } 1274 1448 break; 1275 1449 case InspectorOverlay::LabelArrowDirection::None: 1276 labelPath.addLineTo({ 0, textHeight + (padding * 2) }); 1277 labelPath.addLineTo({ textWidth + (padding * 2), textHeight + (padding * 2) }); 1278 labelPath.addLineTo({ textWidth + (padding * 2), 0 }); 1279 textPosition = FloatPoint(padding, padding + textHeight - textDescent); 1450 textPosition = FloatPoint(layoutLabelPadding, layoutLabelPadding + textHeight - textDescent); 1280 1451 break; 1281 1452 } 1282 1283 labelPath.closeSubpath();1284 1453 1454 Path labelPath = backgroundPathForLayoutLabel(textWidth + (layoutLabelPadding * 2), textHeight + (layoutLabelPadding * 2), arrowDirection, arrowEdgePosition, layoutLabelArrowSize); 1455 1285 1456 context.setFillColor(backgroundColor); 1286 1457 context.fillPath(labelPath); … … 1316 1487 context.setStrokeThickness(1); 1317 1488 for (auto area : gridOverlay.areas) 1318 drawLayoutLabel(context, area.name, area.quad.p1(), LabelArrowDirection::None, translucentLabelBackgroundColor, area.quad.boundingBox().width());1489 drawLayoutLabel(context, area.name, area.quad.p1(), LabelArrowDirection::None, LabelArrowEdgePosition::None, translucentLabelBackgroundColor, area.quad.boundingBox().width()); 1319 1490 1320 1491 for (auto label : gridOverlay.labels) 1321 drawLayoutLabel(context, label.text, label.location, label.arrowDirection, label. backgroundColor);1492 drawLayoutLabel(context, label.text, label.location, label.arrowDirection, label.arrowEdgePosition, label.backgroundColor); 1322 1493 } 1323 1494 … … 1420 1591 } 1421 1592 1422 static InspectorOverlay::Highlight::GridHighlightOverlay::Label buildLabel(String text, FloatPoint location, Color backgroundColor, InspectorOverlay::LabelArrowDirection arrowDirection )1593 static InspectorOverlay::Highlight::GridHighlightOverlay::Label buildLabel(String text, FloatPoint location, Color backgroundColor, InspectorOverlay::LabelArrowDirection arrowDirection, InspectorOverlay::LabelArrowEdgePosition arrowEdgePosition) 1423 1594 { 1424 1595 InspectorOverlay::Highlight::GridHighlightOverlay::Label label; … … 1427 1598 label.backgroundColor = backgroundColor; 1428 1599 label.arrowDirection = arrowDirection; 1600 label.arrowEdgePosition = arrowEdgePosition; 1429 1601 return label; 1430 1602 } … … 1455 1627 return { }; 1456 1628 FloatRect viewportBounds = { { 0, 0 }, pageView->sizeForVisibleContent() }; 1629 1630 auto scrollPosition = pageView->scrollPosition(); 1457 1631 if (offsetBoundsByScroll) 1458 viewportBounds.setLocation( pageView->scrollPosition());1632 viewportBounds.setLocation(scrollPosition); 1459 1633 1460 1634 auto& renderGrid = *downcast<RenderGrid>(renderer); … … 1505 1679 } 1506 1680 1507 Float Point gapLabelPosition = columnStartLine.start();1681 FloatLine gapLabelLine = columnStartLine; 1508 1682 if (i) { 1509 1683 gridHighlightOverlay.gaps.append({ previousColumnEndLine.start(), columnStartLine.start(), columnStartLine.end(), previousColumnEndLine.end() }); 1510 1684 FloatLine lineBetweenColumnTops = { columnStartLine.start(), previousColumnEndLine.start() }; 1511 gapLabelPosition = lineBetweenColumnTops.pointAtRelativeDistance(0.5); 1685 FloatLine lineBetweenColumnBottoms = { columnStartLine.end(), previousColumnEndLine.end() }; 1686 gapLabelLine = { lineBetweenColumnTops.pointAtRelativeDistance(0.5), lineBetweenColumnTops.pointAtRelativeDistance(0.5) }; 1512 1687 } 1513 1688 … … 1540 1715 1541 1716 FloatLine trackTopLine = { columnStartLine.start(), columnEndLine.start() }; 1542 gridHighlightOverlay.labels.append(buildLabel(trackSizeLabel, trackTopLine.pointAtRelativeDistance(0.5), translucentLabelBackgroundColor, LabelArrowDirection::Up ));1717 gridHighlightOverlay.labels.append(buildLabel(trackSizeLabel, trackTopLine.pointAtRelativeDistance(0.5), translucentLabelBackgroundColor, LabelArrowDirection::Up, LabelArrowEdgePosition::Middle)); 1543 1718 } 1544 1719 } else … … 1555 1730 } 1556 1731 } 1557 // FIXME: <webkit.org/b/221972> Layout labels can be drawn outside the viewport, and a best effort should be made to keep them in the viewport while the grid is in the viewport. 1558 if (!lineLabel.isEmpty()) 1559 gridHighlightOverlay.labels.append(buildLabel(lineLabel.toString(), gapLabelPosition, Color::white, LabelArrowDirection::Down)); 1732 1733 if (!lineLabel.isEmpty()) { 1734 auto text = lineLabel.toString(); 1735 auto arrowDirection = LabelArrowDirection::Down; 1736 auto arrowEdgePosition = LabelArrowEdgePosition::Middle; 1737 1738 if (!i) 1739 arrowEdgePosition = LabelArrowEdgePosition::Leading; 1740 else if (i == columnPositions.size() - 1) 1741 arrowEdgePosition = LabelArrowEdgePosition::Trailing; 1742 1743 auto expectedLabelSize = expectedSizeForLayoutLabel(text, arrowDirection); 1744 auto gapLabelPosition = gapLabelLine.start(); 1745 1746 // The area under the window's toolbar is drawable, but not meaningfully visible, so we must account for that space. 1747 auto topEdgeInset = pageView->topContentInset(ScrollView::TopContentInsetType::WebCoreOrPlatformContentInset); 1748 if (gapLabelLine.start().y() - expectedLabelSize.height() - topEdgeInset + scrollPosition.y() - viewportBounds.y() < 0) { 1749 arrowDirection = LabelArrowDirection::Up; 1750 1751 // Special case for the first column to make sure the label will be out of the way of the first row's label. 1752 // The label heights will be the same, as they use the same font, so moving down by this label's size will 1753 // create enough space for this special circumstance. 1754 if (!i) 1755 gapLabelPosition = gapLabelLine.pointAtAbsoluteDistance(expectedLabelSize.height()); 1756 } 1757 1758 gridHighlightOverlay.labels.append(buildLabel(text, gapLabelPosition, Color::white, arrowDirection, arrowEdgePosition)); 1759 } 1560 1760 } 1561 1761 … … 1608 1808 } 1609 1809 FloatLine trackLeftLine = { rowStartLine.start(), rowEndLine.start() }; 1610 gridHighlightOverlay.labels.append(buildLabel(trackSizeLabel, trackLeftLine.pointAtRelativeDistance(0.5), translucentLabelBackgroundColor, LabelArrowDirection::Left ));1810 gridHighlightOverlay.labels.append(buildLabel(trackSizeLabel, trackLeftLine.pointAtRelativeDistance(0.5), translucentLabelBackgroundColor, LabelArrowDirection::Left, LabelArrowEdgePosition::Middle)); 1611 1811 } 1612 1812 } else … … 1623 1823 } 1624 1824 } 1625 // FIXME: <webkit.org/b/221972> Layout labels can be drawn outside the viewport, and a best effort should be made to keep them in the viewport while the grid is in the viewport. 1626 if (!lineLabel.isEmpty()) 1627 gridHighlightOverlay.labels.append(buildLabel(lineLabel.toString(), gapLabelPosition, Color::white, LabelArrowDirection::Right)); 1825 1826 if (!lineLabel.isEmpty()) { 1827 auto text = lineLabel.toString(); 1828 auto arrowDirection = LabelArrowDirection::Right; 1829 auto arrowEdgePosition = LabelArrowEdgePosition::Middle; 1830 1831 if (!i) 1832 arrowEdgePosition = LabelArrowEdgePosition::Leading; 1833 else if (i == rowPositions.size() - 1) 1834 arrowEdgePosition = LabelArrowEdgePosition::Trailing; 1835 1836 auto expectedLabelSize = expectedSizeForLayoutLabel(text, arrowDirection); 1837 if (gapLabelPosition.x() - expectedLabelSize.width() + scrollPosition.x() - viewportBounds.x() < 0) 1838 arrowDirection = LabelArrowDirection::Left; 1839 1840 gridHighlightOverlay.labels.append(buildLabel(text, gapLabelPosition, Color::white, arrowDirection, arrowEdgePosition)); 1841 } 1628 1842 } 1629 1843 -
trunk/Source/WebCore/inspector/InspectorOverlay.h
r274822 r275128 53 53 namespace WebCore { 54 54 55 class FontCascade; 55 56 class FloatPoint; 56 57 class GraphicsContext; … … 72 73 Left, 73 74 Right, 75 }; 76 77 enum class LabelArrowEdgePosition { 78 None, 79 Leading, // Positioned at the left/top side of edge. 80 Middle, // Positioned at the center on the edge. 81 Trailing, // Positioned at the right/bottom side of the edge. 74 82 }; 75 83 … … 104 112 Color backgroundColor; 105 113 LabelArrowDirection arrowDirection; 114 LabelArrowEdgePosition arrowEdgePosition; 106 115 107 116 #if PLATFORM(IOS_FAMILY) … … 210 219 void clearAllGridOverlays(); 211 220 221 WEBCORE_EXPORT static FontCascade fontForLayoutLabel(); 222 WEBCORE_EXPORT static Path backgroundPathForLayoutLabel(float, float, InspectorOverlay::LabelArrowDirection, InspectorOverlay::LabelArrowEdgePosition, float arrowSize); 212 223 private: 213 224 using TimeRectPair = std::pair<MonotonicTime, FloatRect>; … … 227 238 228 239 void drawLayoutHatching(GraphicsContext&, FloatQuad); 229 void drawLayoutLabel(GraphicsContext&, String, FloatPoint, LabelArrowDirection, Color backgroundColor = Color::white, float maximumWidth = 0);240 void drawLayoutLabel(GraphicsContext&, String, FloatPoint, LabelArrowDirection, InspectorOverlay::LabelArrowEdgePosition, Color backgroundColor = Color::white, float maximumWidth = 0); 230 241 231 242 void drawGridOverlay(GraphicsContext&, const InspectorOverlay::Highlight::GridHighlightOverlay&); … … 290 301 encoder << backgroundColor; 291 302 encoder << static_cast<uint32_t>(arrowDirection); 303 encoder << static_cast<uint32_t>(arrowEdgePosition); 292 304 } 293 305 … … 307 319 label.arrowDirection = (InspectorOverlay::LabelArrowDirection)arrowDirection; 308 320 321 uint32_t arrowEdgePosition; 322 if (!decoder.decode(arrowEdgePosition)) 323 return { }; 324 label.arrowEdgePosition = (InspectorOverlay::LabelArrowEdgePosition)arrowEdgePosition; 325 309 326 return { label }; 310 327 } -
trunk/Source/WebKit/ChangeLog
r275120 r275128 1 2021-03-26 Patrick Angle <pangle@apple.com> 2 3 Web Inspector: Grid layout labels can be drawn outside the viewport 4 https://bugs.webkit.org/show_bug.cgi?id=221972 5 6 Reviewed by BJ Burg. 7 8 Add support for the new `WebCore::InspectorOverlay::LabelArrowEdgePosition` property to grid overlays on iOS. 9 10 * UIProcess/Inspector/ios/WKInspectorHighlightView.mm: 11 (createLayoutLabelLayer): 12 - Support the new `WebCore::InspectorOverlay::LabelArrowEdgePosition`. 13 - Use new helpers in WebCore::InspectorOverlay to reduce code duplication. 14 (-[WKInspectorHighlightView _createGridOverlayLayer:scale:]): 15 1 16 2021-03-26 Wenson Hsieh <wenson_hsieh@apple.com> 2 17 -
trunk/Source/WebKit/UIProcess/Inspector/ios/WKInspectorHighlightView.mm
r274822 r275128 319 319 } 320 320 321 static CALayer * createLayoutLabelLayer(String label, WebCore::FloatPoint point, WebCore::InspectorOverlay::LabelArrowDirection direction, WebCore::Color backgroundColor, WebCore::Color strokeColor, double scale, float maximumWidth = 0) 322 { 323 WebCore::FontCascadeDescription fontDescription; 324 fontDescription.setFamilies({ "system-ui" }); 325 fontDescription.setWeight(WebCore::FontSelectionValue(500)); 326 fontDescription.setComputedSize(12); 327 328 WebCore::FontCascade font(WTFMove(fontDescription), 0, 0); 329 font.update(nullptr); 321 static CALayer * createLayoutLabelLayer(String label, WebCore::FloatPoint point, WebCore::InspectorOverlay::LabelArrowDirection arrowDirection, WebCore::InspectorOverlay::LabelArrowEdgePosition arrowEdgePosition, WebCore::Color backgroundColor, WebCore::Color strokeColor, double scale, float maximumWidth = 0) 322 { 323 auto font = WebCore::InspectorOverlay::fontForLayoutLabel(); 330 324 331 325 constexpr auto padding = 4; … … 343 337 } 344 338 345 auto labelPath = adoptCF(CGPathCreateMutable());346 347 339 // Note: Implementation Difference - The textPosition is the center of text, unlike WebCore::InspectorOverlay, where the textPosition is leftmost point on the baseline of the text. 348 340 WebCore::FloatPoint textPosition; 349 350 switch (direction) { 341 switch (arrowDirection) { 351 342 case WebCore::InspectorOverlay::LabelArrowDirection::Down: 352 CGPathMoveToPoint(labelPath.get(), 0, -(textWidth / 2) - padding, -textHeight - (padding * 2) - arrowSize); 353 CGPathAddLineToPoint(labelPath.get(), 0, -(textWidth / 2) - padding, -arrowSize); 354 CGPathAddLineToPoint(labelPath.get(), 0, -arrowSize, -arrowSize); 355 CGPathAddLineToPoint(labelPath.get(), 0, 0, 0); 356 CGPathAddLineToPoint(labelPath.get(), 0, arrowSize, -arrowSize); 357 CGPathAddLineToPoint(labelPath.get(), 0, (textWidth / 2) + padding, -arrowSize); 358 CGPathAddLineToPoint(labelPath.get(), 0, (textWidth / 2) + padding, -textHeight - (padding * 2) - arrowSize); 359 textPosition = WebCore::FloatPoint(0, -(textHeight / 2) - arrowSize - padding); 343 switch (arrowEdgePosition) { 344 case WebCore::InspectorOverlay::LabelArrowEdgePosition::Leading: 345 textPosition = WebCore::FloatPoint((textWidth / 2) + padding, -(textHeight / 2) - arrowSize - padding); 346 break; 347 case WebCore::InspectorOverlay::LabelArrowEdgePosition::Middle: 348 textPosition = WebCore::FloatPoint(0, -(textHeight / 2) - arrowSize - padding); 349 break; 350 case WebCore::InspectorOverlay::LabelArrowEdgePosition::Trailing: 351 textPosition = WebCore::FloatPoint(-(textWidth / 2) - padding, -(textHeight / 2) - arrowSize - padding); 352 break; 353 case WebCore::InspectorOverlay::LabelArrowEdgePosition::None: 354 break; 355 } 360 356 break; 361 357 case WebCore::InspectorOverlay::LabelArrowDirection::Up: 362 CGPathMoveToPoint(labelPath.get(), 0, -(textWidth / 2) - padding, textHeight + (padding * 2) + arrowSize); 363 CGPathAddLineToPoint(labelPath.get(), 0, -(textWidth / 2) - padding, arrowSize); 364 CGPathAddLineToPoint(labelPath.get(), 0, -arrowSize, arrowSize); 365 CGPathAddLineToPoint(labelPath.get(), 0, 0, 0); 366 CGPathAddLineToPoint(labelPath.get(), 0, arrowSize, arrowSize); 367 CGPathAddLineToPoint(labelPath.get(), 0, (textWidth / 2) + padding, arrowSize); 368 CGPathAddLineToPoint(labelPath.get(), 0, (textWidth / 2) + padding, textHeight + (padding * 2) + arrowSize); 369 textPosition = WebCore::FloatPoint(0, (textHeight / 2) + arrowSize + padding); 358 switch (arrowEdgePosition) { 359 case WebCore::InspectorOverlay::LabelArrowEdgePosition::Leading: 360 textPosition = WebCore::FloatPoint((textWidth / 2) + padding, (textHeight / 2) + arrowSize + padding); 361 break; 362 case WebCore::InspectorOverlay::LabelArrowEdgePosition::Middle: 363 textPosition = WebCore::FloatPoint(0, (textHeight / 2) + arrowSize + padding); 364 break; 365 case WebCore::InspectorOverlay::LabelArrowEdgePosition::Trailing: 366 textPosition = WebCore::FloatPoint(-(textWidth / 2) - padding, (textHeight / 2) + arrowSize + padding); 367 break; 368 case WebCore::InspectorOverlay::LabelArrowEdgePosition::None: 369 break; 370 } 370 371 break; 371 372 case WebCore::InspectorOverlay::LabelArrowDirection::Right: 372 CGPathMoveToPoint(labelPath.get(), 0, -textWidth - (padding * 2) - arrowSize, (textHeight / 2) + padding); 373 CGPathAddLineToPoint(labelPath.get(), 0, -arrowSize, (textHeight / 2) + padding); 374 CGPathAddLineToPoint(labelPath.get(), 0, -arrowSize, arrowSize); 375 CGPathAddLineToPoint(labelPath.get(), 0, 0, 0); 376 CGPathAddLineToPoint(labelPath.get(), 0, -arrowSize, -arrowSize); 377 CGPathAddLineToPoint(labelPath.get(), 0, -arrowSize, -(textHeight / 2) - padding); 378 CGPathAddLineToPoint(labelPath.get(), 0, -textWidth - (padding * 2) - arrowSize, -(textHeight / 2) - padding); 379 textPosition = WebCore::FloatPoint(-(textWidth / 2) - arrowSize - padding, 0); 373 switch (arrowEdgePosition) { 374 case WebCore::InspectorOverlay::LabelArrowEdgePosition::Leading: 375 textPosition = WebCore::FloatPoint(-(textWidth / 2) - arrowSize - padding, (textHeight / 2) + padding); 376 break; 377 case WebCore::InspectorOverlay::LabelArrowEdgePosition::Middle: 378 textPosition = WebCore::FloatPoint(-(textWidth / 2) - arrowSize - padding, 0); 379 break; 380 case WebCore::InspectorOverlay::LabelArrowEdgePosition::Trailing: 381 textPosition = WebCore::FloatPoint(-(textWidth / 2) - arrowSize - padding, -(textHeight / 2) - padding); 382 break; 383 case WebCore::InspectorOverlay::LabelArrowEdgePosition::None: 384 break; 385 } 380 386 break; 381 387 case WebCore::InspectorOverlay::LabelArrowDirection::Left: 382 CGPathMoveToPoint(labelPath.get(), 0, textWidth + (padding * 2) + arrowSize, (textHeight / 2) + padding); 383 CGPathAddLineToPoint(labelPath.get(), 0, arrowSize, (textHeight / 2) + padding); 384 CGPathAddLineToPoint(labelPath.get(), 0, arrowSize, arrowSize); 385 CGPathAddLineToPoint(labelPath.get(), 0, 0, 0); 386 CGPathAddLineToPoint(labelPath.get(), 0, arrowSize, -arrowSize); 387 CGPathAddLineToPoint(labelPath.get(), 0, arrowSize, -(textHeight / 2) - padding); 388 CGPathAddLineToPoint(labelPath.get(), 0, textWidth + (padding * 2) + arrowSize, -(textHeight / 2) - padding); 389 textPosition = WebCore::FloatPoint((textWidth / 2) + arrowSize + padding, 0); 388 switch (arrowEdgePosition) { 389 case WebCore::InspectorOverlay::LabelArrowEdgePosition::Leading: 390 textPosition = WebCore::FloatPoint((textWidth / 2) + arrowSize + padding, (textHeight / 2) + padding); 391 break; 392 case WebCore::InspectorOverlay::LabelArrowEdgePosition::Middle: 393 textPosition = WebCore::FloatPoint((textWidth / 2) + arrowSize + padding, 0); 394 break; 395 case WebCore::InspectorOverlay::LabelArrowEdgePosition::Trailing: 396 textPosition = WebCore::FloatPoint((textWidth / 2) + arrowSize + padding, -(textHeight / 2) - padding); 397 break; 398 case WebCore::InspectorOverlay::LabelArrowEdgePosition::None: 399 break; 400 } 390 401 break; 391 402 case WebCore::InspectorOverlay::LabelArrowDirection::None: 392 CGPathMoveToPoint(labelPath.get(), 0, 0, 0);393 CGPathAddLineToPoint(labelPath.get(), 0, 0, textHeight + (padding * 2));394 CGPathAddLineToPoint(labelPath.get(), 0, textWidth + (padding * 2), textHeight + (padding * 2));395 CGPathAddLineToPoint(labelPath.get(), 0, textWidth + (padding * 2), 0);396 403 textPosition = WebCore::FloatPoint(padding + (textWidth / 2), padding + (textHeight / 2)); 397 404 break; 398 405 } 399 406 400 CGPathCloseSubpath(labelPath.get());401 402 407 CALayer *layer = [CALayer layer]; 403 408 409 #if USE(CG) 410 // WebCore::Path::PlatformPathPtr is only a CGPath* when `USE(CG)` is true. 411 auto labelPath = WebCore::InspectorOverlay::backgroundPathForLayoutLabel(textWidth + (padding * 2), textHeight + (padding * 2), arrowDirection, arrowEdgePosition, arrowSize); 412 CGPath* platformLabelPath = labelPath.ensurePlatformPath(); 413 404 414 CAShapeLayer *labelPathLayer = [CAShapeLayer layer]; 405 labelPathLayer.path = labelPath.get();415 labelPathLayer.path = platformLabelPath; 406 416 labelPathLayer.fillColor = cachedCGColor(backgroundColor); 407 417 labelPathLayer.strokeColor = cachedCGColor(strokeColor); 408 418 labelPathLayer.position = CGPointMake(point.x(), point.y()); 409 419 [layer addSublayer:labelPathLayer]; 420 #endif 410 421 411 422 CATextLayer *textLayer = [CATextLayer layer]; … … 454 465 455 466 for (auto area : overlay.areas) 456 [layer addSublayer:createLayoutLabelLayer(area.name, area.quad.p1(), WebCore::InspectorOverlay::LabelArrowDirection::None, translucentLabelBackgroundColor, overlay.color, scale, area.quad.boundingBox().width())];467 [layer addSublayer:createLayoutLabelLayer(area.name, area.quad.p1(), WebCore::InspectorOverlay::LabelArrowDirection::None, WebCore::InspectorOverlay::LabelArrowEdgePosition::None, translucentLabelBackgroundColor, overlay.color, scale, area.quad.boundingBox().width())]; 457 468 458 469 for (auto label : overlay.labels) 459 [layer addSublayer:createLayoutLabelLayer(label.text, label.location, label.arrowDirection, label. backgroundColor, overlay.color, scale)];470 [layer addSublayer:createLayoutLabelLayer(label.text, label.location, label.arrowDirection, label.arrowEdgePosition, label.backgroundColor, overlay.color, scale)]; 460 471 461 472 return layer;
Note: See TracChangeset
for help on using the changeset viewer.