History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/font/AttributeValues.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/font/AttributeValues.java+907−0
@@ -0,0 +1,907 @@
1+/*
2+ * Copyright (c) 2004, 2008, 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 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 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+ public static AffineTransform getBaselineTransform(Map<?, ?> map) {
816+ if (map != null) {
817+ AttributeValues av = null;
818+ if (map instanceof AttributeMap &&
819+ ((AttributeMap) map).getValues() != null) {
820+ av = ((AttributeMap)map).getValues();
821+ } else if (map.get(TextAttribute.TRANSFORM) != null) {
822+ av = AttributeValues.fromMap((Map<Attribute, ?>)map); // yuck
823+ }
824+ if (av != null) {
825+ return av.baselineTransform;
826+ }
827+ }
828+ return null;
829+ }
830+
831+ public static AffineTransform getCharTransform(Map<?, ?> map) {
832+ if (map != null) {
833+ AttributeValues av = null;
834+ if (map instanceof AttributeMap &&
835+ ((AttributeMap) map).getValues() != null) {
836+ av = ((AttributeMap)map).getValues();
837+ } else if (map.get(TextAttribute.TRANSFORM) != null) {
838+ av = AttributeValues.fromMap((Map<Attribute, ?>)map); // yuck
839+ }
840+ if (av != null) {
841+ return av.charTransform;
842+ }
843+ }
844+ return null;
845+ }
846+
847+ public void updateDerivedTransforms() {
848+ // this also updates the mask for the baseline transform
849+ if (transform == null) {
850+ baselineTransform = null;
851+ charTransform = null;
852+ } else {
853+ charTransform = new AffineTransform(transform);
854+ baselineTransform = extractXRotation(charTransform, true);
855+
856+ if (charTransform.isIdentity()) {
857+ charTransform = null;
858+ }
859+
860+ if (baselineTransform.isIdentity()) {
861+ baselineTransform = null;
862+ }
863+ }
864+
865+ if (baselineTransform == null) {
866+ nondefault &= ~EBASELINE_TRANSFORM.mask;
867+ } else {
868+ nondefault |= EBASELINE_TRANSFORM.mask;
869+ }
870+ }
871+
872+ public static AffineTransform extractXRotation(AffineTransform tx,
873+ boolean andTranslation) {
874+ return extractRotation(new Point2D.Double(1, 0), tx, andTranslation);
875+ }
876+
877+ public static AffineTransform extractYRotation(AffineTransform tx,
878+ boolean andTranslation) {
879+ return extractRotation(new Point2D.Double(0, 1), tx, andTranslation);
880+ }
881+
882+ private static AffineTransform extractRotation(Point2D.Double pt,
883+ AffineTransform tx, boolean andTranslation) {
884+
885+ tx.deltaTransform(pt, pt);
886+ AffineTransform rtx = AffineTransform.getRotateInstance(pt.x, pt.y);
887+
888+ try {
889+ AffineTransform rtxi = rtx.createInverse();
890+ double dx = tx.getTranslateX();
891+ double dy = tx.getTranslateY();
892+ tx.preConcatenate(rtxi);
893+ if (andTranslation) {
894+ if (dx != 0 || dy != 0) {
895+ tx.setTransform(tx.getScaleX(), tx.getShearY(),
896+ tx.getShearX(), tx.getScaleY(), 0, 0);
897+ rtx.setTransform(rtx.getScaleX(), rtx.getShearY(),
898+ rtx.getShearX(), rtx.getScaleY(), dx, dy);
899+ }
900+ }
901+ }
902+ catch (NoninvertibleTransformException e) {
903+ return null;
904+ }
905+ return rtx;
906+ }
907+}