pa_font 0.2.1 → 0.2.2

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.
package/README.md CHANGED
@@ -0,0 +1,39 @@
1
+ # paFont
2
+
3
+ `paFont`는 OpenType 폰트에서 텍스트 geometry를 만들고, 같은 폰트로 canvas 문단 레이아웃까지 처리하는 작은 라이브러리입니다.
4
+
5
+ ## 설치
6
+
7
+ ```sh
8
+ npm install pa_font
9
+ ```
10
+
11
+ ## 빠른 예시
12
+
13
+ ```js
14
+ import paFont from "pa_font";
15
+
16
+ const font = await paFont.load("/assets/font.otf");
17
+
18
+ const paragraph = font.paragraph("Canvas paragraph with fast wrapping.", {
19
+ x: 40,
20
+ y: 80,
21
+ size: 32,
22
+ width: 420,
23
+ wrap: "word",
24
+ padding: { x: 24, y: 20 },
25
+ });
26
+
27
+ paragraph.drawText(ctx, { fillStyle: "#111" });
28
+
29
+ const shape = paragraph.toShape({ step: 6 });
30
+ ```
31
+
32
+ ## 문단 API 핵심
33
+
34
+ - `wrap: "word" | "char" | "keep"`로 대부분의 줄바꿈 모드를 짧게 지정할 수 있습니다.
35
+ - `padding` / `margin`은 `24`, `"24 32"`, `[24, 32]`, `{ x: 32, y: 24 }`, `{ top, right, bottom, left }`를 지원합니다.
36
+ - 기본 문단 레이아웃은 `pretext` hot path를 우선 사용하고, 필요한 경우만 native 측정으로 fallback 합니다.
37
+ - 실제 사용 엔진은 `paragraph.layoutEngine`에서 확인할 수 있습니다.
38
+
39
+ 자세한 사용법은 [USAGE.md](./USAGE.md)를 참고하세요.
package/USAGE.md ADDED
@@ -0,0 +1,294 @@
1
+ # paFont Usage
2
+
3
+ `paFont`는 OpenType 폰트를 읽어:
4
+
5
+ - canvas 문단 텍스트로 그리거나
6
+ - polygon / region / point geometry로 변환하는 라이브러리입니다.
7
+
8
+ ## 기본 흐름
9
+
10
+ ### 1. 폰트 로드
11
+
12
+ ```js
13
+ import paFont from "./src/paFont.js";
14
+
15
+ const font = await paFont.load("/assets/font.otf");
16
+ ```
17
+
18
+ 모듈 상대 경로를 쓰고 싶으면:
19
+
20
+ ```js
21
+ const font = await paFont.load("./font.otf", {
22
+ base: import.meta.url,
23
+ });
24
+ ```
25
+
26
+ ## 빠른 예시
27
+
28
+ ### 1. 텍스트를 geometry로 만들기
29
+
30
+ ```js
31
+ const shape = font.text("안녕", {
32
+ x: 0,
33
+ y: 200,
34
+ size: 160,
35
+ flatten: 1,
36
+ });
37
+
38
+ const regions = shape.toRegions();
39
+ const points = shape.toPoints({ step: 8 });
40
+ ```
41
+
42
+ ### 2. 문단을 canvas에 그리고, 필요하면 geometry로 바꾸기
43
+
44
+ ```js
45
+ const paragraph = font.paragraph("캔버스에서 자동 줄바꿈되는 문단입니다.", {
46
+ x: 40,
47
+ y: 80,
48
+ size: 32,
49
+ lineHeight: 1.4,
50
+ align: "left",
51
+ wrap: "word",
52
+ padding: { x: 24, y: 20 },
53
+ });
54
+
55
+ paragraph.drawText(ctx, {
56
+ fillStyle: "#111",
57
+ });
58
+
59
+ const shape = paragraph.toShape();
60
+ const regions = paragraph.toRegions({ step: 6, openWidth: 1 });
61
+ ```
62
+
63
+ ## Font API
64
+
65
+ ### `paFont.load(source, options?)`
66
+
67
+ 폰트를 로드합니다.
68
+
69
+ - `source`: `string | URL | ArrayBuffer | ArrayBufferView`
70
+ - `options.base`: 모듈 기준 상대 경로 해석용
71
+
72
+ 브라우저에서는 `load()`한 폰트가 canvas용으로도 자동 등록되며,
73
+ `font.paragraph(...).drawText()`는 기본적으로 이 폰트를 사용합니다.
74
+
75
+ ### `font.text(value, options?)`
76
+
77
+ 문자열 전체를 `PAShape`로 만듭니다.
78
+
79
+ 주요 옵션:
80
+
81
+ - `x`, `y`: baseline 시작 위치
82
+ - `size`: 글자 크기
83
+ - `flatten`: 곡선 평탄화 허용 오차
84
+ - `kerning`, `letterSpacing`, `tracking`
85
+ - `script`, `language`, `features`
86
+
87
+ ### `font.glyph(value, options?)`
88
+
89
+ 한 글자만 `PAShape`로 만듭니다.
90
+
91
+ ### `font.metrics(value, options?)`
92
+
93
+ 텍스트 폭과 bounding box만 빠르게 계산합니다.
94
+
95
+ ```js
96
+ const metrics = font.metrics("안녕", { size: 120 });
97
+ console.log(metrics.width, metrics.bbox);
98
+ ```
99
+
100
+ ### `font.paragraph(value, options?)`
101
+
102
+ 문단 레이아웃 객체 `paParagraph`를 만듭니다.
103
+
104
+ 추천 옵션:
105
+
106
+ - `wrap`: `word | char | keep`
107
+ - `margin`, `padding`: `24`, `"24 32"`, `[24, 32]`, `{ x: 32, y: 24 }`, `{ top, right, bottom, left }`
108
+ - `width`: 생략하면 `drawText(ctx)` 시 현재 canvas 폭 기준으로 자동 계산
109
+ - `height`: `overflow: "hidden"`과 같이 쓰면 clip/clamp
110
+ - `x`, `y`, `size`, `lineHeight`, `align`
111
+
112
+ 세부 제어 옵션:
113
+
114
+ - `whiteSpace`: `normal | pre-wrap | nowrap`
115
+ - `overflowWrap`: `normal | break-word | anywhere`
116
+ - `wordBreak`: `normal | break-all | keep-all`
117
+ - `overflow`: `visible | hidden`
118
+ - `textOverflow`: `clip | ellipsis`
119
+ - `fontFamily`, `fontWeight`, `fontStyle`, `font`
120
+ - `engine`: `pretext | native`
121
+ - `maxLines`, `ellipsis`
122
+
123
+ `wrap` 기본값은 `word`이며, 다음 조합의 shorthand입니다.
124
+
125
+ - `word`: `wordBreak: "normal"` + `overflowWrap: "break-word"`
126
+ - `char`: `wordBreak: "break-all"`
127
+ - `keep`: `wordBreak: "keep-all"` + `overflowWrap: "normal"`
128
+
129
+ `wordBreak` / `overflowWrap`를 직접 주면 `wrap`보다 우선합니다.
130
+
131
+ ## paParagraph API
132
+
133
+ `font.paragraph()`는 `paParagraph`를 반환합니다.
134
+
135
+ 주요 속성:
136
+
137
+ - `paragraph.text`
138
+ - `paragraph.lines`
139
+ - `paragraph.metrics`
140
+ - `paragraph.options`
141
+ - `paragraph.layoutEngine`
142
+
143
+ 주요 메서드:
144
+
145
+ ### `paragraph.relayout(next?)`
146
+
147
+ 폭이나 정렬이 바뀌었을 때 문단을 다시 레이아웃합니다.
148
+
149
+ ```js
150
+ const mobile = paragraph.relayout({ width: 280 });
151
+ ```
152
+
153
+ `width`를 생략한 문단은 `drawText(ctx)` 시 현재 canvas 폭에 맞춰 자동으로 다시 레이아웃됩니다.
154
+
155
+ 기본 `wrap: "word"` 경로는 `pretext`를 우선 사용하고, `break-all` / `keep-all` 또는
156
+ 엄격한 `overflowWrap: "normal"`이 필요한 경우만 native로 내려갑니다.
157
+ 실제로 사용된 엔진은 `paragraph.layoutEngine`에서 확인할 수 있습니다.
158
+
159
+ ### `paragraph.drawText(ctx, options?)`
160
+
161
+ 현재 문단 레이아웃을 canvas 텍스트로 그립니다.
162
+
163
+ ```js
164
+ paragraph.drawText(ctx, {
165
+ fillStyle: "#111",
166
+ });
167
+ ```
168
+
169
+ 옵션:
170
+
171
+ - `fillStyle`
172
+ - `strokeStyle`
173
+ - `fill`
174
+ - `stroke`
175
+
176
+ ### `paragraph.toShape(options?)`
177
+
178
+ 문단 전체를 하나의 `PAShape`로 변환합니다.
179
+
180
+ ```js
181
+ const shape = paragraph.toShape({
182
+ layout: "current",
183
+ step: 6,
184
+ openWidth: 1,
185
+ });
186
+ ```
187
+
188
+ ### `paragraph.toRegions(options?)`
189
+
190
+ 문단 전체를 plain region 데이터로 반환합니다.
191
+
192
+ ### `paragraph.toPoints(options?)`
193
+
194
+ 문단 전체를 점 샘플로 반환합니다.
195
+
196
+ 공통 옵션:
197
+
198
+ - `layout`: `current | pretext | native`
199
+ - `step`
200
+ - `openWidth`
201
+ - `includeHoles` (`toPoints()` 전용)
202
+
203
+ `layout` 의미:
204
+
205
+ - `current`: 현재 문단 줄바꿈 그대로 사용
206
+ - `pretext`: `pretext` 기준으로 다시 줄 계산
207
+ - `native`: `opentype.js` 측정 기준으로 다시 줄 계산
208
+
209
+ ## PAShape API
210
+
211
+ `font.text()`와 `font.glyph()`는 `PAShape`를 반환합니다.
212
+
213
+ 주요 속성:
214
+
215
+ - `shape.text`
216
+ - `shape.bbox`
217
+ - `shape.metrics`
218
+ - `shape.polygons`
219
+
220
+ 주요 메서드:
221
+
222
+ ### `shape.glyphs()`
223
+
224
+ 문장을 글자별 `PAShape[]`로 나눕니다.
225
+
226
+ ### `shape.toShape({ step, openWidth })`
227
+
228
+ 변형된 새 `PAShape`를 반환합니다.
229
+
230
+ - `step`: polygon 재샘플링 간격
231
+ - `openWidth`: hole을 slit처럼 열기 위한 폭
232
+
233
+ ### `shape.toRegions({ step, openWidth })`
234
+
235
+ 최종 polygon 데이터를 반환합니다.
236
+
237
+ 반환 형태:
238
+
239
+ ```js
240
+ [
241
+ {
242
+ outer: [[x, y], ...],
243
+ holes: [
244
+ [[x, y], ...],
245
+ ],
246
+ bbox: { x, y, w, h },
247
+ },
248
+ ];
249
+ ```
250
+
251
+ ### `shape.toPoints({ step, openWidth, includeHoles })`
252
+
253
+ 경계를 일정 간격의 점들로 샘플링합니다.
254
+
255
+ ### `shape.hit(x, y)` / `shape.contains(x, y)`
256
+
257
+ 도형 hit test를 합니다.
258
+
259
+ ## 언제 무엇을 쓰나
260
+
261
+ - 편집/후처리를 계속할 거면 `toShape()`
262
+ - 정확한 polygon 데이터가 필요하면 `toRegions()`
263
+ - 점 기반 효과나 입자용이면 `toPoints()`
264
+ - 문단을 화면에 바로 그리고 싶으면 `paragraph.drawText(ctx)`
265
+ - 같은 문단을 geometry로 쓰고 싶으면 `paragraph.toShape()`
266
+
267
+ ## CSS-like 예시
268
+
269
+ ```js
270
+ const paragraph = font.paragraph(text, {
271
+ x: 0,
272
+ y: 0,
273
+ size: 20,
274
+ lineHeight: 1.6,
275
+ padding: { x: 32, y: 24 },
276
+ margin: "20 0 0 20",
277
+ wrap: "char",
278
+ overflow: "hidden",
279
+ textOverflow: "ellipsis",
280
+ });
281
+
282
+ paragraph.drawText(ctx);
283
+ ```
284
+
285
+ 이 구현은 CSS를 완전히 복제하는 엔진은 아니지만, canvas 문단 작업에 필요한
286
+ `width auto`, `padding`, `margin`, `wordBreak`, `overflow`, `textOverflow`를
287
+ 가깝게 사용할 수 있도록 설계되어 있습니다.
288
+
289
+ ## 주의
290
+
291
+ - `paragraph.drawText()`는 canvas 텍스트 렌더링입니다.
292
+ - `fontFamily`를 생략하면 브라우저에서는 `paFont.load()`로 불러온 폰트가 기본값으로 사용됩니다.
293
+ - 별도의 CSS webfont를 쓰고 싶으면 `fontFamily` 또는 `font`로 override하면 됩니다.
294
+ - `step`, `openWidth`는 모두 절대 좌표 단위입니다.