PluginProbe
Gutenberg / 17.0.2
Gutenberg v17.0.2
24.0.0 23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 All 403 releases
gutenberg / lib / block-supports / typography.php

typography.php in Gutenberg 17.0.2, at lib/block-supports/typography.php

583 lines 24.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Typography block support flag.
4 *
5 * @package gutenberg
6 */
7
8 /**
9 * Registers the style and typography block attributes for block types that support it.
10 *
11 * @param WP_Block_Type $block_type Block Type.
12 */
13 function gutenberg_register_typography_support( $block_type ) {
14 if ( ! $block_type instanceof WP_Block_Type ) {
15 return;
16 }
17
18 $typography_supports = $block_type->supports['typography'] ?? false;
19 if ( ! $typography_supports ) {
20 return;
21 }
22
23 $has_font_family_support = $typography_supports['__experimentalFontFamily'] ?? false;
24 $has_font_size_support = $typography_supports['fontSize'] ?? false;
25 $has_font_style_support = $typography_supports['__experimentalFontStyle'] ?? false;
26 $has_font_weight_support = $typography_supports['__experimentalFontWeight'] ?? false;
27 $has_letter_spacing_support = $typography_supports['__experimentalLetterSpacing'] ?? false;
28 $has_line_height_support = $typography_supports['lineHeight'] ?? false;
29 $has_text_columns_support = $typography_supports['textColumns'] ?? false;
30 $has_text_decoration_support = $typography_supports['__experimentalTextDecoration'] ?? false;
31 $has_text_transform_support = $typography_supports['__experimentalTextTransform'] ?? false;
32 $has_writing_mode_support = $typography_supports['__experimentalWritingMode'] ?? false;
33
34 $has_typography_support = $has_font_family_support
35 || $has_font_size_support
36 || $has_font_style_support
37 || $has_font_weight_support
38 || $has_letter_spacing_support
39 || $has_line_height_support
40 || $has_text_columns_support
41 || $has_text_decoration_support
42 || $has_text_transform_support
43 || $has_writing_mode_support;
44
45 if ( ! $block_type->attributes ) {
46 $block_type->attributes = array();
47 }
48
49 if ( $has_typography_support && ! array_key_exists( 'style', $block_type->attributes ) ) {
50 $block_type->attributes['style'] = array(
51 'type' => 'object',
52 );
53 }
54
55 if ( $has_font_size_support && ! array_key_exists( 'fontSize', $block_type->attributes ) ) {
56 $block_type->attributes['fontSize'] = array(
57 'type' => 'string',
58 );
59 }
60
61 if ( $has_font_family_support && ! array_key_exists( 'fontFamily', $block_type->attributes ) ) {
62 $block_type->attributes['fontFamily'] = array(
63 'type' => 'string',
64 );
65 }
66 }
67
68 /**
69 * Add CSS classes and inline styles for typography features such as font sizes
70 * to the incoming attributes array. This will be applied to the block markup in
71 * the front-end.
72 *
73 * @param WP_Block_Type $block_type Block type.
74 * @param array $block_attributes Block attributes.
75 *
76 * @return array Typography CSS classes and inline styles.
77 */
78 function gutenberg_apply_typography_support( $block_type, $block_attributes ) {
79 if ( ! $block_type instanceof WP_Block_Type ) {
80 return array();
81 }
82
83 $typography_supports = $block_type->supports['typography'] ?? false;
84 if ( ! $typography_supports ) {
85 return array();
86 }
87
88 if ( wp_should_skip_block_supports_serialization( $block_type, 'typography' ) ) {
89 return array();
90 }
91
92 $has_font_family_support = $typography_supports['__experimentalFontFamily'] ?? false;
93 $has_font_size_support = $typography_supports['fontSize'] ?? false;
94 $has_font_style_support = $typography_supports['__experimentalFontStyle'] ?? false;
95 $has_font_weight_support = $typography_supports['__experimentalFontWeight'] ?? false;
96 $has_letter_spacing_support = $typography_supports['__experimentalLetterSpacing'] ?? false;
97 $has_line_height_support = $typography_supports['lineHeight'] ?? false;
98 $has_text_columns_support = $typography_supports['textColumns'] ?? false;
99 $has_text_decoration_support = $typography_supports['__experimentalTextDecoration'] ?? false;
100 $has_text_transform_support = $typography_supports['__experimentalTextTransform'] ?? false;
101 $has_writing_mode_support = $typography_supports['__experimentalWritingMode'] ?? false;
102
103 // Whether to skip individual block support features.
104 $should_skip_font_size = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontSize' );
105 $should_skip_font_family = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontFamily' );
106 $should_skip_font_style = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontStyle' );
107 $should_skip_font_weight = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontWeight' );
108 $should_skip_line_height = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'lineHeight' );
109 $should_skip_text_columns = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textColumns' );
110 $should_skip_text_decoration = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textDecoration' );
111 $should_skip_text_transform = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textTransform' );
112 $should_skip_letter_spacing = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'letterSpacing' );
113 $should_skip_writing_mode = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'writingMode' );
114
115 $typography_block_styles = array();
116 if ( $has_font_size_support && ! $should_skip_font_size ) {
117 $preset_font_size = array_key_exists( 'fontSize', $block_attributes ) ? "var:preset|font-size|{$block_attributes['fontSize']}" : null;
118 $custom_font_size = isset( $block_attributes['style']['typography']['fontSize'] ) ? $block_attributes['style']['typography']['fontSize'] : null;
119 $typography_block_styles['fontSize'] = $preset_font_size ? $preset_font_size : gutenberg_get_typography_font_size_value(
120 array(
121 'size' => $custom_font_size,
122 )
123 );
124 }
125
126 if ( $has_font_family_support && ! $should_skip_font_family ) {
127 $preset_font_family = array_key_exists( 'fontFamily', $block_attributes ) ? "var:preset|font-family|{$block_attributes['fontFamily']}" : null;
128 $custom_font_family = isset( $block_attributes['style']['typography']['fontFamily'] ) ? gutenberg_typography_get_preset_inline_style_value( $block_attributes['style']['typography']['fontFamily'], 'font-family' ) : null;
129 $typography_block_styles['fontFamily'] = $preset_font_family ? $preset_font_family : $custom_font_family;
130 }
131
132 if ( $has_font_style_support && ! $should_skip_font_style && isset( $block_attributes['style']['typography']['fontStyle'] ) ) {
133 $typography_block_styles['fontStyle'] =
134 gutenberg_typography_get_preset_inline_style_value( $block_attributes['style']['typography']['fontStyle'], 'font-style' );
135 }
136
137 if ( $has_font_weight_support && ! $should_skip_font_weight && isset( $block_attributes['style']['typography']['fontWeight'] ) ) {
138 $typography_block_styles['fontWeight'] =
139 gutenberg_typography_get_preset_inline_style_value( $block_attributes['style']['typography']['fontWeight'], 'font-weight' );
140 }
141
142 if ( $has_line_height_support && ! $should_skip_line_height ) {
143 $typography_block_styles['lineHeight'] = $block_attributes['style']['typography']['lineHeight'] ?? null;
144 }
145
146 if ( $has_text_columns_support && ! $should_skip_text_columns && isset( $block_attributes['style']['typography']['textColumns'] ) ) {
147 $typography_block_styles['textColumns'] = $block_attributes['style']['typography']['textColumns'] ?? null;
148 }
149
150 if ( $has_text_decoration_support && ! $should_skip_text_decoration && isset( $block_attributes['style']['typography']['textDecoration'] ) ) {
151 $typography_block_styles['textDecoration'] =
152 gutenberg_typography_get_preset_inline_style_value( $block_attributes['style']['typography']['textDecoration'], 'text-decoration' );
153 }
154
155 if ( $has_text_transform_support && ! $should_skip_text_transform && isset( $block_attributes['style']['typography']['textTransform'] ) ) {
156 $typography_block_styles['textTransform'] =
157 gutenberg_typography_get_preset_inline_style_value( $block_attributes['style']['typography']['textTransform'], 'text-transform' );
158 }
159
160 if ( $has_letter_spacing_support && ! $should_skip_letter_spacing && isset( $block_attributes['style']['typography']['letterSpacing'] ) ) {
161 $typography_block_styles['letterSpacing'] =
162 gutenberg_typography_get_preset_inline_style_value( $block_attributes['style']['typography']['letterSpacing'], 'letter-spacing' );
163 }
164
165 if ( $has_writing_mode_support && ! $should_skip_writing_mode && isset( $block_attributes['style']['typography']['writingMode'] ) ) {
166 $typography_block_styles['writingMode'] = $block_attributes['style']['typography']['writingMode'] ?? null;
167 }
168
169 $attributes = array();
170 $styles = gutenberg_style_engine_get_styles(
171 array( 'typography' => $typography_block_styles ),
172 array( 'convert_vars_to_classnames' => true )
173 );
174
175 if ( ! empty( $styles['classnames'] ) ) {
176 $attributes['class'] = $styles['classnames'];
177 }
178
179 if ( ! empty( $styles['css'] ) ) {
180 $attributes['style'] = $styles['css'];
181 }
182
183 return $attributes;
184 }
185
186 /**
187 * Generates an inline style value for a typography feature e.g. text decoration,
188 * text transform, and font style.
189 *
190 * Note: This function is for backwards compatibility.
191 * * It is necessary to parse older blocks whose typography styles contain presets.
192 * * It mostly replaces the deprecated `wp_typography_get_css_variable_inline_style()`,
193 * but skips compiling a CSS declaration as the style engine takes over this role.
194 *
195 * @link https://github.com/wordpress/gutenberg/pull/27555
196 *
197 * @since 6.1.0
198 *
199 * @param string $style_value A raw style value for a single typography feature from a block's style attribute.
200 * @param string $css_property Slug for the CSS property the inline style sets.
201 * @return string A CSS inline style value.
202 */
203 function gutenberg_typography_get_preset_inline_style_value( $style_value, $css_property ) {
204 // If the style value is not a preset CSS variable go no further.
205 if ( empty( $style_value ) || ! str_contains( $style_value, "var:preset|{$css_property}|" ) ) {
206 return $style_value;
207 }
208
209 /*
210 * For backwards compatibility.
211 * Presets were removed in WordPress/gutenberg#27555.
212 * We have a preset CSS variable as the style.
213 * Get the style value from the string and return CSS style.
214 */
215 $index_to_splice = strrpos( $style_value, '|' ) + 1;
216 $slug = _wp_to_kebab_case( substr( $style_value, $index_to_splice ) );
217
218 // Return the actual CSS inline style value e.g. `var(--wp--preset--text-decoration--underline);`.
219 return sprintf( 'var(--wp--preset--%s--%s);', $css_property, $slug );
220 }
221
222 /**
223 * Renders typography styles/content to the block wrapper.
224 *
225 * @param string $block_content Rendered block content.
226 * @param array $block Block object.
227 * @return string Filtered block content.
228 */
229 function gutenberg_render_typography_support( $block_content, $block ) {
230 if ( ! isset( $block['attrs']['style']['typography']['fontSize'] ) ) {
231 return $block_content;
232 }
233
234 $custom_font_size = $block['attrs']['style']['typography']['fontSize'];
235 $fluid_font_size = gutenberg_get_typography_font_size_value( array( 'size' => $custom_font_size ) );
236
237 /*
238 * Checks that $fluid_font_size does not match $custom_font_size,
239 * which means it's been mutated by the fluid font size functions.
240 */
241 if ( ! empty( $fluid_font_size ) && $fluid_font_size !== $custom_font_size ) {
242 // Replaces the first instance of `font-size:$custom_font_size` with `font-size:$fluid_font_size`.
243 return preg_replace( '/font-size\s*:\s*' . preg_quote( $custom_font_size, '/' ) . '\s*;?/', 'font-size:' . esc_attr( $fluid_font_size ) . ';', $block_content, 1 );
244 }
245
246 return $block_content;
247 }
248
249 /**
250 * Internal method that checks a string for a unit and value and returns an array consisting of `'value'` and `'unit'`, e.g., [ '42', 'rem' ].
251 * A raw font size of `value + unit` is expected. If the value is a number, it will convert to `value + 'px'`.
252 *
253 * @access private
254 *
255 * @param string|int|float $raw_value Raw size value from theme.json.
256 * @param array $options {
257 * Optional. An associative array of options. Default is empty array.
258 *
259 * @type string $coerce_to Coerce the value to rem or px. Default `'rem'`.
260 * @type int $root_size_value Value of root font size for rem|em <-> px conversion. Default `16`.
261 * @type array<string> $acceptable_units An array of font size units. Default `[ 'rem', 'px', 'em' ]`;
262 * }
263 * @return array An array consisting of `'value'` and `'unit'` properties.
264 */
265 function gutenberg_get_typography_value_and_unit( $raw_value, $options = array() ) {
266 if ( ! is_string( $raw_value ) && ! is_int( $raw_value ) && ! is_float( $raw_value ) ) {
267 _doing_it_wrong(
268 __FUNCTION__,
269 __( 'Raw size value must be a string, integer or a float.', 'gutenberg' ),
270 '6.1.0'
271 );
272 return null;
273 }
274
275 if ( empty( $raw_value ) ) {
276 return null;
277 }
278
279 // Converts numeric values to pixel values by default.
280 if ( is_numeric( $raw_value ) ) {
281 $raw_value = $raw_value . 'px';
282 }
283
284 $defaults = array(
285 'coerce_to' => '',
286 'root_size_value' => 16,
287 'acceptable_units' => array( 'rem', 'px', 'em' ),
288 );
289
290 $options = wp_parse_args( $options, $defaults );
291
292 $acceptable_units_group = implode( '|', $options['acceptable_units'] );
293 $pattern = '/^(\d*\.?\d+)(' . $acceptable_units_group . '){1,1}$/';
294
295 preg_match( $pattern, $raw_value, $matches );
296
297 // We need a number value and a px or rem unit.
298 if ( ! isset( $matches[1] ) || ! isset( $matches[2] ) ) {
299 return null;
300 }
301
302 $value = $matches[1];
303 $unit = $matches[2];
304
305 // Default browser font size. Later we could inject some JS to compute this `getComputedStyle( document.querySelector( "html" ) ).fontSize`.
306 if ( 'px' === $options['coerce_to'] && ( 'em' === $unit || 'rem' === $unit ) ) {
307 $value = $value * $options['root_size_value'];
308 $unit = $options['coerce_to'];
309 }
310
311 if ( 'px' === $unit && ( 'em' === $options['coerce_to'] || 'rem' === $options['coerce_to'] ) ) {
312 $value = $value / $options['root_size_value'];
313 $unit = $options['coerce_to'];
314 }
315
316 /*
317 * No calculation is required if swapping between em and rem yet,
318 * since we assume a root size value. Later we might like to differentiate between
319 * :root font size (rem) and parent element font size (em) relativity.
320 */
321 if ( ( 'em' === $options['coerce_to'] || 'rem' === $options['coerce_to'] ) && ( 'em' === $unit || 'rem' === $unit ) ) {
322 $unit = $options['coerce_to'];
323 }
324
325 return array(
326 'value' => round( $value, 3 ),
327 'unit' => $unit,
328 );
329 }
330
331 /**
332 * Internal implementation of clamp() based on available min/max viewport width, and min/max font sizes.
333 *
334 * @access private
335 *
336 * @param array $args {
337 * Optional. An associative array of values to calculate a fluid formula for font size. Default is empty array.
338 *
339 * @type string $maximum_viewport_width Maximum size up to which type will have fluidity.
340 * @type string $minimum_viewport_width Minimum viewport size from which type will have fluidity.
341 * @type string $maximum_font_size Maximum font size for any clamp() calculation.
342 * @type string $minimum_font_size Minimum font size for any clamp() calculation.
343 * @type int $scale_factor A scale factor to determine how fast a font scales within boundaries.
344 * }
345 * @return string|null A font-size value using clamp().
346 */
347 function gutenberg_get_computed_fluid_typography_value( $args = array() ) {
348 $maximum_viewport_width_raw = isset( $args['maximum_viewport_width'] ) ? $args['maximum_viewport_width'] : null;
349 $minimum_viewport_width_raw = isset( $args['minimum_viewport_width'] ) ? $args['minimum_viewport_width'] : null;
350 $maximum_font_size_raw = isset( $args['maximum_font_size'] ) ? $args['maximum_font_size'] : null;
351 $minimum_font_size_raw = isset( $args['minimum_font_size'] ) ? $args['minimum_font_size'] : null;
352 $scale_factor = isset( $args['scale_factor'] ) ? $args['scale_factor'] : null;
353
354 // Normalizes the minimum font size in order to use the value for calculations.
355 $minimum_font_size = gutenberg_get_typography_value_and_unit( $minimum_font_size_raw );
356
357 /*
358 * We get a 'preferred' unit to keep units consistent when calculating,
359 * otherwise the result will not be accurate.
360 */
361 $font_size_unit = isset( $minimum_font_size['unit'] ) ? $minimum_font_size['unit'] : 'rem';
362
363 // Grabs the maximum font size and normalize it in order to use the value for calculations.
364 $maximum_font_size = gutenberg_get_typography_value_and_unit(
365 $maximum_font_size_raw,
366 array(
367 'coerce_to' => $font_size_unit,
368 )
369 );
370
371 // Checks for mandatory min and max sizes, and protects against unsupported units.
372 if ( ! $maximum_font_size || ! $minimum_font_size ) {
373 return null;
374 }
375
376 // Uses rem for accessible fluid target font scaling.
377 $minimum_font_size_rem = gutenberg_get_typography_value_and_unit(
378 $minimum_font_size_raw,
379 array(
380 'coerce_to' => 'rem',
381 )
382 );
383
384 // Viewport widths defined for fluid typography. Normalize units.
385 $maximum_viewport_width = gutenberg_get_typography_value_and_unit(
386 $maximum_viewport_width_raw,
387 array(
388 'coerce_to' => $font_size_unit,
389 )
390 );
391
392 $minimum_viewport_width = gutenberg_get_typography_value_and_unit(
393 $minimum_viewport_width_raw,
394 array(
395 'coerce_to' => $font_size_unit,
396 )
397 );
398
399 // Protects against unsupported units in min and max viewport widths.
400 if ( ! $minimum_viewport_width || ! $maximum_viewport_width ) {
401 return null;
402 }
403
404 // Build CSS rule.
405 // Borrowed from https://websemantics.uk/tools/responsive-font-calculator/.
406 $view_port_width_offset = round( $minimum_viewport_width['value'] / 100, 3 ) . $font_size_unit;
407 $linear_factor = 100 * ( ( $maximum_font_size['value'] - $minimum_font_size['value'] ) / ( $maximum_viewport_width['value'] - $minimum_viewport_width['value'] ) );
408 $linear_factor_scaled = round( $linear_factor * $scale_factor, 3 );
409 $linear_factor_scaled = empty( $linear_factor_scaled ) ? 1 : $linear_factor_scaled;
410 $fluid_target_font_size = implode( '', $minimum_font_size_rem ) . " + ((1vw - $view_port_width_offset) * $linear_factor_scaled)";
411
412 return "clamp($minimum_font_size_raw, $fluid_target_font_size, $maximum_font_size_raw)";
413 }
414
415 /**
416 * Returns a font-size value based on a given font-size preset.
417 * Takes into account fluid typography parameters and attempts to return a CSS
418 * formula depending on available, valid values.
419 *
420 * @since 6.1.0
421 * @since 6.1.1 Adjusted rules for min and max font sizes.
422 * @since 6.2.0 Added 'settings.typography.fluid.minFontSize' support.
423 * @since 6.3.0 Using layout.wideSize as max viewport width, and logarithmic scale factor to calculate minimum font scale.
424 * @since 6.4.0 Added configurable min and max viewport width values to the typography.fluid theme.json schema.
425 *
426 * @param array $preset {
427 * Required. fontSizes preset value as seen in theme.json.
428 *
429 * @type string $name Name of the font size preset.
430 * @type string $slug Kebab-case unique identifier for the font size preset.
431 * @type string|int|float $size CSS font-size value, including units where applicable.
432 * }
433 * @param bool $should_use_fluid_typography An override to switch fluid typography "on". Can be used for unit testing. Default is `false`.
434 *
435 * @return string|null Font-size value or `null` if a size is not passed in $preset.
436 */
437 function gutenberg_get_typography_font_size_value( $preset, $should_use_fluid_typography = false ) {
438 if ( ! isset( $preset['size'] ) ) {
439 return null;
440 }
441
442 /*
443 * Catches empty values and 0/'0'.
444 * Fluid calculations cannot be performed on 0.
445 */
446 if ( empty( $preset['size'] ) ) {
447 return $preset['size'];
448 }
449
450 // Checks if fluid font sizes are activated.
451 $global_settings = gutenberg_get_global_settings();
452 $typography_settings = isset( $global_settings['typography'] ) ? $global_settings['typography'] : array();
453 $layout_settings = isset( $global_settings['layout'] ) ? $global_settings['layout'] : array();
454
455 $should_use_fluid_typography
456 = isset( $typography_settings['fluid'] ) &&
457 ( true === $typography_settings['fluid'] || is_array( $typography_settings['fluid'] ) ) ?
458 true :
459 $should_use_fluid_typography;
460
461 if ( ! $should_use_fluid_typography ) {
462 return $preset['size'];
463 }
464
465 $fluid_settings = isset( $typography_settings['fluid'] ) && is_array( $typography_settings['fluid'] ) ? $typography_settings['fluid'] : array();
466
467 // Defaults.
468 $default_maximum_viewport_width = '1600px';
469 $default_minimum_viewport_width = '320px';
470 $default_minimum_font_size_factor_max = 0.75;
471 $default_minimum_font_size_factor_min = 0.25;
472 $default_scale_factor = 1;
473 $default_minimum_font_size_limit = '14px';
474
475 // Defaults overrides.
476 $minimum_viewport_width = isset( $fluid_settings['minViewportWidth'] ) ? $fluid_settings['minViewportWidth'] : $default_minimum_viewport_width;
477 $maximum_viewport_width = isset( $layout_settings['wideSize'] ) && ! empty( gutenberg_get_typography_value_and_unit( $layout_settings['wideSize'] ) ) ? $layout_settings['wideSize'] : $default_maximum_viewport_width;
478 if ( isset( $fluid_settings['maxViewportWidth'] ) ) {
479 $maximum_viewport_width = $fluid_settings['maxViewportWidth'];
480 }
481 $has_min_font_size = isset( $fluid_settings['minFontSize'] ) && ! empty( gutenberg_get_typography_value_and_unit( $fluid_settings['minFontSize'] ) );
482 $minimum_font_size_limit = $has_min_font_size ? $fluid_settings['minFontSize'] : $default_minimum_font_size_limit;
483
484 // Font sizes.
485 $fluid_font_size_settings = isset( $preset['fluid'] ) ? $preset['fluid'] : null;
486
487 // A font size has explicitly bypassed fluid calculations.
488 if ( false === $fluid_font_size_settings ) {
489 return $preset['size'];
490 }
491
492 // Try to grab explicit min and max fluid font sizes.
493 $minimum_font_size_raw = isset( $fluid_font_size_settings['min'] ) ? $fluid_font_size_settings['min'] : null;
494 $maximum_font_size_raw = isset( $fluid_font_size_settings['max'] ) ? $fluid_font_size_settings['max'] : null;
495
496 // Font sizes.
497 $preferred_size = gutenberg_get_typography_value_and_unit( $preset['size'] );
498
499 // Protects against unsupported units.
500 if ( empty( $preferred_size['unit'] ) ) {
501 return $preset['size'];
502 }
503
504 // Parses the minimum font size limit, so we can perform checks using it.
505 $minimum_font_size_limit = gutenberg_get_typography_value_and_unit(
506 $minimum_font_size_limit,
507 array(
508 'coerce_to' => $preferred_size['unit'],
509 )
510 );
511
512 // Don't enforce minimum font size if a font size has explicitly set a min and max value.
513 if ( ! empty( $minimum_font_size_limit ) && ( ! $minimum_font_size_raw && ! $maximum_font_size_raw ) ) {
514 /*
515 * If a minimum size was not passed to this function
516 * and the user-defined font size is lower than $minimum_font_size_limit,
517 * do not calculate a fluid value.
518 */
519 if ( $preferred_size['value'] <= $minimum_font_size_limit['value'] ) {
520 return $preset['size'];
521 }
522 }
523
524 // If no fluid max font size is available use the incoming value.
525 if ( ! $maximum_font_size_raw ) {
526 $maximum_font_size_raw = $preferred_size['value'] . $preferred_size['unit'];
527 }
528
529 /*
530 * If no minimumFontSize is provided, create one using
531 * the given font size multiplied by the min font size scale factor.
532 */
533 if ( ! $minimum_font_size_raw ) {
534 $preferred_font_size_in_px = 'px' === $preferred_size['unit'] ? $preferred_size['value'] : $preferred_size['value'] * 16;
535
536 /*
537 * The scale factor is a multiplier that affects how quickly the curve will move towards the minimum,
538 * that is, how quickly the size factor reaches 0 given increasing font size values.
539 * For a - b * log2(), lower values of b will make the curve move towards the minimum faster.
540 * The scale factor is constrained between min and max values.
541 */
542 $minimum_font_size_factor = min( max( 1 - 0.075 * log( $preferred_font_size_in_px, 2 ), $default_minimum_font_size_factor_min ), $default_minimum_font_size_factor_max );
543 $calculated_minimum_font_size = round( $preferred_size['value'] * $minimum_font_size_factor, 3 );
544
545 // Only use calculated min font size if it's > $minimum_font_size_limit value.
546 if ( ! empty( $minimum_font_size_limit ) && $calculated_minimum_font_size <= $minimum_font_size_limit['value'] ) {
547 $minimum_font_size_raw = $minimum_font_size_limit['value'] . $minimum_font_size_limit['unit'];
548 } else {
549 $minimum_font_size_raw = $calculated_minimum_font_size . $preferred_size['unit'];
550 }
551 }
552
553 $fluid_font_size_value = gutenberg_get_computed_fluid_typography_value(
554 array(
555 'minimum_viewport_width' => $minimum_viewport_width,
556 'maximum_viewport_width' => $maximum_viewport_width,
557 'minimum_font_size' => $minimum_font_size_raw,
558 'maximum_font_size' => $maximum_font_size_raw,
559 'scale_factor' => $default_scale_factor,
560 )
561 );
562
563 if ( ! empty( $fluid_font_size_value ) ) {
564 return $fluid_font_size_value;
565 }
566
567 return $preset['size'];
568 }
569
570 // Register the block support.
571 WP_Block_Supports::get_instance()->register(
572 'typography',
573 array(
574 'register_attribute' => 'gutenberg_register_typography_support',
575 'apply' => 'gutenberg_apply_typography_support',
576 )
577 );
578
579 if ( function_exists( 'wp_render_typography_support' ) ) {
580 remove_filter( 'render_block', 'wp_render_typography_support' );
581 }
582 add_filter( 'render_block', 'gutenberg_render_typography_support', 10, 2 );
583