@remotion/layout-utils 4.0.312 → 4.0.314

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,4 @@
1
1
  export { fillTextBox } from './layouts/fill-text-box';
2
2
  export { fitText } from './layouts/fit-text';
3
+ export { fitTextOnNLines } from './layouts/fit-text-on-n-lines';
3
4
  export { Dimensions, TextTransform, measureText } from './layouts/measure-text';
package/dist/cjs/index.js CHANGED
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.measureText = exports.fitText = exports.fillTextBox = void 0;
3
+ exports.measureText = exports.fitTextOnNLines = exports.fitText = exports.fillTextBox = void 0;
4
4
  var fill_text_box_1 = require("./layouts/fill-text-box");
5
5
  Object.defineProperty(exports, "fillTextBox", { enumerable: true, get: function () { return fill_text_box_1.fillTextBox; } });
6
6
  var fit_text_1 = require("./layouts/fit-text");
7
7
  Object.defineProperty(exports, "fitText", { enumerable: true, get: function () { return fit_text_1.fitText; } });
8
+ var fit_text_on_n_lines_1 = require("./layouts/fit-text-on-n-lines");
9
+ Object.defineProperty(exports, "fitTextOnNLines", { enumerable: true, get: function () { return fit_text_on_n_lines_1.fitTextOnNLines; } });
8
10
  var measure_text_1 = require("./layouts/measure-text");
9
11
  Object.defineProperty(exports, "measureText", { enumerable: true, get: function () { return measure_text_1.measureText; } });
@@ -37,6 +37,7 @@ const fillTextBox = ({ maxBoxWidth, maxLines, }) => {
37
37
  fontWeight,
38
38
  fontSize,
39
39
  letterSpacing,
40
+ textTransform,
40
41
  fontVariantNumeric,
41
42
  });
42
43
  return { exceedsBox: false, newLine: false };
@@ -51,6 +52,7 @@ const fillTextBox = ({ maxBoxWidth, maxLines, }) => {
51
52
  fontWeight,
52
53
  fontSize,
53
54
  letterSpacing,
55
+ textTransform,
54
56
  fontVariantNumeric,
55
57
  },
56
58
  ];
@@ -0,0 +1,19 @@
1
+ import type { TextTransform } from './measure-text';
2
+ type FitTextOnNLinesProps = {
3
+ text: string;
4
+ maxLines: number;
5
+ maxBoxWidth: number;
6
+ fontFamily: string;
7
+ fontWeight?: number | string;
8
+ letterSpacing?: string;
9
+ fontVariantNumeric?: string;
10
+ validateFontIsLoaded?: boolean;
11
+ textTransform?: TextTransform;
12
+ additionalStyles?: Record<string, string>;
13
+ maxFontSize?: number;
14
+ };
15
+ export declare const fitTextOnNLines: ({ text, maxLines, maxBoxWidth, fontFamily, fontWeight, letterSpacing, fontVariantNumeric, validateFontIsLoaded, textTransform, additionalStyles, maxFontSize, }: FitTextOnNLinesProps) => {
16
+ fontSize: number;
17
+ lines: string[];
18
+ };
19
+ export {};
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fitTextOnNLines = void 0;
4
+ const fill_text_box_1 = require("./fill-text-box");
5
+ const PRECISION = 100;
6
+ const fitTextOnNLines = ({ text, maxLines, maxBoxWidth, fontFamily, fontWeight, letterSpacing, fontVariantNumeric, validateFontIsLoaded, textTransform, additionalStyles, maxFontSize, }) => {
7
+ // Fixed max font size since we are using binary search a
8
+ const minFontSize = 0.1;
9
+ // Binary search to find the optimal font size
10
+ let left = Math.floor(minFontSize * PRECISION);
11
+ let right = Math.floor((maxFontSize !== null && maxFontSize !== void 0 ? maxFontSize : 2000) * PRECISION);
12
+ let optimalFontSize = minFontSize;
13
+ let optimalLines = [];
14
+ while (left <= right) {
15
+ const mid = Math.floor((left + right) / 2);
16
+ const fontSize = mid / PRECISION;
17
+ // Create a text box with current font size
18
+ const textBox = (0, fill_text_box_1.fillTextBox)({
19
+ maxBoxWidth,
20
+ maxLines,
21
+ });
22
+ // Split text into words and try to fit them
23
+ const words = text.split(' ');
24
+ let exceedsBox = false;
25
+ let currentLine = 0;
26
+ const lines = [''];
27
+ for (const word of words) {
28
+ const result = textBox.add({
29
+ text: word + ' ',
30
+ fontFamily,
31
+ fontWeight,
32
+ fontSize,
33
+ letterSpacing,
34
+ fontVariantNumeric,
35
+ validateFontIsLoaded,
36
+ textTransform,
37
+ additionalStyles,
38
+ });
39
+ if (result.exceedsBox) {
40
+ exceedsBox = true;
41
+ break;
42
+ }
43
+ if (result.newLine) {
44
+ lines.push('');
45
+ currentLine++;
46
+ }
47
+ lines[currentLine] += word + ' ';
48
+ }
49
+ // If text fits within the box and number of lines
50
+ if (!exceedsBox && currentLine < maxLines) {
51
+ optimalFontSize = fontSize;
52
+ optimalLines = lines;
53
+ left = mid + 1;
54
+ }
55
+ else {
56
+ right = mid - 1;
57
+ }
58
+ }
59
+ return {
60
+ fontSize: optimalFontSize,
61
+ lines: optimalLines,
62
+ };
63
+ };
64
+ exports.fitTextOnNLines = fitTextOnNLines;
@@ -75,7 +75,10 @@ const measureText = ({ text, fontFamily, fontSize, fontWeight, letterSpacing, fo
75
75
  });
76
76
  const sameAsFallbackFont = boundingBox.height === boundingBoxOfFallbackFont.height &&
77
77
  boundingBox.width === boundingBoxOfFallbackFont.width;
78
- if (sameAsFallbackFont && computedFallback !== computedFontFamily) {
78
+ // Ensure there are at least 4 unique characters, with just a few, there is more likely to be a false positive
79
+ if (sameAsFallbackFont &&
80
+ computedFallback !== computedFontFamily &&
81
+ new Set(text).size > 4) {
79
82
  const err = [
80
83
  `Called measureText() with "fontFamily": ${JSON.stringify(fontFamily)} but it looks like the font is not loaded at the time of calling.`,
81
84
  `A measurement with the fallback font ${computedFallback} was taken and had the same dimensions, indicating that the browser used the fallback font.`,
@@ -89,7 +89,7 @@ var measureText = ({
89
89
  textTransform
90
90
  });
91
91
  const sameAsFallbackFont = boundingBox.height === boundingBoxOfFallbackFont.height && boundingBox.width === boundingBoxOfFallbackFont.width;
92
- if (sameAsFallbackFont && computedFallback !== computedFontFamily) {
92
+ if (sameAsFallbackFont && computedFallback !== computedFontFamily && new Set(text).size > 4) {
93
93
  const err = [
94
94
  `Called measureText() with "fontFamily": ${JSON.stringify(fontFamily)} but it looks like the font is not loaded at the time of calling.`,
95
95
  `A measurement with the fallback font ${computedFallback} was taken and had the same dimensions, indicating that the browser used the fallback font.`,
@@ -153,6 +153,7 @@ var fillTextBox = ({
153
153
  fontWeight,
154
154
  fontSize,
155
155
  letterSpacing,
156
+ textTransform,
156
157
  fontVariantNumeric
157
158
  });
158
159
  return { exceedsBox: false, newLine: false };
@@ -167,6 +168,7 @@ var fillTextBox = ({
167
168
  fontWeight,
168
169
  fontSize,
169
170
  letterSpacing,
171
+ textTransform,
170
172
  fontVariantNumeric
171
173
  }
172
174
  ];
@@ -200,8 +202,75 @@ var fitText = ({
200
202
  });
201
203
  return { fontSize: withinWidth / estimate.width * sampleSize };
202
204
  };
205
+ // src/layouts/fit-text-on-n-lines.ts
206
+ var PRECISION = 100;
207
+ var fitTextOnNLines = ({
208
+ text,
209
+ maxLines,
210
+ maxBoxWidth,
211
+ fontFamily,
212
+ fontWeight,
213
+ letterSpacing,
214
+ fontVariantNumeric,
215
+ validateFontIsLoaded,
216
+ textTransform,
217
+ additionalStyles,
218
+ maxFontSize
219
+ }) => {
220
+ const minFontSize = 0.1;
221
+ let left = Math.floor(minFontSize * PRECISION);
222
+ let right = Math.floor((maxFontSize ?? 2000) * PRECISION);
223
+ let optimalFontSize = minFontSize;
224
+ let optimalLines = [];
225
+ while (left <= right) {
226
+ const mid = Math.floor((left + right) / 2);
227
+ const fontSize = mid / PRECISION;
228
+ const textBox = fillTextBox({
229
+ maxBoxWidth,
230
+ maxLines
231
+ });
232
+ const words = text.split(" ");
233
+ let exceedsBox = false;
234
+ let currentLine = 0;
235
+ const lines = [""];
236
+ for (const word of words) {
237
+ const result = textBox.add({
238
+ text: word + " ",
239
+ fontFamily,
240
+ fontWeight,
241
+ fontSize,
242
+ letterSpacing,
243
+ fontVariantNumeric,
244
+ validateFontIsLoaded,
245
+ textTransform,
246
+ additionalStyles
247
+ });
248
+ if (result.exceedsBox) {
249
+ exceedsBox = true;
250
+ break;
251
+ }
252
+ if (result.newLine) {
253
+ lines.push("");
254
+ currentLine++;
255
+ }
256
+ lines[currentLine] += word + " ";
257
+ }
258
+ if (!exceedsBox && currentLine < maxLines) {
259
+ optimalFontSize = fontSize;
260
+ optimalLines = lines;
261
+ left = mid + 1;
262
+ } else {
263
+ right = mid - 1;
264
+ }
265
+ }
266
+ return {
267
+ fontSize: optimalFontSize,
268
+ lines: optimalLines
269
+ };
270
+ };
203
271
  export {
204
272
  measureText,
273
+ fitTextOnNLines,
205
274
  fitText,
206
275
  fillTextBox
207
276
  };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/layout-utils"
4
4
  },
5
5
  "name": "@remotion/layout-utils",
6
- "version": "4.0.312",
6
+ "version": "4.0.314",
7
7
  "description": "Utilities for working with layouts",
8
8
  "main": "dist/cjs/index.js",
9
9
  "types": "dist/cjs/index.d.ts",
@@ -20,7 +20,7 @@
20
20
  },
21
21
  "devDependencies": {
22
22
  "eslint": "9.19.0",
23
- "@remotion/eslint-config-internal": "4.0.312"
23
+ "@remotion/eslint-config-internal": "4.0.314"
24
24
  },
25
25
  "author": "Yehor Misiats (https://github.com/satelllte)",
26
26
  "maintainers": [