Skip to content

Commit d43247c

Browse files
committed
[CSS Fonts] Implement ic-height for font-size-adjust
https://bugs.webkit.org/show_bug.cgi?id=264064 Reviewed by NOBODY (OOPS!). This change brings the ic-height metric support for font-size-adjust [1] into ports using OpenType. As initializing glyphs' vertical data is expensive, we defer it until the vertical data is requested. If a used font does not provide height of the cjk water glyph, we use its width as a fallback [2] because the glyph usually has the same width and height. [1] https://www.w3.org/TR/css-fonts-5/#valdef-font-size-adjust-ic-height [2] w3c/csswg-drafts#8792 Test: imported/w3c/web-platform-tests/css/css-fonts/font-size-adjust-ic-height.html * LayoutTests/imported/w3c/web-platform-tests/css/css-fonts/font-size-adjust-ic-height-expected.html: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-fonts/font-size-adjust-ic-height-ref.html: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-fonts/font-size-adjust-ic-height.html: Added. * Source/WebCore/platform/graphics/Font.cpp: (WebCore::m_shouldNotBeUsedForArabic): (WebCore::Font::platformGlyphInit): (WebCore::Font::platformGlyphVerticalDataInit): (WebCore::Font::heightForGlyph const): * Source/WebCore/platform/graphics/Font.h: (WebCore::Font::widthForGlyph const): * Source/WebCore/platform/graphics/FontMetrics.h: (WebCore::FontMetrics::ideogramHeight const): (WebCore::FontMetrics::reset): * Source/WebCore/platform/graphics/FontSizeAdjust.h: (WebCore::FontSizeAdjust::resolve const): * Source/WebCore/rendering/RenderFileUploadControl.cpp: (WebCore::RenderFileUploadControl::paintControl): * Source/WebCore/style/StyleFontSizeFunctions.cpp: (WebCore::Style::adjustedFontSize):
1 parent e209781 commit d43247c

File tree

9 files changed

+148
-16
lines changed

9 files changed

+148
-16
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
>
2+
<meta charset="UTF-8">
3+
<title>font-size-adjust with the ic-height metrictitle>
4+
<link rel="author" title="ChangSeok Oh" href="mailto:[email protected]" />
5+
<style>
6+
@font-face {
7+
font-family: IcTestFullWidth;
8+
src: url(../css-values/resources/IcTestFullWidth.woff2);
9+
}
10+
div {
11+
font-family: IcTestFullWidth;
12+
background: green;
13+
color: green;
14+
writing-mode: vertical-rl;
15+
text-orientation: upright;
16+
}
17+
.valueRef {
18+
font-size: 200px;
19+
}
20+
.fromFontRef {
21+
font-size: 100px;
22+
}
23+
style>
24+
<div class="valueRef">div>
25+
<div class="fromFontRef">div>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
>
2+
<meta charset="UTF-8">
3+
<title>font-size-adjust with the ic-height metrictitle>
4+
<link rel="author" title="ChangSeok Oh" href="mailto:[email protected]" />
5+
<style>
6+
@font-face {
7+
font-family: IcTestFullWidth;
8+
src: url(../css-values/resources/IcTestFullWidth.woff2);
9+
}
10+
div {
11+
font-family: IcTestFullWidth;
12+
background: green;
13+
color: green;
14+
writing-mode: vertical-rl;
15+
text-orientation: upright;
16+
}
17+
.valueRef {
18+
font-size: 200px;
19+
}
20+
.fromFontRef {
21+
font-size: 100px;
22+
}
23+
style>
24+
<div class="valueRef">div>
25+
<div class="fromFontRef">div>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
>
2+
<meta charset="UTF-8">
3+
<title>font-size-adjust with the ic-height metrictitle>
4+
<link rel="author" title="ChangSeok Oh" href="mailto:[email protected]" />
5+
<link rel="help" href="https://www.w3.org/TR/css-fonts-5/#valdef-font-size-adjust-ic-height" />
6+
<link rel="match" href="font-size-adjust-ic-height-ref.html" />
7+
<meta name="assert" content="Test checks whether font-size-adjust with the ic-height metric adjusts font size.">
8+
<style>
9+
@font-face {
10+
font-family: IcTestFullWidth;
11+
src: url(../css-values/resources/IcTestFullWidth.woff2);
12+
}
13+
div {
14+
font-family: IcTestFullWidth;
15+
font-size: 100px;
16+
background: green;
17+
color: green;
18+
writing-mode: vertical-rl;
19+
text-orientation: upright;
20+
}
21+
.value {
22+
/* The IcTestFullWidth font has an aspect value of 1.0 for ic-height.
23+
Therefore, an ic-height 2.0 means a 200% scaling up. */
24+
font-size-adjust: ic-height 2.0;
25+
}
26+
.fromFont {
27+
/* Likewise, ic-height from-font means 100% of the specified font size. */
28+
font-size-adjust: ic-height from-font;
29+
}
30+
style>
31+
<div class="value">div>
32+
<div class="fromFont">div>

Source/WebCore/platform/graphics/Font.cpp

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*
22
* Copyright (C) 2005-2023 Apple Inc. All rights reserved.
33
* Copyright (C) 2006 Alexey Proskuryakov
4+
* Copyright (C) 2023 ChangSeok Oh
45
*
56
* Redistribution and use in source and binary forms, with or without
67
* modification, are permitted provided that the following conditions
@@ -89,12 +90,8 @@ Font::Font(const FontPlatformData& platformData, Origin origin, IsInterstitial i
8990
platformInit();
9091
platformGlyphInit();
9192
platformCharWidthInit();
92-
#if ENABLE(OPENTYPE_VERTICAL)
93-
if (platformData.orientation() == FontOrientation::Vertical && orientationFallback == IsOrientationFallback::No) {
94-
m_verticalData = FontCache::forCurrentThread().verticalData(platformData);
95-
m_hasVerticalGlyphs = m_verticalData.get() && m_verticalData->hasVerticalMetrics();
96-
}
97-
#endif
93+
if (platformData.orientation() == FontOrientation::Vertical && orientationFallback == IsOrientationFallback::No)
94+
platformGlyphVerticalDataInit();
9895
}
9996

10097
// Estimates of avgCharWidth and maxCharWidth for platforms that don't support accessing these values from the font.
@@ -158,6 +155,19 @@ void Font::platformGlyphInit()
158155
if (auto* page = glyphPage(GlyphPage::pageNumberForCodePoint(cjkWater))) {
159156
auto glyph = page->glyphDataForCharacter(cjkWater).glyph;
160157
m_fontMetrics.setIdeogramWidth(widthForGlyph(glyph));
158+
m_fontMetrics.setIdeogramHeightCallback([this, weakThis = WeakPtr { *this }, glyph] {
159+
if (!weakThis)
160+
return 0.0f;
161+
162+
platformGlyphVerticalDataInit();
163+
164+
auto advanceHeight = heightForGlyph(glyph);
165+
// FIXME: Vertical glyph data is often missing in fonts, but a fallback
166+
// behavior is not standardized yet. Gecko uses average character width instead,
167+
// so we implement it until a standard fallback is defined.
168+
// See https://github.com/w3c/csswg-drafts/issues/8792
169+
return advanceHeight.has_value() ? advanceHeight.value() : platformWidthForGlyph(glyph);
170+
});
161171
} else
162172
m_fontMetrics.setIdeogramWidth(platformData().size());
163173

@@ -168,6 +178,18 @@ void Font::platformGlyphInit()
168178
determinePitch();
169179
}
170180

181+
void Font::platformGlyphVerticalDataInit()
182+
{
183+
#if ENABLE(OPENTYPE_VERTICAL)
184+
// Initializing vertical data is expensive. We limit it if only necessary.
185+
if (m_verticalData)
186+
return;
187+
188+
m_verticalData = FontCache::forCurrentThread().verticalData(m_platformData);
189+
m_hasVerticalGlyphs = m_verticalData.get() && m_verticalData->hasVerticalMetrics();
190+
#endif
191+
}
192+
171193
Font::~Font()
172194
{
173195
SystemFallbackFontCache::forCurrentThread().remove(this);
@@ -617,6 +639,16 @@ bool Font::canRenderCombiningCharacterSequence(StringView stringView) const
617639
return true;
618640
}
619641

642+
std::optional<float> Font::heightForGlyph(Glyph glyph) const
643+
{
644+
#if ENABLE(OPENTYPE_VERTICAL)
645+
if (m_verticalData)
646+
return m_verticalData->advanceHeight(this, glyph);
647+
#endif
648+
UNUSED_PARAM(glyph);
649+
return std::nullopt;
650+
}
651+
620652
Path Font::pathForGlyph(Glyph glyph) const
621653
{
622654
if (m_glyphPathMap) {

Source/WebCore/platform/graphics/Font.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ class Font : public RefCounted, public CanMakeWeakPtr, public CanMak
156156
Exclude
157157
};
158158
float widthForGlyph(Glyph, SyntheticBoldInclusion = SyntheticBoldInclusion::Incorporate) const;
159+
std::optional<float> heightForGlyph(Glyph) const;
159160

160161
Path pathForGlyph(Glyph) const;
161162

@@ -237,6 +238,7 @@ class Font : public RefCounted, public CanMakeWeakPtr, public CanMak
237238

238239
void platformInit();
239240
void platformGlyphInit();
241+
void platformGlyphVerticalDataInit();
240242
void platformCharWidthInit();
241243
void platformDestroy();
242244

@@ -406,11 +408,10 @@ ALWAYS_INLINE float Font::widthForGlyph(Glyph glyph, SyntheticBoldInclusion Synt
406408
if (width != cGlyphSizeUnknown)
407409
return width + (SyntheticBoldInclusion == SyntheticBoldInclusion::Incorporate ? syntheticBoldOffset() : 0);
408410

409-
#if ENABLE(OPENTYPE_VERTICAL)
410-
if (m_verticalData)
411-
width = m_verticalData->advanceHeight(this, glyph);
412-
else
413-
#endif
411+
if (m_platformData.orientation() == FontOrientation::Vertical && !isTextOrientationFallback()) {
412+
auto height = heightForGlyph(glyph);
413+
width = height.has_value() ? height.value() : platformWidthForGlyph(glyph);
414+
} else
414415
width = platformWidthForGlyph(glyph);
415416

416417
m_glyphToWidthMap.setMetricsForGlyph(glyph, width);

Source/WebCore/platform/graphics/FontMetrics.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "FontBaseline.h"
2424
#include <optional>
25+
#include <wtf/Function.h>
2526
#include <wtf/MathExtras.h>
2627

2728
namespace WebCore {
@@ -30,6 +31,8 @@ class FontMetrics {
3031
public:
3132
static const unsigned defaultUnitsPerEm = 1000;
3233

34+
using IdeogramHeightCallback = Function<float()>;
35+
3336
unsigned unitsPerEm() const { return m_unitsPerEm; }
3437
void setUnitsPerEm(unsigned unitsPerEm) { m_unitsPerEm = unitsPerEm; }
3538

@@ -126,6 +129,14 @@ class FontMetrics {
126129
float ideogramWidth() const { return m_ideogramWidth; }
127130
void setIdeogramWidth(float ideogramWidth) { m_ideogramWidth = ideogramWidth; }
128131

132+
float ideogramHeight() const
133+
{
134+
if (!m_ideogramHeight && m_ideogramHeightCallback)
135+
m_ideogramHeight = m_ideogramHeightCallback();
136+
return m_ideogramHeight.has_value() ? m_ideogramHeight.value() : 0;
137+
};
138+
void setIdeogramHeightCallback(IdeogramHeightCallback&& callback) { m_ideogramHeightCallback = WTFMove(callback); }
139+
129140
float underlinePosition() const { return m_underlinePosition; }
130141
void setUnderlinePosition(float underlinePosition) { m_underlinePosition = underlinePosition; }
131142

@@ -151,6 +162,7 @@ class FontMetrics {
151162
m_xHeight = 0;
152163
m_zeroWidth = std::nullopt;
153164
m_ideogramWidth = 0;
165+
m_ideogramHeight = std::nullopt;
154166
m_underlinePosition = 0;
155167
m_underlineThickness = 0;
156168
}
@@ -175,6 +187,9 @@ class FontMetrics {
175187
float m_xHeight { 0 };
176188
float m_underlinePosition { 0 };
177189
float m_underlineThickness { 0 };
190+
191+
mutable std::optional<float> m_ideogramHeight;
192+
IdeogramHeightCallback m_ideogramHeightCallback;
178193
};
179194

180195
static inline float scaleEmToUnits(float x, unsigned unitsPerEm)

Source/WebCore/platform/graphics/FontSizeAdjust.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,14 @@ struct FontSizeAdjust {
5656
if (fontMetrics.zeroWidth())
5757
metricValue = fontMetrics.zeroWidth();
5858
break;
59-
// FIXME: Are ic-height and ic-width the same? Gecko treats them the same.
6059
case FontSizeAdjust::Metric::IcWidth:
61-
case FontSizeAdjust::Metric::IcHeight:
6260
if (fontMetrics.ideogramWidth() > 0)
6361
metricValue = fontMetrics.ideogramWidth();
6462
break;
63+
case FontSizeAdjust::Metric::IcHeight:
64+
if (fontMetrics.ideogramHeight() > 0)
65+
metricValue = fontMetrics.ideogramHeight();
66+
break;
6567
case FontSizeAdjust::Metric::ExHeight:
6668
default:
6769
if (fontMetrics.hasXHeight())

Source/WebCore/rendering/RenderFileUploadControl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ void RenderFileUploadControl::paintControl(PaintInfo& paintInfo, const LayoutPoi
185185
textVisualRect.setLocation(buttonTextRenderer->localToContainerPoint(textVisualRect.location(), this));
186186
textVisualRect.moveBy(roundPointToDevicePixels(paintOffset, document().deviceScaleFactor()));
187187

188-
auto metrics = textBox->style().fontCascade().metricsOfPrimaryFont();
188+
const auto& metrics = textBox->style().fontCascade().metricsOfPrimaryFont();
189189

190190
if (!isHorizontalWritingMode) {
191191
if (isFlippedBlocksWritingMode)

Source/WebCore/style/StyleFontSizeFunctions.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,10 +202,10 @@ float adjustedFontSize(float size, const FontSizeAdjust& sizeAdjust, const FontM
202202
return metrics.hasCapHeight() ? adjustedFontSize(size, *sizeAdjust.value, metrics.floatCapHeight()) : size;
203203
case FontSizeAdjust::Metric::ChWidth:
204204
return metrics.zeroWidth() ? adjustedFontSize(size, *sizeAdjust.value, *metrics.zeroWidth()) : size;
205-
// FIXME: Are ic-height and ic-width the same? Gecko treats them the same.
206205
case FontSizeAdjust::Metric::IcWidth:
207-
case FontSizeAdjust::Metric::IcHeight:
208206
return metrics.ideogramWidth() > 0 ? adjustedFontSize(size, *sizeAdjust.value, metrics.ideogramWidth()) : size;
207+
case FontSizeAdjust::Metric::IcHeight:
208+
return metrics.ideogramHeight() > 0 ? adjustedFontSize(size, *sizeAdjust.value, metrics.ideogramHeight()) : size;
209209
case FontSizeAdjust::Metric::ExHeight:
210210
default:
211211
return metrics.hasXHeight() ? adjustedFontSize(size, *sizeAdjust.value, metrics.xHeight()) : size;

0 commit comments

Comments
 (0)