Path: blob/master/src/java.desktop/share/classes/sun/font/AttributeValues.java
41155 views
/*1* Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26*27* (C) Copyright IBM Corp. 2005 - All Rights Reserved28*29* The original version of this source code and documentation is30* copyrighted and owned by IBM. These materials are provided31* under terms of a License Agreement between IBM and Sun.32* This technology is protected by multiple US and International33* patents. This notice and attribution to IBM may not be removed.34*/3536package sun.font;3738import static sun.font.EAttribute.*;39import static java.lang.Math.*;4041import java.awt.Font;42import java.awt.Paint;43import java.awt.Toolkit;44import java.awt.font.GraphicAttribute;45import java.awt.font.NumericShaper;46import java.awt.font.TextAttribute;47import java.awt.font.TransformAttribute;48import java.awt.geom.AffineTransform;49import java.awt.geom.NoninvertibleTransformException;50import java.awt.geom.Point2D;51import java.awt.im.InputMethodHighlight;52import java.io.Serializable;53import java.text.Annotation;54import java.text.AttributedCharacterIterator.Attribute;55import java.util.Map;56import java.util.HashMap;57import java.util.Hashtable;5859public final class AttributeValues implements Cloneable {60private int defined;61private int nondefault;6263private String family = "Default";64private float weight = 1f;65private float width = 1f;66private float posture; // 0f67private float size = 12f;68private float tracking; // 0f69private NumericShaper numericShaping; // null70private AffineTransform transform; // null == identity71private GraphicAttribute charReplacement; // null72private Paint foreground; // null73private Paint background; // null74private float justification = 1f;75private Object imHighlight; // null76// (can be either Attribute wrapping IMH, or IMH itself77private Font font; // here for completeness, don't actually use78private byte imUnderline = -1; // same default as underline79private byte superscript; // 080private byte underline = -1; // arrgh, value for ON is 081private byte runDirection = -2; // BIDI.DIRECTION_DEFAULT_LEFT_TO_RIGHT82private byte bidiEmbedding; // 083private byte kerning; // 084private byte ligatures; // 085private boolean strikethrough; // false86private boolean swapColors; // false8788private AffineTransform baselineTransform; // derived from transform89private AffineTransform charTransform; // derived from transform9091private static final AttributeValues DEFAULT = new AttributeValues();9293// type-specific API94public String getFamily() { return family; }95public void setFamily(String f) { this.family = f; update(EFAMILY); }9697public float getWeight() { return weight; }98public void setWeight(float f) { this.weight = f; update(EWEIGHT); }99100public float getWidth() { return width; }101public void setWidth(float f) { this.width = f; update(EWIDTH); }102103public float getPosture() { return posture; }104public void setPosture(float f) { this.posture = f; update(EPOSTURE); }105106public float getSize() { return size; }107public void setSize(float f) { this.size = f; update(ESIZE); }108109public AffineTransform getTransform() { return transform; }110public void setTransform(AffineTransform f) {111this.transform = (f == null || f.isIdentity())112? DEFAULT.transform113: new AffineTransform(f);114updateDerivedTransforms();115update(ETRANSFORM);116}117public void setTransform(TransformAttribute f) {118this.transform = (f == null || f.isIdentity())119? DEFAULT.transform120: f.getTransform();121updateDerivedTransforms();122update(ETRANSFORM);123}124125public int getSuperscript() { return superscript; }126public void setSuperscript(int f) {127this.superscript = (byte)f; update(ESUPERSCRIPT); }128129public Font getFont() { return font; }130public void setFont(Font f) { this.font = f; update(EFONT); }131132public GraphicAttribute getCharReplacement() { return charReplacement; }133public void setCharReplacement(GraphicAttribute f) {134this.charReplacement = f; update(ECHAR_REPLACEMENT); }135136public Paint getForeground() { return foreground; }137public void setForeground(Paint f) {138this.foreground = f; update(EFOREGROUND); }139140public Paint getBackground() { return background; }141public void setBackground(Paint f) {142this.background = f; update(EBACKGROUND); }143144public int getUnderline() { return underline; }145public void setUnderline(int f) {146this.underline = (byte)f; update(EUNDERLINE); }147148public boolean getStrikethrough() { return strikethrough; }149public void setStrikethrough(boolean f) {150this.strikethrough = f; update(ESTRIKETHROUGH); }151152public int getRunDirection() { return runDirection; }153public void setRunDirection(int f) {154this.runDirection = (byte)f; update(ERUN_DIRECTION); }155156public int getBidiEmbedding() { return bidiEmbedding; }157public void setBidiEmbedding(int f) {158this.bidiEmbedding = (byte)f; update(EBIDI_EMBEDDING); }159160public float getJustification() { return justification; }161public void setJustification(float f) {162this.justification = f; update(EJUSTIFICATION); }163164public Object getInputMethodHighlight() { return imHighlight; }165public void setInputMethodHighlight(Annotation f) {166this.imHighlight = f; update(EINPUT_METHOD_HIGHLIGHT); }167public void setInputMethodHighlight(InputMethodHighlight f) {168this.imHighlight = f; update(EINPUT_METHOD_HIGHLIGHT); }169170public int getInputMethodUnderline() { return imUnderline; }171public void setInputMethodUnderline(int f) {172this.imUnderline = (byte)f; update(EINPUT_METHOD_UNDERLINE); }173174public boolean getSwapColors() { return swapColors; }175public void setSwapColors(boolean f) {176this.swapColors = f; update(ESWAP_COLORS); }177178public NumericShaper getNumericShaping() { return numericShaping; }179public void setNumericShaping(NumericShaper f) {180this.numericShaping = f; update(ENUMERIC_SHAPING); }181182public int getKerning() { return kerning; }183public void setKerning(int f) {184this.kerning = (byte)f; update(EKERNING); }185186public float getTracking() { return tracking; }187public void setTracking(float f) {188this.tracking = (byte)f; update(ETRACKING); }189190public int getLigatures() { return ligatures; }191public void setLigatures(int f) {192this.ligatures = (byte)f; update(ELIGATURES); }193194195public AffineTransform getBaselineTransform() { return baselineTransform; }196public AffineTransform getCharTransform() { return charTransform; }197198// mask api199200public static int getMask(EAttribute att) {201return att.mask;202}203204public static int getMask(EAttribute ... atts) {205int mask = 0;206for (EAttribute a: atts) {207mask |= a.mask;208}209return mask;210}211212public static final int MASK_ALL =213getMask(EAttribute.class.getEnumConstants());214215public void unsetDefault() {216defined &= nondefault;217}218219public void defineAll(int mask) {220defined |= mask;221if ((defined & EBASELINE_TRANSFORM.mask) != 0) {222throw new InternalError("can't define derived attribute");223}224}225226public boolean allDefined(int mask) {227return (defined & mask) == mask;228}229230public boolean anyDefined(int mask) {231return (defined & mask) != 0;232}233234public boolean anyNonDefault(int mask) {235return (nondefault & mask) != 0;236}237238// generic EAttribute API239240public boolean isDefined(EAttribute a) {241return (defined & a.mask) != 0;242}243244public boolean isNonDefault(EAttribute a) {245return (nondefault & a.mask) != 0;246}247248public void setDefault(EAttribute a) {249if (a.att == null) {250throw new InternalError("can't set default derived attribute: " + a);251}252i_set(a, DEFAULT);253defined |= a.mask;254nondefault &= ~a.mask;255}256257public void unset(EAttribute a) {258if (a.att == null) {259throw new InternalError("can't unset derived attribute: " + a);260}261i_set(a, DEFAULT);262defined &= ~a.mask;263nondefault &= ~a.mask;264}265266public void set(EAttribute a, AttributeValues src) {267if (a.att == null) {268throw new InternalError("can't set derived attribute: " + a);269}270if (src == null || src == DEFAULT) {271setDefault(a);272} else {273if ((src.defined & a.mask) != 0) {274i_set(a, src);275update(a);276}277}278}279280public void set(EAttribute a, Object o) {281if (a.att == null) {282throw new InternalError("can't set derived attribute: " + a);283}284if (o != null) {285try {286i_set(a, o);287update(a);288return;289} catch (Exception e) {290}291}292setDefault(a);293}294295public Object get(EAttribute a) {296if (a.att == null) {297throw new InternalError("can't get derived attribute: " + a);298}299if ((nondefault & a.mask) != 0) {300return i_get(a);301}302return null;303}304305// merging306307public AttributeValues merge(Map<? extends Attribute, ?>map) {308return merge(map, MASK_ALL);309}310311public AttributeValues merge(Map<? extends Attribute, ?>map,312int mask) {313if (map instanceof AttributeMap &&314((AttributeMap) map).getValues() != null) {315merge(((AttributeMap)map).getValues(), mask);316} else if (map != null && !map.isEmpty()) {317for (Map.Entry<? extends Attribute, ?> e: map.entrySet()) {318try {319EAttribute ea = EAttribute.forAttribute(e.getKey());320if (ea!= null && (mask & ea.mask) != 0) {321set(ea, e.getValue());322}323} catch (ClassCastException cce) {324// IGNORED325}326}327}328return this;329}330331public AttributeValues merge(AttributeValues src) {332return merge(src, MASK_ALL);333}334335public AttributeValues merge(AttributeValues src, int mask) {336int m = mask & src.defined;337for (EAttribute ea: EAttribute.atts) {338if (m == 0) {339break;340}341if ((m & ea.mask) != 0) {342m &= ~ea.mask;343i_set(ea, src);344update(ea);345}346}347return this;348}349350// creation API351352public static AttributeValues fromMap(Map<? extends Attribute, ?> map) {353return fromMap(map, MASK_ALL);354}355356public static AttributeValues fromMap(Map<? extends Attribute, ?> map,357int mask) {358return new AttributeValues().merge(map, mask);359}360361public Map<TextAttribute, Object> toMap(Map<TextAttribute, Object> fill) {362if (fill == null) {363fill = new HashMap<TextAttribute, Object>();364}365366for (int m = defined, i = 0; m != 0; ++i) {367EAttribute ea = EAttribute.atts[i];368if ((m & ea.mask) != 0) {369m &= ~ea.mask;370fill.put(ea.att, get(ea));371}372}373374return fill;375}376377// key must be serializable, so use String, not Object378private static final String DEFINED_KEY =379"sun.font.attributevalues.defined_key";380381public static boolean is16Hashtable(Hashtable<Object, Object> ht) {382return ht.containsKey(DEFINED_KEY);383}384385public static AttributeValues386fromSerializableHashtable(Hashtable<Object, Object> ht)387{388AttributeValues result = new AttributeValues();389if (ht != null && !ht.isEmpty()) {390for (Map.Entry<Object, Object> e: ht.entrySet()) {391Object key = e.getKey();392Object val = e.getValue();393if (key.equals(DEFINED_KEY)) {394result.defineAll(((Integer)val).intValue());395} else {396try {397EAttribute ea =398EAttribute.forAttribute((Attribute)key);399if (ea != null) {400result.set(ea, val);401}402}403catch (ClassCastException ex) {404}405}406}407}408return result;409}410411public Hashtable<Object, Object> toSerializableHashtable() {412Hashtable<Object, Object> ht = new Hashtable<>();413int hashkey = defined;414for (int m = defined, i = 0; m != 0; ++i) {415EAttribute ea = EAttribute.atts[i];416if ((m & ea.mask) != 0) {417m &= ~ea.mask;418Object o = get(ea);419if (o == null) {420// hashkey will handle it421} else if (o instanceof Serializable) { // check all...422ht.put(ea.att, o);423} else {424hashkey &= ~ea.mask;425}426}427}428ht.put(DEFINED_KEY, Integer.valueOf(hashkey));429430return ht;431}432433// boilerplate434public int hashCode() {435return defined << 8 ^ nondefault;436}437438public boolean equals(Object rhs) {439try {440return equals((AttributeValues)rhs);441}442catch (ClassCastException e) {443}444return false;445}446447public boolean equals(AttributeValues rhs) {448// test in order of most likely to differ and easiest to compare449// also assumes we're generally calling this only if family,450// size, weight, posture are the same451452if (rhs == null) return false;453if (rhs == this) return true;454455return defined == rhs.defined456&& nondefault == rhs.nondefault457&& underline == rhs.underline458&& strikethrough == rhs.strikethrough459&& superscript == rhs.superscript460&& width == rhs.width461&& kerning == rhs.kerning462&& tracking == rhs.tracking463&& ligatures == rhs.ligatures464&& runDirection == rhs.runDirection465&& bidiEmbedding == rhs.bidiEmbedding466&& swapColors == rhs.swapColors467&& equals(transform, rhs.transform)468&& equals(foreground, rhs.foreground)469&& equals(background, rhs.background)470&& equals(numericShaping, rhs.numericShaping)471&& equals(justification, rhs.justification)472&& equals(charReplacement, rhs.charReplacement)473&& size == rhs.size474&& weight == rhs.weight475&& posture == rhs.posture476&& equals(family, rhs.family)477&& equals(font, rhs.font)478&& imUnderline == rhs.imUnderline479&& equals(imHighlight, rhs.imHighlight);480}481482public AttributeValues clone() {483try {484AttributeValues result = (AttributeValues)super.clone();485if (transform != null) { // AffineTransform is mutable486result.transform = new AffineTransform(transform);487result.updateDerivedTransforms();488}489// if transform is null, derived transforms are null490// so there's nothing to do491return result;492}493catch (CloneNotSupportedException e) {494// never happens495return null;496}497}498499public String toString() {500StringBuilder b = new StringBuilder();501b.append('{');502for (int m = defined, i = 0; m != 0; ++i) {503EAttribute ea = EAttribute.atts[i];504if ((m & ea.mask) != 0) {505m &= ~ea.mask;506if (b.length() > 1) {507b.append(", ");508}509b.append(ea);510b.append('=');511switch (ea) {512case EFAMILY: b.append('"');513b.append(family);514b.append('"'); break;515case EWEIGHT: b.append(weight); break;516case EWIDTH: b.append(width); break;517case EPOSTURE: b.append(posture); break;518case ESIZE: b.append(size); break;519case ETRANSFORM: b.append(transform); break;520case ESUPERSCRIPT: b.append(superscript); break;521case EFONT: b.append(font); break;522case ECHAR_REPLACEMENT: b.append(charReplacement); break;523case EFOREGROUND: b.append(foreground); break;524case EBACKGROUND: b.append(background); break;525case EUNDERLINE: b.append(underline); break;526case ESTRIKETHROUGH: b.append(strikethrough); break;527case ERUN_DIRECTION: b.append(runDirection); break;528case EBIDI_EMBEDDING: b.append(bidiEmbedding); break;529case EJUSTIFICATION: b.append(justification); break;530case EINPUT_METHOD_HIGHLIGHT: b.append(imHighlight); break;531case EINPUT_METHOD_UNDERLINE: b.append(imUnderline); break;532case ESWAP_COLORS: b.append(swapColors); break;533case ENUMERIC_SHAPING: b.append(numericShaping); break;534case EKERNING: b.append(kerning); break;535case ELIGATURES: b.append(ligatures); break;536case ETRACKING: b.append(tracking); break;537default: throw new InternalError();538}539if ((nondefault & ea.mask) == 0) {540b.append('*');541}542}543}544b.append("[btx=" + baselineTransform + ", ctx=" + charTransform + "]");545b.append('}');546return b.toString();547}548549// internal utilities550551private static boolean equals(Object lhs, Object rhs) {552return lhs == null ? rhs == null : lhs.equals(rhs);553}554555private void update(EAttribute a) {556defined |= a.mask;557if (i_validate(a)) {558if (i_equals(a, DEFAULT)) {559nondefault &= ~a.mask;560} else {561nondefault |= a.mask;562}563} else {564setDefault(a);565}566}567568// dispatch569570private void i_set(EAttribute a, AttributeValues src) {571switch (a) {572case EFAMILY: family = src.family; break;573case EWEIGHT: weight = src.weight; break;574case EWIDTH: width = src.width; break;575case EPOSTURE: posture = src.posture; break;576case ESIZE: size = src.size; break;577case ETRANSFORM: transform = src.transform; updateDerivedTransforms(); break;578case ESUPERSCRIPT: superscript = src.superscript; break;579case EFONT: font = src.font; break;580case ECHAR_REPLACEMENT: charReplacement = src.charReplacement; break;581case EFOREGROUND: foreground = src.foreground; break;582case EBACKGROUND: background = src.background; break;583case EUNDERLINE: underline = src.underline; break;584case ESTRIKETHROUGH: strikethrough = src.strikethrough; break;585case ERUN_DIRECTION: runDirection = src.runDirection; break;586case EBIDI_EMBEDDING: bidiEmbedding = src.bidiEmbedding; break;587case EJUSTIFICATION: justification = src.justification; break;588case EINPUT_METHOD_HIGHLIGHT: imHighlight = src.imHighlight; break;589case EINPUT_METHOD_UNDERLINE: imUnderline = src.imUnderline; break;590case ESWAP_COLORS: swapColors = src.swapColors; break;591case ENUMERIC_SHAPING: numericShaping = src.numericShaping; break;592case EKERNING: kerning = src.kerning; break;593case ELIGATURES: ligatures = src.ligatures; break;594case ETRACKING: tracking = src.tracking; break;595default: throw new InternalError();596}597}598599private boolean i_equals(EAttribute a, AttributeValues src) {600switch (a) {601case EFAMILY: return equals(family, src.family);602case EWEIGHT: return weight == src.weight;603case EWIDTH: return width == src.width;604case EPOSTURE: return posture == src.posture;605case ESIZE: return size == src.size;606case ETRANSFORM: return equals(transform, src.transform);607case ESUPERSCRIPT: return superscript == src.superscript;608case EFONT: return equals(font, src.font);609case ECHAR_REPLACEMENT: return equals(charReplacement, src.charReplacement);610case EFOREGROUND: return equals(foreground, src.foreground);611case EBACKGROUND: return equals(background, src.background);612case EUNDERLINE: return underline == src.underline;613case ESTRIKETHROUGH: return strikethrough == src.strikethrough;614case ERUN_DIRECTION: return runDirection == src.runDirection;615case EBIDI_EMBEDDING: return bidiEmbedding == src.bidiEmbedding;616case EJUSTIFICATION: return justification == src.justification;617case EINPUT_METHOD_HIGHLIGHT: return equals(imHighlight, src.imHighlight);618case EINPUT_METHOD_UNDERLINE: return imUnderline == src.imUnderline;619case ESWAP_COLORS: return swapColors == src.swapColors;620case ENUMERIC_SHAPING: return equals(numericShaping, src.numericShaping);621case EKERNING: return kerning == src.kerning;622case ELIGATURES: return ligatures == src.ligatures;623case ETRACKING: return tracking == src.tracking;624default: throw new InternalError();625}626}627628private void i_set(EAttribute a, Object o) {629switch (a) {630case EFAMILY: family = ((String)o).trim(); break;631case EWEIGHT: weight = ((Number)o).floatValue(); break;632case EWIDTH: width = ((Number)o).floatValue(); break;633case EPOSTURE: posture = ((Number)o).floatValue(); break;634case ESIZE: size = ((Number)o).floatValue(); break;635case ETRANSFORM: {636if (o instanceof TransformAttribute) {637TransformAttribute ta = (TransformAttribute)o;638if (ta.isIdentity()) {639transform = null;640} else {641transform = ta.getTransform();642}643} else {644transform = new AffineTransform((AffineTransform)o);645}646updateDerivedTransforms();647} break;648case ESUPERSCRIPT: superscript = (byte)((Integer)o).intValue(); break;649case EFONT: font = (Font)o; break;650case ECHAR_REPLACEMENT: charReplacement = (GraphicAttribute)o; break;651case EFOREGROUND: foreground = (Paint)o; break;652case EBACKGROUND: background = (Paint)o; break;653case EUNDERLINE: underline = (byte)((Integer)o).intValue(); break;654case ESTRIKETHROUGH: strikethrough = ((Boolean)o).booleanValue(); break;655case ERUN_DIRECTION: {656if (o instanceof Boolean) {657runDirection = (byte)(TextAttribute.RUN_DIRECTION_LTR.equals(o) ? 0 : 1);658} else {659runDirection = (byte)((Integer)o).intValue();660}661} break;662case EBIDI_EMBEDDING: bidiEmbedding = (byte)((Integer)o).intValue(); break;663case EJUSTIFICATION: justification = ((Number)o).floatValue(); break;664case EINPUT_METHOD_HIGHLIGHT: {665if (o instanceof Annotation) {666Annotation at = (Annotation)o;667imHighlight = (InputMethodHighlight)at.getValue();668} else {669imHighlight = (InputMethodHighlight)o;670}671} break;672case EINPUT_METHOD_UNDERLINE: imUnderline = (byte)((Integer)o).intValue();673break;674case ESWAP_COLORS: swapColors = ((Boolean)o).booleanValue(); break;675case ENUMERIC_SHAPING: numericShaping = (NumericShaper)o; break;676case EKERNING: kerning = (byte)((Integer)o).intValue(); break;677case ELIGATURES: ligatures = (byte)((Integer)o).intValue(); break;678case ETRACKING: tracking = ((Number)o).floatValue(); break;679default: throw new InternalError();680}681}682683private Object i_get(EAttribute a) {684switch (a) {685case EFAMILY: return family;686case EWEIGHT: return Float.valueOf(weight);687case EWIDTH: return Float.valueOf(width);688case EPOSTURE: return Float.valueOf(posture);689case ESIZE: return Float.valueOf(size);690case ETRANSFORM:691return transform == null692? TransformAttribute.IDENTITY693: new TransformAttribute(transform);694case ESUPERSCRIPT: return Integer.valueOf(superscript);695case EFONT: return font;696case ECHAR_REPLACEMENT: return charReplacement;697case EFOREGROUND: return foreground;698case EBACKGROUND: return background;699case EUNDERLINE: return Integer.valueOf(underline);700case ESTRIKETHROUGH: return Boolean.valueOf(strikethrough);701case ERUN_DIRECTION: {702switch (runDirection) {703// todo: figure out a way to indicate this value704// case -1: return Integer.valueOf(runDirection);705case 0: return TextAttribute.RUN_DIRECTION_LTR;706case 1: return TextAttribute.RUN_DIRECTION_RTL;707default: return null;708}709} // not reachable710case EBIDI_EMBEDDING: return Integer.valueOf(bidiEmbedding);711case EJUSTIFICATION: return Float.valueOf(justification);712case EINPUT_METHOD_HIGHLIGHT: return imHighlight;713case EINPUT_METHOD_UNDERLINE: return Integer.valueOf(imUnderline);714case ESWAP_COLORS: return Boolean.valueOf(swapColors);715case ENUMERIC_SHAPING: return numericShaping;716case EKERNING: return Integer.valueOf(kerning);717case ELIGATURES: return Integer.valueOf(ligatures);718case ETRACKING: return Float.valueOf(tracking);719default: throw new InternalError();720}721}722723private boolean i_validate(EAttribute a) {724switch (a) {725case EFAMILY: if (family == null || family.length() == 0)726family = DEFAULT.family; return true;727case EWEIGHT: return weight > 0 && weight < 10;728case EWIDTH: return width >= .5f && width < 10;729case EPOSTURE: return posture >= -1 && posture <= 1;730case ESIZE: return size >= 0;731case ETRANSFORM: if (transform != null && transform.isIdentity())732transform = DEFAULT.transform; return true;733case ESUPERSCRIPT: return superscript >= -7 && superscript <= 7;734case EFONT: return true;735case ECHAR_REPLACEMENT: return true;736case EFOREGROUND: return true;737case EBACKGROUND: return true;738case EUNDERLINE: return underline >= -1 && underline < 6;739case ESTRIKETHROUGH: return true;740case ERUN_DIRECTION: return runDirection >= -2 && runDirection <= 1;741case EBIDI_EMBEDDING: return bidiEmbedding >= -61 && bidiEmbedding < 62;742case EJUSTIFICATION: justification = max(0, min (justification, 1));743return true;744case EINPUT_METHOD_HIGHLIGHT: return true;745case EINPUT_METHOD_UNDERLINE: return imUnderline >= -1 && imUnderline < 6;746case ESWAP_COLORS: return true;747case ENUMERIC_SHAPING: return true;748case EKERNING: return kerning >= 0 && kerning <= 1;749case ELIGATURES: return ligatures >= 0 && ligatures <= 1;750case ETRACKING: return tracking >= -1 && tracking <= 10;751default: throw new InternalError("unknown attribute: " + a);752}753}754755// Until textlayout is fixed to use AttributeValues, we'll end up756// creating a map from the values for it. This is a compromise between757// creating the whole map and just checking a particular value.758// Plan to remove these.759public static float getJustification(Map<?, ?> map) {760if (map != null) {761if (map instanceof AttributeMap &&762((AttributeMap) map).getValues() != null) {763return ((AttributeMap)map).getValues().justification;764}765Object obj = map.get(TextAttribute.JUSTIFICATION);766if (obj != null && obj instanceof Number) {767return max(0, min(1, ((Number)obj).floatValue()));768}769}770return DEFAULT.justification;771}772773public static NumericShaper getNumericShaping(Map<?, ?> map) {774if (map != null) {775if (map instanceof AttributeMap &&776((AttributeMap) map).getValues() != null) {777return ((AttributeMap)map).getValues().numericShaping;778}779Object obj = map.get(TextAttribute.NUMERIC_SHAPING);780if (obj != null && obj instanceof NumericShaper) {781return (NumericShaper)obj;782}783}784return DEFAULT.numericShaping;785}786787/**788* If this has an imHighlight, create copy of this with those attributes789* applied to it. Otherwise return this unchanged.790*/791public AttributeValues applyIMHighlight() {792if (imHighlight != null) {793InputMethodHighlight hl = null;794if (imHighlight instanceof InputMethodHighlight) {795hl = (InputMethodHighlight)imHighlight;796} else {797hl = (InputMethodHighlight)((Annotation)imHighlight).getValue();798}799800Map<TextAttribute, ?> imStyles = hl.getStyle();801if (imStyles == null) {802Toolkit tk = Toolkit.getDefaultToolkit();803imStyles = tk.mapInputMethodHighlight(hl);804}805806if (imStyles != null) {807return clone().merge(imStyles);808}809}810811return this;812}813814@SuppressWarnings("unchecked")815public static AffineTransform getBaselineTransform(Map<?, ?> map) {816if (map != null) {817AttributeValues av = null;818if (map instanceof AttributeMap &&819((AttributeMap) map).getValues() != null) {820av = ((AttributeMap)map).getValues();821} else if (map.get(TextAttribute.TRANSFORM) != null) {822av = AttributeValues.fromMap((Map<Attribute, ?>)map); // yuck823}824if (av != null) {825return av.baselineTransform;826}827}828return null;829}830831@SuppressWarnings("unchecked")832public static AffineTransform getCharTransform(Map<?, ?> map) {833if (map != null) {834AttributeValues av = null;835if (map instanceof AttributeMap &&836((AttributeMap) map).getValues() != null) {837av = ((AttributeMap)map).getValues();838} else if (map.get(TextAttribute.TRANSFORM) != null) {839av = AttributeValues.fromMap((Map<Attribute, ?>)map); // yuck840}841if (av != null) {842return av.charTransform;843}844}845return null;846}847848public void updateDerivedTransforms() {849// this also updates the mask for the baseline transform850if (transform == null) {851baselineTransform = null;852charTransform = null;853} else {854charTransform = new AffineTransform(transform);855baselineTransform = extractXRotation(charTransform, true);856857if (charTransform.isIdentity()) {858charTransform = null;859}860861if (baselineTransform.isIdentity()) {862baselineTransform = null;863}864}865866if (baselineTransform == null) {867nondefault &= ~EBASELINE_TRANSFORM.mask;868} else {869nondefault |= EBASELINE_TRANSFORM.mask;870}871}872873public static AffineTransform extractXRotation(AffineTransform tx,874boolean andTranslation) {875return extractRotation(new Point2D.Double(1, 0), tx, andTranslation);876}877878public static AffineTransform extractYRotation(AffineTransform tx,879boolean andTranslation) {880return extractRotation(new Point2D.Double(0, 1), tx, andTranslation);881}882883private static AffineTransform extractRotation(Point2D.Double pt,884AffineTransform tx, boolean andTranslation) {885886tx.deltaTransform(pt, pt);887AffineTransform rtx = AffineTransform.getRotateInstance(pt.x, pt.y);888889try {890AffineTransform rtxi = rtx.createInverse();891double dx = tx.getTranslateX();892double dy = tx.getTranslateY();893tx.preConcatenate(rtxi);894if (andTranslation) {895if (dx != 0 || dy != 0) {896tx.setTransform(tx.getScaleX(), tx.getShearY(),897tx.getShearX(), tx.getScaleY(), 0, 0);898rtx.setTransform(rtx.getScaleX(), rtx.getShearY(),899rtx.getShearX(), rtx.getScaleY(), dx, dy);900}901}902}903catch (NoninvertibleTransformException e) {904return null;905}906return rtx;907}908}909910911