Skip to content

Commit

Permalink
Adding experimental size adjust based option (vercel#41009)
Browse files Browse the repository at this point in the history
Adding experimental `adjustFontFallbacksWithSizeAdjust` option
  • Loading branch information
janicklas-ralph authored and BowlingX committed Oct 5, 2022
1 parent 0718c91 commit 3da9c8a
Show file tree
Hide file tree
Showing 14 changed files with 9,854 additions and 9,258 deletions.
2 changes: 2 additions & 0 deletions packages/next/build/webpack-config.ts
Expand Up @@ -1889,6 +1889,8 @@ export default async function getBaseWebpackConfig(
return new FontStylesheetGatheringPlugin({
isLikeServerless,
adjustFontFallbacks: config.experimental.adjustFontFallbacks,
adjustFontFallbacksWithSizeAdjust:
config.experimental.adjustFontFallbacksWithSizeAdjust,
})
})(),
new WellKnownErrorsPlugin(),
Expand Down
Expand Up @@ -54,16 +54,20 @@ export class FontStylesheetGatheringPlugin {
manifestContent: FontManifest = []
isLikeServerless: boolean
adjustFontFallbacks?: boolean
adjustFontFallbacksWithSizeAdjust?: boolean

constructor({
isLikeServerless,
adjustFontFallbacks,
adjustFontFallbacksWithSizeAdjust,
}: {
isLikeServerless: boolean
adjustFontFallbacks?: boolean
adjustFontFallbacksWithSizeAdjust?: boolean
}) {
this.isLikeServerless = isLikeServerless
this.adjustFontFallbacks = adjustFontFallbacks
this.adjustFontFallbacksWithSizeAdjust = adjustFontFallbacksWithSizeAdjust
}

private parserHandler = (
Expand Down Expand Up @@ -224,7 +228,11 @@ export class FontStylesheetGatheringPlugin {
let css = await fontDefinitionPromises[promiseIndex]

if (this.adjustFontFallbacks) {
css += getFontOverrideCss(fontStylesheets[promiseIndex], css)
css += getFontOverrideCss(
fontStylesheets[promiseIndex],
css,
this.adjustFontFallbacksWithSizeAdjust
)
}

if (css) {
Expand Down
3 changes: 3 additions & 0 deletions packages/next/server/config-schema.ts
Expand Up @@ -222,6 +222,9 @@ const configSchema = {
adjustFontFallbacks: {
type: 'boolean',
},
adjustFontFallbacksWithSizeAdjust: {
type: 'boolean',
},
amp: {
additionalProperties: false,
properties: {
Expand Down
2 changes: 2 additions & 0 deletions packages/next/server/config-shared.ts
Expand Up @@ -151,6 +151,7 @@ export interface ExperimentalConfig {
algorithm?: SubresourceIntegrityAlgorithm
}
adjustFontFallbacks?: boolean
adjustFontFallbacksWithSizeAdjust?: boolean

// A list of packages that should be treated as external in the RSC server build
optoutServerComponentsBundle?: string[]
Expand Down Expand Up @@ -588,6 +589,7 @@ export const defaultConfig: NextConfig = {
modularizeImports: undefined,
enableUndici: false,
adjustFontFallbacks: false,
adjustFontFallbacksWithSizeAdjust: false,
},
}

Expand Down
69 changes: 59 additions & 10 deletions packages/next/server/font-utils.ts
Expand Up @@ -98,26 +98,51 @@ function parseGoogleFontName(css: string): Array<string> {
return [...fontNames]
}

function formatOverrideValue(val: number) {
return Math.abs(val * 100).toFixed(2)
}

export function calculateOverrideValues(font: string, fontMetrics: any) {
const fontKey = font.toLowerCase().trim().replace(/ /g, '')
const { category, ascentOverride, descentOverride, lineGapOverride } =
const fontKey = font.trim()
let { category, ascent, descent, lineGap, unitsPerEm } = fontMetrics[fontKey]
const fallbackFont =
category === 'serif' ? DEFAULT_SERIF_FONT : DEFAULT_SANS_SERIF_FONT
ascent = formatOverrideValue(ascent / unitsPerEm)
descent = formatOverrideValue(descent / unitsPerEm)
lineGap = formatOverrideValue(lineGap / unitsPerEm)

return {
ascent,
descent,
lineGap,
fallbackFont: fallbackFont.name,
}
}

export function calculateSizeAdjustValues(font: string, fontMetrics: any) {
const fontKey = font.trim()
let { category, ascent, descent, lineGap, unitsPerEm, xAvgCharWidth } =
fontMetrics[fontKey]
const fallbackFont =
category === 'serif' ? DEFAULT_SERIF_FONT : DEFAULT_SANS_SERIF_FONT
const ascent = (ascentOverride * 100).toFixed(2)
const descent = (descentOverride * 100).toFixed(2)
const lineGap = (lineGapOverride * 100).toFixed(2)

let sizeAdjust = xAvgCharWidth / fallbackFont.xAvgCharWidth

ascent = formatOverrideValue(ascent / (unitsPerEm * sizeAdjust))
descent = formatOverrideValue(descent / (unitsPerEm * sizeAdjust))
lineGap = formatOverrideValue(lineGap / (unitsPerEm * sizeAdjust))

return {
ascent,
descent,
lineGap,
fallbackFont,
fallbackFont: fallbackFont.name,
sizeAdjust: formatOverrideValue(sizeAdjust),
}
}

function calculateOverrideCSS(font: string, fontMetrics: any) {
const fontName = font.toLowerCase().trim().replace(/ /g, '-')
const fontName = font.trim()

const { ascent, descent, lineGap, fallbackFont } = calculateOverrideValues(
font,
Expand All @@ -126,7 +151,7 @@ function calculateOverrideCSS(font: string, fontMetrics: any) {

return `
@font-face {
font-family: "${fontName}-fallback";
font-family: "${fontName} Fallback";
ascent-override: ${ascent}%;
descent-override: ${descent}%;
line-gap-override: ${lineGap}%;
Expand All @@ -135,17 +160,41 @@ function calculateOverrideCSS(font: string, fontMetrics: any) {
`
}

export function getFontOverrideCss(url: string, css: string) {
function calculateSizeAdjustCSS(font: string, fontMetrics: any) {
const fontName = font.trim()

const { ascent, descent, lineGap, fallbackFont, sizeAdjust } =
calculateSizeAdjustValues(font, fontMetrics)

return `
@font-face {
font-family: "${fontName} Fallback";
ascent-override: ${ascent}%;
descent-override: ${descent}%;
line-gap-override: ${lineGap}%;
size-adjust: ${sizeAdjust}%;
src: local("${fallbackFont}");
}
`
}

export function getFontOverrideCss(
url: string,
css: string,
useSizeAdjust = false
) {
if (!isGoogleFont(url)) {
return ''
}

const calcFn = useSizeAdjust ? calculateSizeAdjustCSS : calculateOverrideCSS

try {
const fontNames = parseGoogleFontName(css)
const fontMetrics = googleFontsMetrics

const fontCss = fontNames.reduce((cssStr, fontName) => {
cssStr += calculateOverrideCSS(fontName, fontMetrics)
cssStr += calcFn(fontName, fontMetrics)
return cssStr
}, '')

Expand Down

0 comments on commit 3da9c8a

Please sign in to comment.