-
Notifications
You must be signed in to change notification settings - Fork 35
/
Font.java
691 lines (632 loc) · 21.9 KB
/
Font.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
package io.github.humbleui.skija;
import java.util.function.*;
import org.jetbrains.annotations.*;
import io.github.humbleui.skija.impl.*;
import io.github.humbleui.types.*;
public class Font extends Managed {
static { Library.staticLoad(); }
@ApiStatus.Internal public FontMetrics _metrics = null;
@ApiStatus.Internal public Float _spacing = null;
@ApiStatus.Internal
public Font(long ptr) {
super(ptr, _FinalizerHolder.PTR);
}
@ApiStatus.Internal
public Font(long ptr, boolean managed) {
super(ptr, _FinalizerHolder.PTR, managed);
}
/**
* Returns Font initialized with default values
*/
public Font() {
this(_nMakeDefault());
Stats.onNativeCall();
}
/**
* Returns Font with Typeface and default size
*
* @param typeface typeface and style used to draw and measure text. Pass null for default
*/
public Font(@Nullable Typeface typeface) {
this(_nMakeTypeface(Native.getPtr(typeface)));
Stats.onNativeCall();
ReferenceUtil.reachabilityFence(typeface);
}
/**
* @param typeface typeface and style used to draw and measure text. Pass null for default
* @param size typographic size of the text
*/
public Font(@Nullable Typeface typeface, float size) {
this(_nMakeTypefaceSize(Native.getPtr(typeface), size));
Stats.onNativeCall();
ReferenceUtil.reachabilityFence(typeface);
}
/**
* Constructs Font with default values with Typeface and size in points,
* horizontal scale, and horizontal skew. Horizontal scale emulates condensed
* and expanded fonts. Horizontal skew emulates oblique fonts.
*
* @param typeface typeface and style used to draw and measure text. Pass null for default
* @param size typographic size of the text
* @param scaleX text horizonral scale
* @param skewX additional shear on x-axis relative to y-axis
*/
public Font(@Nullable Typeface typeface, float size, float scaleX, float skewX) {
this(_nMakeTypefaceSizeScaleSkew(Native.getPtr(typeface), size, scaleX, skewX));
Stats.onNativeCall();
ReferenceUtil.reachabilityFence(typeface);
}
/**
* Compares fonts, and returns true if they are equivalent.
* May return false if Typeface has identical contents but different pointers.
*/
@ApiStatus.Internal @Override
public boolean _nativeEquals(Native other) {
try {
return _nEquals(_ptr, Native.getPtr(other));
} finally {
ReferenceUtil.reachabilityFence(this);
ReferenceUtil.reachabilityFence(other);
}
}
@ApiStatus.Internal
public void _resetMetrics() {
_metrics = null;
_spacing = null;
}
@ApiStatus.Internal
public static Font makeClone(long ptr) {
Stats.onNativeCall();
return new Font(_nMakeClone(ptr));
}
/**
* If true, instructs the font manager to always hint glyphs.
* Returned value is only meaningful if platform uses FreeType as the font manager.
*
* @return true if all glyphs are hinted
*/
public boolean isAutoHintingForced() {
try {
Stats.onNativeCall();
return _nIsAutoHintingForced(_ptr);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* @return true if font engine may return glyphs from font bitmaps instead of from outlines
*/
public boolean areBitmapsEmbedded() {
try {
Stats.onNativeCall();
return _nAreBitmapsEmbedded(_ptr);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* @return true if glyphs may be drawn at sub-pixel offsets
*/
public boolean isSubpixel() {
try {
Stats.onNativeCall();
return _nIsSubpixel(_ptr);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* @return true if font and glyph metrics are requested to be linearly scalable
*/
public boolean areMetricsLinear() {
try {
Stats.onNativeCall();
return _nAreMetricsLinear(_ptr);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* Returns true if bold is approximated by increasing the stroke width when creating glyph
* bitmaps from outlines.
*
* @return true if bold is approximated through stroke width
*/
public boolean isEmboldened() {
try {
Stats.onNativeCall();
return _nIsEmboldened(_ptr);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* Returns true if baselines will be snapped to pixel positions when the current transformation
* matrix is axis aligned.
*
* @return true if baselines may be snapped to pixels
*/
public boolean isBaselineSnapped() {
try {
Stats.onNativeCall();
return _nIsBaselineSnapped(_ptr);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* Sets whether to always hint glyphs. If forceAutoHinting is set, instructs the font manager to always hint glyphs. Only affects platforms that use FreeType as the font manager.
*
* @param value setting to always hint glyphs
* @return this
*/
public Font setAutoHintingForced(boolean value) {
_resetMetrics();
Stats.onNativeCall();
_nSetAutoHintingForced(_ptr, value);
return this;
}
/**
* Requests, but does not require, to use bitmaps in fonts instead of outlines.
*
* @param value setting to use bitmaps in fonts
* @return this
*/
public Font setBitmapsEmbedded(boolean value) {
_resetMetrics();
Stats.onNativeCall();
_nSetBitmapsEmbedded(_ptr, value);
return this;
}
/**
* Requests, but does not require, that glyphs respect sub-pixel positioning.
*
* @param value setting for sub-pixel positioning
* @return this
*/
public Font setSubpixel(boolean value) {
_resetMetrics();
Stats.onNativeCall();
_nSetSubpixel(_ptr, value);
return this;
}
/**
* Requests, but does not require, linearly scalable font and glyph metrics.
*
* For outline fonts 'true' means font and glyph metrics should ignore hinting and rounding.
* Note that some bitmap formats may not be able to scale linearly and will ignore this flag.
*
* @param value setting for linearly scalable font and glyph metrics.
* @return this
*/
public Font setMetricsLinear(boolean value) {
_resetMetrics();
Stats.onNativeCall();
_nSetMetricsLinear(_ptr, value);
return this;
}
/**
* Increases stroke width when creating glyph bitmaps to approximate a bold typeface.
*
* @param value setting for bold approximation
* @return this
*/
public Font setEmboldened(boolean value) {
_resetMetrics();
Stats.onNativeCall();
_nSetEmboldened(_ptr, value);
return this;
}
/**
* Requests that baselines be snapped to pixels when the current transformation matrix is axis
* aligned.
*
* @param value setting for baseline snapping to pixels
* @return this
*/
public Font setBaselineSnapped(boolean value) {
_resetMetrics();
Stats.onNativeCall();
_nSetBaselineSnapped(_ptr, value);
return this;
}
/**
* Whether edge pixels draw opaque or with partial transparency.
*/
public FontEdging getEdging() {
try {
Stats.onNativeCall();
return FontEdging._values[_nGetEdging(_ptr)];
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* Requests, but does not require, that edge pixels draw opaque or with
* partial transparency.
*/
public Font setEdging(FontEdging value) {
_resetMetrics();
Stats.onNativeCall();
_nSetEdging(_ptr, value.ordinal());
return this;
}
/**
* @return level of glyph outline adjustment
*/
public FontHinting getHinting() {
try {
Stats.onNativeCall();
return FontHinting._values[_nGetHinting(_ptr)];
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* Sets level of glyph outline adjustment. Does not check for valid values of hintingLevel.
*/
public Font setHinting(FontHinting value) {
_resetMetrics();
Stats.onNativeCall();
_nSetHinting(_ptr, value.ordinal());
return this;
}
/**
* Returns a font with the same attributes of this font, but with the specified size.
*/
public Font makeWithSize(float size) {
return new Font(getTypeface(), size, getScaleX(), getSkewX());
}
/**
* @return {@link Typeface} if set, or null
*/
@Nullable
public Typeface getTypeface() {
try {
Stats.onNativeCall();
long ptr = _nGetTypeface(_ptr);
return ptr == 0 ? null : new Typeface(ptr);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* @return {@link Typeface} if set, or the default typeface.
*/
@NotNull
public Typeface getTypefaceOrDefault() {
try {
Stats.onNativeCall();
return new Typeface(_nGetTypefaceOrDefault(_ptr));
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* @return text size in points
*/
public float getSize() {
try {
Stats.onNativeCall();
return _nGetSize(_ptr);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* @return text scale on x-axis. Default value is 1
*/
public float getScaleX() {
try {
Stats.onNativeCall();
return _nGetScaleX(_ptr);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* @return text skew on x-axis. Default value is 0
*/
public float getSkewX() {
try {
Stats.onNativeCall();
return _nGetSkewX(_ptr);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* Sets Typeface to typeface. Pass null to use the default typeface.
*/
public Font setTypeface(@Nullable Typeface typeface) {
try {
_resetMetrics();
Stats.onNativeCall();
_nSetTypeface(_ptr, Native.getPtr(typeface));
return this;
} finally {
ReferenceUtil.reachabilityFence(typeface);
}
}
/**
* Sets text size in points. Has no effect if value is not greater than or equal to zero.
*/
public Font setSize(float value) {
_resetMetrics();
Stats.onNativeCall();
_nSetSize(_ptr, value);
return this;
}
/**
* Sets text scale on x-axis. Default value is 1.
*/
public Font setScaleX(float value) {
_resetMetrics();
Stats.onNativeCall();
_nSetScaleX(_ptr, value);
return this;
}
/**
* Sets text skew on x-axis. Default value is 0.
*/
public Font setSkewX(float value) {
_resetMetrics();
Stats.onNativeCall();
_nSetSkewX(_ptr, value);
return this;
}
/**
* Converts text into glyph indices.
*
* @return the corresponding glyph ids for each character.
*/
public short[] getStringGlyphs(String s) {
return getUTF32Glyphs(s.codePoints().toArray());
}
/**
* Given an array of UTF32 character codes, return their corresponding glyph IDs.
*
* @return the corresponding glyph IDs for each character.
*/
public short[] getUTF32Glyphs(int[] uni) {
try {
Stats.onNativeCall();
return _nGetUTF32Glyphs(_ptr, uni);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* @return the glyph that corresponds to the specified unicode code-point (in UTF32 encoding). If the unichar is not supported, returns 0
*/
public short getUTF32Glyph(int unichar) {
try {
Stats.onNativeCall();
return _nGetUTF32Glyph(_ptr, unichar);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* @return number of glyphs represented by text
*/
public int getStringGlyphsCount(String s) {
try {
Stats.onNativeCall();
return _nGetStringGlyphsCount(_ptr, s);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* @return the bounding box of text
*/
public Rect measureText(String s) {
return measureText(s, null);
}
/**
* @param p stroke width or PathEffect may modify the advance with
* @return the bounding box of text
*/
public Rect measureText(String s, Paint p) {
try {
Stats.onNativeCall();
return _nMeasureText(_ptr, s, Native.getPtr(p));
} finally {
ReferenceUtil.reachabilityFence(this);
ReferenceUtil.reachabilityFence(p);
}
}
public float measureTextWidth(String s) {
Stats.onNativeCall();
return measureTextWidth(s, null);
}
public float measureTextWidth(String s, Paint p) {
try {
Stats.onNativeCall();
return _nMeasureTextWidth(_ptr, s, Native.getPtr(p));
} finally {
ReferenceUtil.reachabilityFence(this);
ReferenceUtil.reachabilityFence(p);
}
}
/**
* Retrieves the advances for each glyph
*/
public float[] getWidths(short[] glyphs) {
try {
Stats.onNativeCall();
return _nGetWidths(_ptr, glyphs);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* Retrieves the bounds for each glyph
*/
public Rect[] getBounds(short[] glyphs) {
return getBounds(glyphs, null);
}
/**
* Retrieves the bounds for each glyph
*/
public Rect[] getBounds(short[] glyphs, Paint p) {
try {
Stats.onNativeCall();
return _nGetBounds(_ptr, glyphs, Native.getPtr(p));
} finally {
ReferenceUtil.reachabilityFence(this);
ReferenceUtil.reachabilityFence(p);
}
}
/**
* Retrieves the positions for each glyph.
*/
public Point[] getPositions(short[] glyphs) {
try {
Stats.onNativeCall();
return _nGetPositions(_ptr, glyphs, 0, 0);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* Retrieves the positions for each glyph, beginning at the specified origin.
*/
public Point[] getPositions(short[] glyphs, Point offset) {
try {
Stats.onNativeCall();
return _nGetPositions(_ptr, glyphs, offset._x, offset._y);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* Retrieves the x-positions for each glyph.
*/
public float[] getXPositions(short[] glyphs) {
try {
Stats.onNativeCall();
return _nGetXPositions(_ptr, glyphs, 0);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* Retrieves the x-positions for each glyph, beginning at the specified origin.
*/
public float[] getXPositions(short[] glyphs, float offset) {
try {
Stats.onNativeCall();
return _nGetXPositions(_ptr, glyphs, offset);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* If the glyph has an outline, returns it. The glyph outline may be empty.
* Degenerate contours in the glyph outline will be skipped. If glyph is described by a bitmap, returns null.
*/
@Nullable
public Path getPath(short glyph) {
try {
Stats.onNativeCall();
long ptr = _nGetPath(_ptr, glyph);
return ptr == 0 ? null : new Path(ptr);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* Return glyph outlines, some of which might be null.
*/
public Path[] getPaths(short[] glyphs) {
try {
Stats.onNativeCall();
return _nGetPaths(_ptr, glyphs);
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* Returns FontMetrics associated with Typeface. Results are scaled by text size but does not take into account
* dimensions required by text scale, text skew, fake bold, style stroke, and {@link PathEffect}.
*/
@NotNull
public FontMetrics getMetrics() {
try {
if (_metrics == null) {
Stats.onNativeCall();
_metrics = _nGetMetrics(_ptr);
}
return _metrics;
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
/**
* Returns the recommended spacing between lines: the sum of metrics descent, ascent, and leading.
* Result is scaled by text size but does not take into account dimensions required by stroking and SkPathEffect.
*/
public float getSpacing() {
try {
if (_spacing == null) {
Stats.onNativeCall();
_spacing = _nGetSpacing(_ptr);
}
return _spacing;
} finally {
ReferenceUtil.reachabilityFence(this);
}
}
@ApiStatus.Internal
public static class _FinalizerHolder {
public static final long PTR = _nGetFinalizer();
}
@ApiStatus.Internal public static native long _nGetFinalizer();
@ApiStatus.Internal public static native long _nMakeDefault();
@ApiStatus.Internal public static native long _nMakeTypeface(long typefacePtr);
@ApiStatus.Internal public static native long _nMakeTypefaceSize(long typefacePtr, float size);
@ApiStatus.Internal public static native long _nMakeTypefaceSizeScaleSkew(long typefacePtr, float size, float scaleX, float skewX);
@ApiStatus.Internal public static native long _nMakeClone(long ptr);
@ApiStatus.Internal public static native boolean _nEquals(long ptr, long otherPtr);
@ApiStatus.Internal public static native boolean _nIsAutoHintingForced(long ptr);
@ApiStatus.Internal public static native boolean _nAreBitmapsEmbedded(long ptr);
@ApiStatus.Internal public static native boolean _nIsSubpixel(long ptr);
@ApiStatus.Internal public static native boolean _nAreMetricsLinear(long ptr);
@ApiStatus.Internal public static native boolean _nIsEmboldened(long ptr);
@ApiStatus.Internal public static native boolean _nIsBaselineSnapped(long ptr);
@ApiStatus.Internal public static native void _nSetAutoHintingForced(long ptr, boolean value);
@ApiStatus.Internal public static native void _nSetBitmapsEmbedded(long ptr, boolean value);
@ApiStatus.Internal public static native void _nSetSubpixel(long ptr, boolean value);
@ApiStatus.Internal public static native void _nSetMetricsLinear(long ptr, boolean value);
@ApiStatus.Internal public static native void _nSetEmboldened(long ptr, boolean value);
@ApiStatus.Internal public static native void _nSetBaselineSnapped(long ptr, boolean value);
@ApiStatus.Internal public static native int _nGetEdging(long ptr);
@ApiStatus.Internal public static native void _nSetEdging(long ptr, int value);
@ApiStatus.Internal public static native int _nGetHinting(long ptr);
@ApiStatus.Internal public static native void _nSetHinting(long ptr, int value);
@ApiStatus.Internal public static native long _nGetTypeface(long ptr);
@ApiStatus.Internal public static native long _nGetTypefaceOrDefault(long ptr);
@ApiStatus.Internal public static native float _nGetSize(long ptr);
@ApiStatus.Internal public static native float _nGetScaleX(long ptr);
@ApiStatus.Internal public static native float _nGetSkewX(long ptr);
@ApiStatus.Internal public static native void _nSetTypeface(long ptr, long typefacePtr);
@ApiStatus.Internal public static native void _nSetSize(long ptr, float value);
@ApiStatus.Internal public static native void _nSetScaleX(long ptr, float value);
@ApiStatus.Internal public static native void _nSetSkewX(long ptr, float value);
@ApiStatus.Internal public static native short[] _nGetStringGlyphs(long ptr, String str);
@ApiStatus.Internal public static native short _nGetUTF32Glyph(long ptr, int uni);
@ApiStatus.Internal public static native short[] _nGetUTF32Glyphs(long ptr, int[] uni);
@ApiStatus.Internal public static native int _nGetStringGlyphsCount(long ptr, String str);
@ApiStatus.Internal public static native Rect _nMeasureText(long ptr, String str, long paintPtr);
@ApiStatus.Internal public static native float _nMeasureTextWidth(long ptr, String str, long paintPtr);
@ApiStatus.Internal public static native float[] _nGetWidths(long ptr, short[] glyphs);
@ApiStatus.Internal public static native Rect[] _nGetBounds(long ptr, short[] glyphs, long paintPtr);
@ApiStatus.Internal public static native Point[] _nGetPositions(long ptr, short[] glyphs, float x, float y);
@ApiStatus.Internal public static native float[] _nGetXPositions(long ptr, short[] glyphs, float x);
@ApiStatus.Internal public static native long _nGetPath(long ptr, short glyph);
@ApiStatus.Internal public static native Path[] _nGetPaths(long ptr, short[] glyphs);
@ApiStatus.Internal public static native FontMetrics _nGetMetrics(long ptr);
@ApiStatus.Internal public static native float _nGetSpacing(long ptr);
}