Changeset 197600 in webkit
- Timestamp:
- Mar 4, 2016, 4:57:19 PM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
-
ChangeLog (modified) (1 diff)
-
rendering/RenderThemeIOS.h (modified) (2 diffs)
-
rendering/RenderThemeIOS.mm (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r197599 r197600 1 2016-03-04 Tim Horton <timothy_horton@apple.com> 2 3 Begin implementing <attachment> painting on iOS 4 https://bugs.webkit.org/show_bug.cgi?id=155046 5 <rdar://problem/24805991> 6 7 Reviewed by Enrica Casucci. 8 9 No new tests; there are existing tests that I will unskip and rebaseline 10 in the near future. 11 12 * rendering/RenderThemeIOS.h: 13 * rendering/RenderThemeIOS.mm: 14 (WebCore::AttachmentInfo::addLine): 15 (WebCore::AttachmentInfo::buildTitleLines): 16 (WebCore::AttachmentInfo::buildSingleLine): 17 (WebCore::getAttachmentProgress): 18 (WebCore::iconForAttachment): 19 (WebCore::AttachmentInfo::AttachmentInfo): 20 (WebCore::RenderThemeIOS::attachmentIntrinsicSize): 21 (WebCore::RenderThemeIOS::attachmentBaseline): 22 (WebCore::paintAttachmentIcon): 23 (WebCore::paintAttachmentText): 24 (WebCore::paintAttachmentProgress): 25 (WebCore::paintAttachmentBorder): 26 (WebCore::RenderThemeIOS::paintAttachment): 27 There are still a few missing pieces, but get <attachment> painting a bit on iOS. 28 We will paint an icon, action, title, and subtitle - in that order - depending on what we have. 29 The content is vertically and horizontally centered. 30 1 31 2016-03-04 Gavin Barraclough <barraclough@apple.com> 2 32 -
trunk/Source/WebCore/rendering/RenderThemeIOS.h
r197563 r197600 35 35 class RenderStyle; 36 36 class GraphicsContext; 37 37 struct AttachmentLayout; 38 38 39 class RenderThemeIOS final : public RenderTheme { 39 40 public: … … 111 112 #endif 112 113 114 #if ENABLE(ATTACHMENT_ELEMENT) 115 LayoutSize attachmentIntrinsicSize(const RenderAttachment&) const override; 116 int attachmentBaseline(const RenderAttachment&) const override; 117 bool paintAttachment(const RenderObject&, const PaintInfo&, const IntRect&) override; 118 #endif 119 113 120 private: 114 121 RenderThemeIOS(); -
trunk/Source/WebCore/rendering/RenderThemeIOS.mm
r197563 r197600 28 28 #if PLATFORM(IOS) 29 29 30 #import "BitmapImage.h" 30 31 #import "CSSPrimitiveValue.h" 31 32 #import "CSSToLengthConversionData.h" … … 34 35 #import "DateComponents.h" 35 36 #import "Document.h" 37 #import "File.h" 36 38 #import "FloatRoundedRect.h" 37 39 #import "FontCache.h" 38 40 #import "FontCascade.h" 39 41 #import "Frame.h" 42 #import "FrameSelection.h" 40 43 #import "FrameView.h" 44 #import "GeometryUtilities.h" 41 45 #import "Gradient.h" 42 46 #import "GraphicsContext.h" 43 47 #import "GraphicsContextCG.h" 48 #import "HTMLAttachmentElement.h" 44 49 #import "HTMLInputElement.h" 45 50 #import "HTMLNames.h" … … 50 55 #import "Page.h" 51 56 #import "PaintInfo.h" 57 #import "PathUtilities.h" 52 58 #import "PlatformLocale.h" 59 #import "RenderAttachment.h" 53 60 #import "RenderObject.h" 54 61 #import "RenderProgress.h" … … 58 65 #import "SoftLinking.h" 59 66 #import "UIKitSPI.h" 67 #import "UTIUtilities.h" 60 68 #import "UserAgentScripts.h" 61 69 #import "UserAgentStyleSheets.h" … … 67 75 #import <wtf/StdLibExtras.h> 68 76 77 SOFT_LINK_FRAMEWORK(MobileCoreServices) 78 SOFT_LINK_CLASS(MobileCoreServices, LSDocumentProxy) 79 69 80 SOFT_LINK_FRAMEWORK(UIKit) 70 81 SOFT_LINK_CLASS(UIKit, UIApplication) 71 82 SOFT_LINK_CLASS(UIKit, UIColor) 83 SOFT_LINK_CLASS(UIKit, UIDocumentInteractionController) 84 SOFT_LINK_CLASS(UIKit, UIFont) 85 SOFT_LINK_CLASS(UIKit, UIImage) 72 86 SOFT_LINK_CONSTANT(UIKit, UIContentSizeCategoryDidChangeNotification, CFStringRef) 87 SOFT_LINK_CONSTANT(UIKit, UIFontTextStyleFootnote, NSString *) 88 SOFT_LINK_CONSTANT(UIKit, UIFontTextStyleCaption1, NSString *) 73 89 #define UIContentSizeCategoryDidChangeNotification getUIContentSizeCategoryDidChangeNotification() 74 90 … … 80 96 81 97 namespace WebCore { 98 99 using namespace HTMLNames; 82 100 83 101 const float ControlBaseHeight = 20; … … 1322 1340 } 1323 1341 1324 } 1342 #if ENABLE(ATTACHMENT_ELEMENT) 1343 1344 const CGSize attachmentSize = { 160, 119 }; 1345 1346 const CGFloat attachmentBorderRadius = 16; 1347 static Color attachmentBorderColor() { return Color(204, 204, 204); } 1348 1349 const CGFloat attachmentProgressSize = 36; 1350 const CGFloat attachmentIconSize = 48; 1351 1352 const CGFloat attachmentItemMargin = 8; 1353 1354 const CGFloat attachmentTitleMaximumWidth = 140; 1355 const CFIndex attachmentTitleMaximumLineCount = 2; 1356 1357 // FIXME: Should be emphasized. 1358 static UIFont *attachmentActionFont() { return [getUIFontClass() preferredFontForTextStyle:getUIFontTextStyleFootnote()]; } 1359 static UIColor *attachmentActionColor() { return [getUIColorClass() systemBlueColor]; } 1360 1361 static UIFont *attachmentTitleFont() { return [getUIFontClass() preferredFontForTextStyle:getUIFontTextStyleCaption1()]; } 1362 static UIColor *attachmentTitleColor() { return [getUIColorClass() systemGrayColor]; } 1363 1364 static UIFont *attachmentSubtitleFont() { return [getUIFontClass() preferredFontForTextStyle:getUIFontTextStyleCaption1()]; } 1365 static UIColor *attachmentSubtitleColor() { return [getUIColorClass() systemGrayColor]; } 1366 1367 struct AttachmentInfo { 1368 explicit AttachmentInfo(const RenderAttachment&); 1369 1370 FloatRect iconRect; 1371 FloatRect attachmentRect; 1372 FloatRect progressRect; 1373 1374 BOOL hasProgress { NO }; 1375 float progress; 1376 1377 RetainPtr<UIImage> icon; 1378 1379 int baseline { 0 }; 1380 1381 struct LabelLine { 1382 FloatRect rect; 1383 RetainPtr<CTLineRef> line; 1384 }; 1385 Vector<LabelLine> lines; 1386 1387 CGFloat contentYOrigin { 0 }; 1388 1389 private: 1390 void buildTitleLines(const RenderAttachment&); 1391 void buildSingleLine(const String&, UIFont *, UIColor *); 1392 1393 void addLine(CTLineRef); 1394 }; 1395 1396 void AttachmentInfo::addLine(CTLineRef line) 1397 { 1398 CGRect lineBounds = CTLineGetBoundsWithOptions(line, kCTLineBoundsExcludeTypographicLeading); 1399 CGFloat trailingWhitespaceWidth = CTLineGetTrailingWhitespaceWidth(line); 1400 CGFloat lineWidthIgnoringTrailingWhitespace = lineBounds.size.width - trailingWhitespaceWidth; 1401 CGFloat lineHeight = CGCeiling(lineBounds.size.height + lineBounds.origin.y); 1402 1403 CGFloat xOffset = (attachmentRect.width() / 2) - (lineWidthIgnoringTrailingWhitespace / 2); 1404 LabelLine labelLine; 1405 labelLine.line = line; 1406 labelLine.rect = FloatRect(xOffset, 0, lineWidthIgnoringTrailingWhitespace, lineHeight); 1407 1408 lines.append(labelLine); 1409 } 1410 1411 void AttachmentInfo::buildTitleLines(const RenderAttachment& attachment) 1412 { 1413 RetainPtr<UIFont> font = attachmentTitleFont(); 1414 1415 String title = attachment.attachmentElement().attachmentTitle(); 1416 if (title.isEmpty()) 1417 return; 1418 1419 NSDictionary *textAttributes = @{ 1420 (id)kCTFontAttributeName: font.get(), 1421 (id)kCTForegroundColorAttributeName: attachmentTitleColor() 1422 }; 1423 RetainPtr<NSAttributedString> attributedTitle = adoptNS([[NSAttributedString alloc] initWithString:title attributes:textAttributes]); 1424 RetainPtr<CTFramesetterRef> titleFramesetter = adoptCF(CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributedTitle.get())); 1425 1426 CFRange fitRange; 1427 CGSize titleTextSize = CTFramesetterSuggestFrameSizeWithConstraints(titleFramesetter.get(), CFRangeMake(0, 0), nullptr, CGSizeMake(attachmentTitleMaximumWidth, CGFLOAT_MAX), &fitRange); 1428 1429 RetainPtr<CGPathRef> titlePath = adoptCF(CGPathCreateWithRect(CGRectMake(0, 0, titleTextSize.width, titleTextSize.height), nullptr)); 1430 RetainPtr<CTFrameRef> titleFrame = adoptCF(CTFramesetterCreateFrame(titleFramesetter.get(), fitRange, titlePath.get(), nullptr)); 1431 1432 CFArrayRef ctLines = CTFrameGetLines(titleFrame.get()); 1433 CFIndex lineCount = CFArrayGetCount(ctLines); 1434 if (!lineCount) 1435 return; 1436 1437 // Lay out and record the first (attachmentTitleMaximumLineCount - 1) lines. 1438 CFIndex lineIndex = 0; 1439 for (; lineIndex < std::min(attachmentTitleMaximumLineCount - 1, lineCount); ++lineIndex) { 1440 CTLineRef line = (CTLineRef)CFArrayGetValueAtIndex(ctLines, lineIndex); 1441 addLine(line); 1442 } 1443 1444 if (lineIndex == lineCount) 1445 return; 1446 1447 // We had text that didn't fit in the first (attachmentTitleMaximumLineCount - 1) lines. 1448 // Combine it into one last line, and center-truncate it. 1449 CTLineRef firstRemainingLine = (CTLineRef)CFArrayGetValueAtIndex(ctLines, lineIndex); 1450 CFIndex remainingRangeStart = CTLineGetStringRange(firstRemainingLine).location; 1451 NSRange remainingRange = NSMakeRange(remainingRangeStart, [attributedTitle length] - remainingRangeStart); 1452 NSAttributedString *remainingString = [attributedTitle attributedSubstringFromRange:remainingRange]; 1453 RetainPtr<CTLineRef> remainingLine = adoptCF(CTLineCreateWithAttributedString((CFAttributedStringRef)remainingString)); 1454 RetainPtr<NSAttributedString> ellipsisString = adoptNS([[NSAttributedString alloc] initWithString:@"\u2026" attributes:textAttributes]); 1455 RetainPtr<CTLineRef> ellipsisLine = adoptCF(CTLineCreateWithAttributedString((CFAttributedStringRef)ellipsisString.get())); 1456 RetainPtr<CTLineRef> truncatedLine = adoptCF(CTLineCreateTruncatedLine(remainingLine.get(), attachmentTitleMaximumWidth, kCTLineTruncationMiddle, ellipsisLine.get())); 1457 1458 if (!truncatedLine) 1459 truncatedLine = remainingLine; 1460 1461 addLine(truncatedLine.get()); 1462 } 1463 1464 void AttachmentInfo::buildSingleLine(const String& text, UIFont *font, UIColor *color) 1465 { 1466 if (text.isEmpty()) 1467 return; 1468 1469 NSDictionary *textAttributes = @{ 1470 (id)kCTFontAttributeName: font, 1471 (id)kCTForegroundColorAttributeName: color 1472 }; 1473 RetainPtr<NSAttributedString> attributedText = adoptNS([[NSAttributedString alloc] initWithString:text attributes:textAttributes]); 1474 1475 addLine(adoptCF(CTLineCreateWithAttributedString((CFAttributedStringRef)attributedText.get())).get()); 1476 } 1477 1478 static BOOL getAttachmentProgress(const RenderAttachment& attachment, float& progress) 1479 { 1480 String progressString = attachment.attachmentElement().fastGetAttribute(progressAttr); 1481 if (progressString.isEmpty()) 1482 return NO; 1483 bool validProgress; 1484 progress = progressString.toFloat(&validProgress); 1485 return validProgress; 1486 } 1487 1488 static RetainPtr<UIImage> iconForAttachment(const RenderAttachment& attachment, FloatSize& size) 1489 { 1490 String MIMEType = attachment.attachmentElement().attachmentType(); 1491 1492 String fileName; 1493 if (File* file = attachment.attachmentElement().file()) 1494 fileName = file->name(); 1495 1496 if (fileName.isEmpty()) 1497 fileName = attachment.attachmentElement().attachmentTitle(); 1498 1499 RetainPtr<UIImage> result; 1500 1501 RetainPtr<UIDocumentInteractionController> documentInteractionController = adoptNS([[getUIDocumentInteractionControllerClass() alloc] init]); 1502 [documentInteractionController setName:fileName]; 1503 [documentInteractionController setUTI:static_cast<NSString *>(mimeTypeFromUTITree(MIMEType.createCFString().get()).get())]; 1504 1505 NSArray *icons = [documentInteractionController icons]; 1506 if (!icons.count) 1507 return nil; 1508 1509 result = icons.lastObject; 1510 1511 BOOL useHeightForClosestMatch = [result size].height > [result size].width; 1512 CGFloat bestMatchRatio = -1; 1513 1514 for (UIImage *icon in icons) { 1515 CGFloat iconSize = useHeightForClosestMatch ? icon.size.height : icon.size.width; 1516 1517 CGFloat matchRatio = (attachmentIconSize / iconSize) - 1.0f; 1518 if (matchRatio < 0.3f) { 1519 matchRatio = CGFAbs(matchRatio); 1520 if ((bestMatchRatio == -1) || (matchRatio < bestMatchRatio)) { 1521 result = icon; 1522 bestMatchRatio = matchRatio; 1523 } 1524 } 1525 } 1526 1527 CGFloat iconAspect = [result size].width / [result size].height; 1528 size = largestRectWithAspectRatioInsideRect(iconAspect, FloatRect(0, 0, attachmentIconSize, attachmentIconSize)).size(); 1529 1530 return result; 1531 } 1532 1533 AttachmentInfo::AttachmentInfo(const RenderAttachment& attachment) 1534 { 1535 attachmentRect = FloatRect(0, 0, attachmentSize.width, attachmentSize.height); 1536 1537 hasProgress = getAttachmentProgress(attachment, progress); 1538 1539 String action = attachment.attachmentElement().fastGetAttribute(actionAttr); 1540 String subtitle = attachment.attachmentElement().fastGetAttribute(subtitleAttr); 1541 1542 CGFloat yOffset = 0; 1543 1544 if (hasProgress) { 1545 progressRect = FloatRect((attachmentRect.width() / 2) - (attachmentProgressSize / 2), 0, attachmentProgressSize, attachmentProgressSize); 1546 yOffset += attachmentProgressSize + attachmentItemMargin; 1547 } 1548 1549 if (action.isEmpty() && !hasProgress) { 1550 FloatSize iconSize; 1551 icon = iconForAttachment(attachment, iconSize); 1552 if (icon) { 1553 iconRect = FloatRect(FloatPoint((attachmentRect.width() / 2) - (iconSize.width() / 2), 0), iconSize); 1554 yOffset += iconRect.height() + attachmentItemMargin; 1555 } 1556 } else 1557 buildSingleLine(action, attachmentActionFont(), attachmentActionColor()); 1558 1559 buildTitleLines(attachment); 1560 buildSingleLine(subtitle, attachmentSubtitleFont(), attachmentSubtitleColor()); 1561 1562 if (!lines.isEmpty()) { 1563 for (auto& line : lines) { 1564 line.rect.setY(yOffset); 1565 yOffset += line.rect.height() + attachmentItemMargin; 1566 } 1567 } 1568 1569 contentYOrigin = (attachmentRect.height() / 2) - (yOffset / 2); 1570 } 1571 1572 LayoutSize RenderThemeIOS::attachmentIntrinsicSize(const RenderAttachment&) const 1573 { 1574 return LayoutSize(FloatSize(attachmentSize)); 1575 } 1576 1577 int RenderThemeIOS::attachmentBaseline(const RenderAttachment& attachment) const 1578 { 1579 AttachmentInfo info(attachment); 1580 return info.baseline; 1581 } 1582 1583 static void paintAttachmentIcon(GraphicsContext& context, AttachmentInfo& info) 1584 { 1585 if (!info.icon) 1586 return; 1587 1588 RefPtr<Image> iconImage = BitmapImage::create([info.icon CGImage]); 1589 if (!iconImage) 1590 return; 1591 1592 context.drawImage(*iconImage, info.iconRect); 1593 } 1594 1595 1596 static void paintAttachmentText(GraphicsContext& context, AttachmentInfo& info) 1597 { 1598 for (const auto& line : info.lines) { 1599 GraphicsContextStateSaver saver(context); 1600 1601 context.translate(toFloatSize(line.rect.minXMaxYCorner())); 1602 context.scale(FloatSize(1, -1)); 1603 1604 CGContextSetTextMatrix(context.platformContext(), CGAffineTransformIdentity); 1605 CTLineDraw(line.line.get(), context.platformContext()); 1606 } 1607 } 1608 1609 static void paintAttachmentProgress(GraphicsContext& context, AttachmentInfo& info) 1610 { 1611 GraphicsContextStateSaver saver(context); 1612 1613 // FIXME: Implement progress indicator. 1614 context.fillRect(info.progressRect, Color(0, 255, 0)); 1615 } 1616 1617 static void paintAttachmentBorder(GraphicsContext& context, AttachmentInfo& info) 1618 { 1619 Path borderPath; 1620 borderPath.addRoundedRect(info.attachmentRect, FloatSize(attachmentBorderRadius, attachmentBorderRadius)); 1621 context.setStrokeColor(attachmentBorderColor()); 1622 context.setStrokeThickness(1); 1623 context.strokePath(borderPath); 1624 } 1625 1626 bool RenderThemeIOS::paintAttachment(const RenderObject& renderer, const PaintInfo& paintInfo, const IntRect& paintRect) 1627 { 1628 if (!is<RenderAttachment>(renderer)) 1629 return false; 1630 1631 const RenderAttachment& attachment = downcast<RenderAttachment>(renderer); 1632 1633 AttachmentInfo info(attachment); 1634 1635 GraphicsContext& context = paintInfo.context(); 1636 GraphicsContextStateSaver saver(context); 1637 1638 context.translate(toFloatSize(paintRect.location())); 1639 1640 paintAttachmentBorder(context, info); 1641 1642 context.translate(FloatSize(0, info.contentYOrigin)); 1643 1644 if (info.hasProgress) 1645 paintAttachmentProgress(context, info); 1646 else if (info.icon) 1647 paintAttachmentIcon(context, info); 1648 1649 paintAttachmentText(context, info); 1650 1651 return true; 1652 } 1653 1654 #endif // ENABLE(ATTACHMENT_ELEMENT) 1655 1656 } // namespace WebCore 1325 1657 1326 1658 #endif //PLATFORM(IOS)
Note:
See TracChangeset
for help on using the changeset viewer.