Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/classes/sun/font/AttributeValues.java
41155 views
1
/*
2
* Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
/*
27
*
28
* (C) Copyright IBM Corp. 2005 - All Rights Reserved
29
*
30
* The original version of this source code and documentation is
31
* copyrighted and owned by IBM. These materials are provided
32
* under terms of a License Agreement between IBM and Sun.
33
* This technology is protected by multiple US and International
34
* patents. This notice and attribution to IBM may not be removed.
35
*/
36
37
package sun.font;
38
39
import static sun.font.EAttribute.*;
40
import static java.lang.Math.*;
41
42
import java.awt.Font;
43
import java.awt.Paint;
44
import java.awt.Toolkit;
45
import java.awt.font.GraphicAttribute;
46
import java.awt.font.NumericShaper;
47
import java.awt.font.TextAttribute;
48
import java.awt.font.TransformAttribute;
49
import java.awt.geom.AffineTransform;
50
import java.awt.geom.NoninvertibleTransformException;
51
import java.awt.geom.Point2D;
52
import java.awt.im.InputMethodHighlight;
53
import java.io.Serializable;
54
import java.text.Annotation;
55
import java.text.AttributedCharacterIterator.Attribute;
56
import java.util.Map;
57
import java.util.HashMap;
58
import java.util.Hashtable;
59
60
public final class AttributeValues implements Cloneable {
61
private int defined;
62
private int nondefault;
63
64
private String family = "Default";
65
private float weight = 1f;
66
private float width = 1f;
67
private float posture; // 0f
68
private float size = 12f;
69
private float tracking; // 0f
70
private NumericShaper numericShaping; // null
71
private AffineTransform transform; // null == identity
72
private GraphicAttribute charReplacement; // null
73
private Paint foreground; // null
74
private Paint background; // null
75
private float justification = 1f;
76
private Object imHighlight; // null
77
// (can be either Attribute wrapping IMH, or IMH itself
78
private Font font; // here for completeness, don't actually use
79
private byte imUnderline = -1; // same default as underline
80
private byte superscript; // 0
81
private byte underline = -1; // arrgh, value for ON is 0
82
private byte runDirection = -2; // BIDI.DIRECTION_DEFAULT_LEFT_TO_RIGHT
83
private byte bidiEmbedding; // 0
84
private byte kerning; // 0
85
private byte ligatures; // 0
86
private boolean strikethrough; // false
87
private boolean swapColors; // false
88
89
private AffineTransform baselineTransform; // derived from transform
90
private AffineTransform charTransform; // derived from transform
91
92
private static final AttributeValues DEFAULT = new AttributeValues();
93
94
// type-specific API
95
public String getFamily() { return family; }
96
public void setFamily(String f) { this.family = f; update(EFAMILY); }
97
98
public float getWeight() { return weight; }
99
public void setWeight(float f) { this.weight = f; update(EWEIGHT); }
100
101
public float getWidth() { return width; }
102
public void setWidth(float f) { this.width = f; update(EWIDTH); }
103
104
public float getPosture() { return posture; }
105
public void setPosture(float f) { this.posture = f; update(EPOSTURE); }
106
107
public float getSize() { return size; }
108
public void setSize(float f) { this.size = f; update(ESIZE); }
109
110
public AffineTransform getTransform() { return transform; }
111
public void setTransform(AffineTransform f) {
112
this.transform = (f == null || f.isIdentity())
113
? DEFAULT.transform
114
: new AffineTransform(f);
115
updateDerivedTransforms();
116
update(ETRANSFORM);
117
}
118
public void setTransform(TransformAttribute f) {
119
this.transform = (f == null || f.isIdentity())
120
? DEFAULT.transform
121
: f.getTransform();
122
updateDerivedTransforms();
123
update(ETRANSFORM);
124
}
125
126
public int getSuperscript() { return superscript; }
127
public void setSuperscript(int f) {
128
this.superscript = (byte)f; update(ESUPERSCRIPT); }
129
130
public Font getFont() { return font; }
131
public void setFont(Font f) { this.font = f; update(EFONT); }
132
133
public GraphicAttribute getCharReplacement() { return charReplacement; }
134
public void setCharReplacement(GraphicAttribute f) {
135
this.charReplacement = f; update(ECHAR_REPLACEMENT); }
136
137
public Paint getForeground() { return foreground; }
138
public void setForeground(Paint f) {
139
this.foreground = f; update(EFOREGROUND); }
140
141
public Paint getBackground() { return background; }
142
public void setBackground(Paint f) {
143
this.background = f; update(EBACKGROUND); }
144
145
public int getUnderline() { return underline; }
146
public void setUnderline(int f) {
147
this.underline = (byte)f; update(EUNDERLINE); }
148
149
public boolean getStrikethrough() { return strikethrough; }
150
public void setStrikethrough(boolean f) {
151
this.strikethrough = f; update(ESTRIKETHROUGH); }
152
153
public int getRunDirection() { return runDirection; }
154
public void setRunDirection(int f) {
155
this.runDirection = (byte)f; update(ERUN_DIRECTION); }
156
157
public int getBidiEmbedding() { return bidiEmbedding; }
158
public void setBidiEmbedding(int f) {
159
this.bidiEmbedding = (byte)f; update(EBIDI_EMBEDDING); }
160
161
public float getJustification() { return justification; }
162
public void setJustification(float f) {
163
this.justification = f; update(EJUSTIFICATION); }
164
165
public Object getInputMethodHighlight() { return imHighlight; }
166
public void setInputMethodHighlight(Annotation f) {
167
this.imHighlight = f; update(EINPUT_METHOD_HIGHLIGHT); }
168
public void setInputMethodHighlight(InputMethodHighlight f) {
169
this.imHighlight = f; update(EINPUT_METHOD_HIGHLIGHT); }
170
171
public int getInputMethodUnderline() { return imUnderline; }
172
public void setInputMethodUnderline(int f) {
173
this.imUnderline = (byte)f; update(EINPUT_METHOD_UNDERLINE); }
174
175
public boolean getSwapColors() { return swapColors; }
176
public void setSwapColors(boolean f) {
177
this.swapColors = f; update(ESWAP_COLORS); }
178
179
public NumericShaper getNumericShaping() { return numericShaping; }
180
public void setNumericShaping(NumericShaper f) {
181
this.numericShaping = f; update(ENUMERIC_SHAPING); }
182
183
public int getKerning() { return kerning; }
184
public void setKerning(int f) {
185
this.kerning = (byte)f; update(EKERNING); }
186
187
public float getTracking() { return tracking; }
188
public void setTracking(float f) {
189
this.tracking = (byte)f; update(ETRACKING); }
190
191
public int getLigatures() { return ligatures; }
192
public void setLigatures(int f) {
193
this.ligatures = (byte)f; update(ELIGATURES); }
194
195
196
public AffineTransform getBaselineTransform() { return baselineTransform; }
197
public AffineTransform getCharTransform() { return charTransform; }
198
199
// mask api
200
201
public static int getMask(EAttribute att) {
202
return att.mask;
203
}
204
205
public static int getMask(EAttribute ... atts) {
206
int mask = 0;
207
for (EAttribute a: atts) {
208
mask |= a.mask;
209
}
210
return mask;
211
}
212
213
public static final int MASK_ALL =
214
getMask(EAttribute.class.getEnumConstants());
215
216
public void unsetDefault() {
217
defined &= nondefault;
218
}
219
220
public void defineAll(int mask) {
221
defined |= mask;
222
if ((defined & EBASELINE_TRANSFORM.mask) != 0) {
223
throw new InternalError("can't define derived attribute");
224
}
225
}
226
227
public boolean allDefined(int mask) {
228
return (defined & mask) == mask;
229
}
230
231
public boolean anyDefined(int mask) {
232
return (defined & mask) != 0;
233
}
234
235
public boolean anyNonDefault(int mask) {
236
return (nondefault & mask) != 0;
237
}
238
239
// generic EAttribute API
240
241
public boolean isDefined(EAttribute a) {
242
return (defined & a.mask) != 0;
243
}
244
245
public boolean isNonDefault(EAttribute a) {
246
return (nondefault & a.mask) != 0;
247
}
248
249
public void setDefault(EAttribute a) {
250
if (a.att == null) {
251
throw new InternalError("can't set default derived attribute: " + a);
252
}
253
i_set(a, DEFAULT);
254
defined |= a.mask;
255
nondefault &= ~a.mask;
256
}
257
258
public void unset(EAttribute a) {
259
if (a.att == null) {
260
throw new InternalError("can't unset derived attribute: " + a);
261
}
262
i_set(a, DEFAULT);
263
defined &= ~a.mask;
264
nondefault &= ~a.mask;
265
}
266
267
public void set(EAttribute a, AttributeValues src) {
268
if (a.att == null) {
269
throw new InternalError("can't set derived attribute: " + a);
270
}
271
if (src == null || src == DEFAULT) {
272
setDefault(a);
273
} else {
274
if ((src.defined & a.mask) != 0) {
275
i_set(a, src);
276
update(a);
277
}
278
}
279
}
280
281
public void set(EAttribute a, Object o) {
282
if (a.att == null) {
283
throw new InternalError("can't set derived attribute: " + a);
284
}
285
if (o != null) {
286
try {
287
i_set(a, o);
288
update(a);
289
return;
290
} catch (Exception e) {
291
}
292
}
293
setDefault(a);
294
}
295
296
public Object get(EAttribute a) {
297
if (a.att == null) {
298
throw new InternalError("can't get derived attribute: " + a);
299
}
300
if ((nondefault & a.mask) != 0) {
301
return i_get(a);
302
}
303
return null;
304
}
305
306
// merging
307
308
public AttributeValues merge(Map<? extends Attribute, ?>map) {
309
return merge(map, MASK_ALL);
310
}
311
312
public AttributeValues merge(Map<? extends Attribute, ?>map,
313
int mask) {
314
if (map instanceof AttributeMap &&
315
((AttributeMap) map).getValues() != null) {
316
merge(((AttributeMap)map).getValues(), mask);
317
} else if (map != null && !map.isEmpty()) {
318
for (Map.Entry<? extends Attribute, ?> e: map.entrySet()) {
319
try {
320
EAttribute ea = EAttribute.forAttribute(e.getKey());
321
if (ea!= null && (mask & ea.mask) != 0) {
322
set(ea, e.getValue());
323
}
324
} catch (ClassCastException cce) {
325
// IGNORED
326
}
327
}
328
}
329
return this;
330
}
331
332
public AttributeValues merge(AttributeValues src) {
333
return merge(src, MASK_ALL);
334
}
335
336
public AttributeValues merge(AttributeValues src, int mask) {
337
int m = mask & src.defined;
338
for (EAttribute ea: EAttribute.atts) {
339
if (m == 0) {
340
break;
341
}
342
if ((m & ea.mask) != 0) {
343
m &= ~ea.mask;
344
i_set(ea, src);
345
update(ea);
346
}
347
}
348
return this;
349
}
350
351
// creation API
352
353
public static AttributeValues fromMap(Map<? extends Attribute, ?> map) {
354
return fromMap(map, MASK_ALL);
355
}
356
357
public static AttributeValues fromMap(Map<? extends Attribute, ?> map,
358
int mask) {
359
return new AttributeValues().merge(map, mask);
360
}
361
362
public Map<TextAttribute, Object> toMap(Map<TextAttribute, Object> fill) {
363
if (fill == null) {
364
fill = new HashMap<TextAttribute, Object>();
365
}
366
367
for (int m = defined, i = 0; m != 0; ++i) {
368
EAttribute ea = EAttribute.atts[i];
369
if ((m & ea.mask) != 0) {
370
m &= ~ea.mask;
371
fill.put(ea.att, get(ea));
372
}
373
}
374
375
return fill;
376
}
377
378
// key must be serializable, so use String, not Object
379
private static final String DEFINED_KEY =
380
"sun.font.attributevalues.defined_key";
381
382
public static boolean is16Hashtable(Hashtable<Object, Object> ht) {
383
return ht.containsKey(DEFINED_KEY);
384
}
385
386
public static AttributeValues
387
fromSerializableHashtable(Hashtable<Object, Object> ht)
388
{
389
AttributeValues result = new AttributeValues();
390
if (ht != null && !ht.isEmpty()) {
391
for (Map.Entry<Object, Object> e: ht.entrySet()) {
392
Object key = e.getKey();
393
Object val = e.getValue();
394
if (key.equals(DEFINED_KEY)) {
395
result.defineAll(((Integer)val).intValue());
396
} else {
397
try {
398
EAttribute ea =
399
EAttribute.forAttribute((Attribute)key);
400
if (ea != null) {
401
result.set(ea, val);
402
}
403
}
404
catch (ClassCastException ex) {
405
}
406
}
407
}
408
}
409
return result;
410
}
411
412
public Hashtable<Object, Object> toSerializableHashtable() {
413
Hashtable<Object, Object> ht = new Hashtable<>();
414
int hashkey = defined;
415
for (int m = defined, i = 0; m != 0; ++i) {
416
EAttribute ea = EAttribute.atts[i];
417
if ((m & ea.mask) != 0) {
418
m &= ~ea.mask;
419
Object o = get(ea);
420
if (o == null) {
421
// hashkey will handle it
422
} else if (o instanceof Serializable) { // check all...
423
ht.put(ea.att, o);
424
} else {
425
hashkey &= ~ea.mask;
426
}
427
}
428
}
429
ht.put(DEFINED_KEY, Integer.valueOf(hashkey));
430
431
return ht;
432
}
433
434
// boilerplate
435
public int hashCode() {
436
return defined << 8 ^ nondefault;
437
}
438
439
public boolean equals(Object rhs) {
440
try {
441
return equals((AttributeValues)rhs);
442
}
443
catch (ClassCastException e) {
444
}
445
return false;
446
}
447
448
public boolean equals(AttributeValues rhs) {
449
// test in order of most likely to differ and easiest to compare
450
// also assumes we're generally calling this only if family,
451
// size, weight, posture are the same
452
453
if (rhs == null) return false;
454
if (rhs == this) return true;
455
456
return defined == rhs.defined
457
&& nondefault == rhs.nondefault
458
&& underline == rhs.underline
459
&& strikethrough == rhs.strikethrough
460
&& superscript == rhs.superscript
461
&& width == rhs.width
462
&& kerning == rhs.kerning
463
&& tracking == rhs.tracking
464
&& ligatures == rhs.ligatures
465
&& runDirection == rhs.runDirection
466
&& bidiEmbedding == rhs.bidiEmbedding
467
&& swapColors == rhs.swapColors
468
&& equals(transform, rhs.transform)
469
&& equals(foreground, rhs.foreground)
470
&& equals(background, rhs.background)
471
&& equals(numericShaping, rhs.numericShaping)
472
&& equals(justification, rhs.justification)
473
&& equals(charReplacement, rhs.charReplacement)
474
&& size == rhs.size
475
&& weight == rhs.weight
476
&& posture == rhs.posture
477
&& equals(family, rhs.family)
478
&& equals(font, rhs.font)
479
&& imUnderline == rhs.imUnderline
480
&& equals(imHighlight, rhs.imHighlight);
481
}
482
483
public AttributeValues clone() {
484
try {
485
AttributeValues result = (AttributeValues)super.clone();
486
if (transform != null) { // AffineTransform is mutable
487
result.transform = new AffineTransform(transform);
488
result.updateDerivedTransforms();
489
}
490
// if transform is null, derived transforms are null
491
// so there's nothing to do
492
return result;
493
}
494
catch (CloneNotSupportedException e) {
495
// never happens
496
return null;
497
}
498
}
499
500
public String toString() {
501
StringBuilder b = new StringBuilder();
502
b.append('{');
503
for (int m = defined, i = 0; m != 0; ++i) {
504
EAttribute ea = EAttribute.atts[i];
505
if ((m & ea.mask) != 0) {
506
m &= ~ea.mask;
507
if (b.length() > 1) {
508
b.append(", ");
509
}
510
b.append(ea);
511
b.append('=');
512
switch (ea) {
513
case EFAMILY: b.append('"');
514
b.append(family);
515
b.append('"'); break;
516
case EWEIGHT: b.append(weight); break;
517
case EWIDTH: b.append(width); break;
518
case EPOSTURE: b.append(posture); break;
519
case ESIZE: b.append(size); break;
520
case ETRANSFORM: b.append(transform); break;
521
case ESUPERSCRIPT: b.append(superscript); break;
522
case EFONT: b.append(font); break;
523
case ECHAR_REPLACEMENT: b.append(charReplacement); break;
524
case EFOREGROUND: b.append(foreground); break;
525
case EBACKGROUND: b.append(background); break;
526
case EUNDERLINE: b.append(underline); break;
527
case ESTRIKETHROUGH: b.append(strikethrough); break;
528
case ERUN_DIRECTION: b.append(runDirection); break;
529
case EBIDI_EMBEDDING: b.append(bidiEmbedding); break;
530
case EJUSTIFICATION: b.append(justification); break;
531
case EINPUT_METHOD_HIGHLIGHT: b.append(imHighlight); break;
532
case EINPUT_METHOD_UNDERLINE: b.append(imUnderline); break;
533
case ESWAP_COLORS: b.append(swapColors); break;
534
case ENUMERIC_SHAPING: b.append(numericShaping); break;
535
case EKERNING: b.append(kerning); break;
536
case ELIGATURES: b.append(ligatures); break;
537
case ETRACKING: b.append(tracking); break;
538
default: throw new InternalError();
539
}
540
if ((nondefault & ea.mask) == 0) {
541
b.append('*');
542
}
543
}
544
}
545
b.append("[btx=" + baselineTransform + ", ctx=" + charTransform + "]");
546
b.append('}');
547
return b.toString();
548
}
549
550
// internal utilities
551
552
private static boolean equals(Object lhs, Object rhs) {
553
return lhs == null ? rhs == null : lhs.equals(rhs);
554
}
555
556
private void update(EAttribute a) {
557
defined |= a.mask;
558
if (i_validate(a)) {
559
if (i_equals(a, DEFAULT)) {
560
nondefault &= ~a.mask;
561
} else {
562
nondefault |= a.mask;
563
}
564
} else {
565
setDefault(a);
566
}
567
}
568
569
// dispatch
570
571
private void i_set(EAttribute a, AttributeValues src) {
572
switch (a) {
573
case EFAMILY: family = src.family; break;
574
case EWEIGHT: weight = src.weight; break;
575
case EWIDTH: width = src.width; break;
576
case EPOSTURE: posture = src.posture; break;
577
case ESIZE: size = src.size; break;
578
case ETRANSFORM: transform = src.transform; updateDerivedTransforms(); break;
579
case ESUPERSCRIPT: superscript = src.superscript; break;
580
case EFONT: font = src.font; break;
581
case ECHAR_REPLACEMENT: charReplacement = src.charReplacement; break;
582
case EFOREGROUND: foreground = src.foreground; break;
583
case EBACKGROUND: background = src.background; break;
584
case EUNDERLINE: underline = src.underline; break;
585
case ESTRIKETHROUGH: strikethrough = src.strikethrough; break;
586
case ERUN_DIRECTION: runDirection = src.runDirection; break;
587
case EBIDI_EMBEDDING: bidiEmbedding = src.bidiEmbedding; break;
588
case EJUSTIFICATION: justification = src.justification; break;
589
case EINPUT_METHOD_HIGHLIGHT: imHighlight = src.imHighlight; break;
590
case EINPUT_METHOD_UNDERLINE: imUnderline = src.imUnderline; break;
591
case ESWAP_COLORS: swapColors = src.swapColors; break;
592
case ENUMERIC_SHAPING: numericShaping = src.numericShaping; break;
593
case EKERNING: kerning = src.kerning; break;
594
case ELIGATURES: ligatures = src.ligatures; break;
595
case ETRACKING: tracking = src.tracking; break;
596
default: throw new InternalError();
597
}
598
}
599
600
private boolean i_equals(EAttribute a, AttributeValues src) {
601
switch (a) {
602
case EFAMILY: return equals(family, src.family);
603
case EWEIGHT: return weight == src.weight;
604
case EWIDTH: return width == src.width;
605
case EPOSTURE: return posture == src.posture;
606
case ESIZE: return size == src.size;
607
case ETRANSFORM: return equals(transform, src.transform);
608
case ESUPERSCRIPT: return superscript == src.superscript;
609
case EFONT: return equals(font, src.font);
610
case ECHAR_REPLACEMENT: return equals(charReplacement, src.charReplacement);
611
case EFOREGROUND: return equals(foreground, src.foreground);
612
case EBACKGROUND: return equals(background, src.background);
613
case EUNDERLINE: return underline == src.underline;
614
case ESTRIKETHROUGH: return strikethrough == src.strikethrough;
615
case ERUN_DIRECTION: return runDirection == src.runDirection;
616
case EBIDI_EMBEDDING: return bidiEmbedding == src.bidiEmbedding;
617
case EJUSTIFICATION: return justification == src.justification;
618
case EINPUT_METHOD_HIGHLIGHT: return equals(imHighlight, src.imHighlight);
619
case EINPUT_METHOD_UNDERLINE: return imUnderline == src.imUnderline;
620
case ESWAP_COLORS: return swapColors == src.swapColors;
621
case ENUMERIC_SHAPING: return equals(numericShaping, src.numericShaping);
622
case EKERNING: return kerning == src.kerning;
623
case ELIGATURES: return ligatures == src.ligatures;
624
case ETRACKING: return tracking == src.tracking;
625
default: throw new InternalError();
626
}
627
}
628
629
private void i_set(EAttribute a, Object o) {
630
switch (a) {
631
case EFAMILY: family = ((String)o).trim(); break;
632
case EWEIGHT: weight = ((Number)o).floatValue(); break;
633
case EWIDTH: width = ((Number)o).floatValue(); break;
634
case EPOSTURE: posture = ((Number)o).floatValue(); break;
635
case ESIZE: size = ((Number)o).floatValue(); break;
636
case ETRANSFORM: {
637
if (o instanceof TransformAttribute) {
638
TransformAttribute ta = (TransformAttribute)o;
639
if (ta.isIdentity()) {
640
transform = null;
641
} else {
642
transform = ta.getTransform();
643
}
644
} else {
645
transform = new AffineTransform((AffineTransform)o);
646
}
647
updateDerivedTransforms();
648
} break;
649
case ESUPERSCRIPT: superscript = (byte)((Integer)o).intValue(); break;
650
case EFONT: font = (Font)o; break;
651
case ECHAR_REPLACEMENT: charReplacement = (GraphicAttribute)o; break;
652
case EFOREGROUND: foreground = (Paint)o; break;
653
case EBACKGROUND: background = (Paint)o; break;
654
case EUNDERLINE: underline = (byte)((Integer)o).intValue(); break;
655
case ESTRIKETHROUGH: strikethrough = ((Boolean)o).booleanValue(); break;
656
case ERUN_DIRECTION: {
657
if (o instanceof Boolean) {
658
runDirection = (byte)(TextAttribute.RUN_DIRECTION_LTR.equals(o) ? 0 : 1);
659
} else {
660
runDirection = (byte)((Integer)o).intValue();
661
}
662
} break;
663
case EBIDI_EMBEDDING: bidiEmbedding = (byte)((Integer)o).intValue(); break;
664
case EJUSTIFICATION: justification = ((Number)o).floatValue(); break;
665
case EINPUT_METHOD_HIGHLIGHT: {
666
if (o instanceof Annotation) {
667
Annotation at = (Annotation)o;
668
imHighlight = (InputMethodHighlight)at.getValue();
669
} else {
670
imHighlight = (InputMethodHighlight)o;
671
}
672
} break;
673
case EINPUT_METHOD_UNDERLINE: imUnderline = (byte)((Integer)o).intValue();
674
break;
675
case ESWAP_COLORS: swapColors = ((Boolean)o).booleanValue(); break;
676
case ENUMERIC_SHAPING: numericShaping = (NumericShaper)o; break;
677
case EKERNING: kerning = (byte)((Integer)o).intValue(); break;
678
case ELIGATURES: ligatures = (byte)((Integer)o).intValue(); break;
679
case ETRACKING: tracking = ((Number)o).floatValue(); break;
680
default: throw new InternalError();
681
}
682
}
683
684
private Object i_get(EAttribute a) {
685
switch (a) {
686
case EFAMILY: return family;
687
case EWEIGHT: return Float.valueOf(weight);
688
case EWIDTH: return Float.valueOf(width);
689
case EPOSTURE: return Float.valueOf(posture);
690
case ESIZE: return Float.valueOf(size);
691
case ETRANSFORM:
692
return transform == null
693
? TransformAttribute.IDENTITY
694
: new TransformAttribute(transform);
695
case ESUPERSCRIPT: return Integer.valueOf(superscript);
696
case EFONT: return font;
697
case ECHAR_REPLACEMENT: return charReplacement;
698
case EFOREGROUND: return foreground;
699
case EBACKGROUND: return background;
700
case EUNDERLINE: return Integer.valueOf(underline);
701
case ESTRIKETHROUGH: return Boolean.valueOf(strikethrough);
702
case ERUN_DIRECTION: {
703
switch (runDirection) {
704
// todo: figure out a way to indicate this value
705
// case -1: return Integer.valueOf(runDirection);
706
case 0: return TextAttribute.RUN_DIRECTION_LTR;
707
case 1: return TextAttribute.RUN_DIRECTION_RTL;
708
default: return null;
709
}
710
} // not reachable
711
case EBIDI_EMBEDDING: return Integer.valueOf(bidiEmbedding);
712
case EJUSTIFICATION: return Float.valueOf(justification);
713
case EINPUT_METHOD_HIGHLIGHT: return imHighlight;
714
case EINPUT_METHOD_UNDERLINE: return Integer.valueOf(imUnderline);
715
case ESWAP_COLORS: return Boolean.valueOf(swapColors);
716
case ENUMERIC_SHAPING: return numericShaping;
717
case EKERNING: return Integer.valueOf(kerning);
718
case ELIGATURES: return Integer.valueOf(ligatures);
719
case ETRACKING: return Float.valueOf(tracking);
720
default: throw new InternalError();
721
}
722
}
723
724
private boolean i_validate(EAttribute a) {
725
switch (a) {
726
case EFAMILY: if (family == null || family.length() == 0)
727
family = DEFAULT.family; return true;
728
case EWEIGHT: return weight > 0 && weight < 10;
729
case EWIDTH: return width >= .5f && width < 10;
730
case EPOSTURE: return posture >= -1 && posture <= 1;
731
case ESIZE: return size >= 0;
732
case ETRANSFORM: if (transform != null && transform.isIdentity())
733
transform = DEFAULT.transform; return true;
734
case ESUPERSCRIPT: return superscript >= -7 && superscript <= 7;
735
case EFONT: return true;
736
case ECHAR_REPLACEMENT: return true;
737
case EFOREGROUND: return true;
738
case EBACKGROUND: return true;
739
case EUNDERLINE: return underline >= -1 && underline < 6;
740
case ESTRIKETHROUGH: return true;
741
case ERUN_DIRECTION: return runDirection >= -2 && runDirection <= 1;
742
case EBIDI_EMBEDDING: return bidiEmbedding >= -61 && bidiEmbedding < 62;
743
case EJUSTIFICATION: justification = max(0, min (justification, 1));
744
return true;
745
case EINPUT_METHOD_HIGHLIGHT: return true;
746
case EINPUT_METHOD_UNDERLINE: return imUnderline >= -1 && imUnderline < 6;
747
case ESWAP_COLORS: return true;
748
case ENUMERIC_SHAPING: return true;
749
case EKERNING: return kerning >= 0 && kerning <= 1;
750
case ELIGATURES: return ligatures >= 0 && ligatures <= 1;
751
case ETRACKING: return tracking >= -1 && tracking <= 10;
752
default: throw new InternalError("unknown attribute: " + a);
753
}
754
}
755
756
// Until textlayout is fixed to use AttributeValues, we'll end up
757
// creating a map from the values for it. This is a compromise between
758
// creating the whole map and just checking a particular value.
759
// Plan to remove these.
760
public static float getJustification(Map<?, ?> map) {
761
if (map != null) {
762
if (map instanceof AttributeMap &&
763
((AttributeMap) map).getValues() != null) {
764
return ((AttributeMap)map).getValues().justification;
765
}
766
Object obj = map.get(TextAttribute.JUSTIFICATION);
767
if (obj != null && obj instanceof Number) {
768
return max(0, min(1, ((Number)obj).floatValue()));
769
}
770
}
771
return DEFAULT.justification;
772
}
773
774
public static NumericShaper getNumericShaping(Map<?, ?> map) {
775
if (map != null) {
776
if (map instanceof AttributeMap &&
777
((AttributeMap) map).getValues() != null) {
778
return ((AttributeMap)map).getValues().numericShaping;
779
}
780
Object obj = map.get(TextAttribute.NUMERIC_SHAPING);
781
if (obj != null && obj instanceof NumericShaper) {
782
return (NumericShaper)obj;
783
}
784
}
785
return DEFAULT.numericShaping;
786
}
787
788
/**
789
* If this has an imHighlight, create copy of this with those attributes
790
* applied to it. Otherwise return this unchanged.
791
*/
792
public AttributeValues applyIMHighlight() {
793
if (imHighlight != null) {
794
InputMethodHighlight hl = null;
795
if (imHighlight instanceof InputMethodHighlight) {
796
hl = (InputMethodHighlight)imHighlight;
797
} else {
798
hl = (InputMethodHighlight)((Annotation)imHighlight).getValue();
799
}
800
801
Map<TextAttribute, ?> imStyles = hl.getStyle();
802
if (imStyles == null) {
803
Toolkit tk = Toolkit.getDefaultToolkit();
804
imStyles = tk.mapInputMethodHighlight(hl);
805
}
806
807
if (imStyles != null) {
808
return clone().merge(imStyles);
809
}
810
}
811
812
return this;
813
}
814
815
@SuppressWarnings("unchecked")
816
public static AffineTransform getBaselineTransform(Map<?, ?> map) {
817
if (map != null) {
818
AttributeValues av = null;
819
if (map instanceof AttributeMap &&
820
((AttributeMap) map).getValues() != null) {
821
av = ((AttributeMap)map).getValues();
822
} else if (map.get(TextAttribute.TRANSFORM) != null) {
823
av = AttributeValues.fromMap((Map<Attribute, ?>)map); // yuck
824
}
825
if (av != null) {
826
return av.baselineTransform;
827
}
828
}
829
return null;
830
}
831
832
@SuppressWarnings("unchecked")
833
public static AffineTransform getCharTransform(Map<?, ?> map) {
834
if (map != null) {
835
AttributeValues av = null;
836
if (map instanceof AttributeMap &&
837
((AttributeMap) map).getValues() != null) {
838
av = ((AttributeMap)map).getValues();
839
} else if (map.get(TextAttribute.TRANSFORM) != null) {
840
av = AttributeValues.fromMap((Map<Attribute, ?>)map); // yuck
841
}
842
if (av != null) {
843
return av.charTransform;
844
}
845
}
846
return null;
847
}
848
849
public void updateDerivedTransforms() {
850
// this also updates the mask for the baseline transform
851
if (transform == null) {
852
baselineTransform = null;
853
charTransform = null;
854
} else {
855
charTransform = new AffineTransform(transform);
856
baselineTransform = extractXRotation(charTransform, true);
857
858
if (charTransform.isIdentity()) {
859
charTransform = null;
860
}
861
862
if (baselineTransform.isIdentity()) {
863
baselineTransform = null;
864
}
865
}
866
867
if (baselineTransform == null) {
868
nondefault &= ~EBASELINE_TRANSFORM.mask;
869
} else {
870
nondefault |= EBASELINE_TRANSFORM.mask;
871
}
872
}
873
874
public static AffineTransform extractXRotation(AffineTransform tx,
875
boolean andTranslation) {
876
return extractRotation(new Point2D.Double(1, 0), tx, andTranslation);
877
}
878
879
public static AffineTransform extractYRotation(AffineTransform tx,
880
boolean andTranslation) {
881
return extractRotation(new Point2D.Double(0, 1), tx, andTranslation);
882
}
883
884
private static AffineTransform extractRotation(Point2D.Double pt,
885
AffineTransform tx, boolean andTranslation) {
886
887
tx.deltaTransform(pt, pt);
888
AffineTransform rtx = AffineTransform.getRotateInstance(pt.x, pt.y);
889
890
try {
891
AffineTransform rtxi = rtx.createInverse();
892
double dx = tx.getTranslateX();
893
double dy = tx.getTranslateY();
894
tx.preConcatenate(rtxi);
895
if (andTranslation) {
896
if (dx != 0 || dy != 0) {
897
tx.setTransform(tx.getScaleX(), tx.getShearY(),
898
tx.getShearX(), tx.getScaleY(), 0, 0);
899
rtx.setTransform(rtx.getScaleX(), rtx.getShearY(),
900
rtx.getShearX(), rtx.getScaleY(), dx, dy);
901
}
902
}
903
}
904
catch (NoninvertibleTransformException e) {
905
return null;
906
}
907
return rtx;
908
}
909
}
910
911