StringBuilder b = new StringBuilder(); b.append('{'); for (int m = defined, i = 0; m != 0; ++i) { EAttribute ea = EAttribute.atts[i]; if ((m & ea.mask) != 0) { m &= ~ea.mask; if (b.length() > 1) { b.append(", "); } b.append(ea); b.append('='); switch (ea) { case EFAMILY: b.append('"'); b.append(family); b.append('"'); break; case EWEIGHT: b.append(weight); break; case EWIDTH: b.append(width); break; case EPOSTURE: b.append(posture); break; case ESIZE: b.append(size); break; case ETRANSFORM: b.append(transform); break; case ESUPERSCRIPT: b.append(superscript); break; case EFONT: b.append(font); break; case ECHAR_REPLACEMENT: b.append(charReplacement); break; case EFOREGROUND: b.append(foreground); break; case EBACKGROUND: b.append(background); break; case EUNDERLINE: b.append(underline); break; case ESTRIKETHROUGH: b.append(strikethrough); break; case ERUN_DIRECTION: b.append(runDirection); break; case EBIDI_EMBEDDING: b.append(bidiEmbedding); break; case EJUSTIFICATION: b.append(justification); break; case EINPUT_METHOD_HIGHLIGHT: b.append(imHighlight); break; case EINPUT_METHOD_UNDERLINE: b.append(imUnderline); break; case ESWAP_COLORS: b.append(swapColors); break; case ENUMERIC_SHAPING: b.append(numericShaping); break; case EKERNING: b.append(kerning); break; case ELIGATURES: b.append(ligatures); break; case ETRACKING: b.append(tracking); break; default: throw new InternalError(); } if ((nondefault & ea.mask) == 0) { b.append('*'); } } } b.append("[btx=" + baselineTransform + ", ctx=" + charTransform + "]"); b.append('}'); return b.toString(); } // internal utilities private static boolean equals(Object lhs, Object rhs) { return lhs == null ? rhs == null : lhs.equals(rhs); } private void update(EAttribute a) { defined |= a.mask; if (i_validate(a)) { if (i_equals(a, DEFAULT)) { nondefault &= ~a.mask; } else { nondefault |= a.mask; } } else { setDefault(a); } } // dispatch private void i_set(EAttribute a, AttributeValues src) { switch (a) { case EFAMILY: family = src.family; break; case EWEIGHT: weight = src.weight; break; case EWIDTH: width = src.width; break; case EPOSTURE: posture = src.posture; break; case ESIZE: size = src.size; break; case ETRANSFORM: transform = src.transform; updateDerivedTransforms(); break; case ESUPERSCRIPT: superscript = src.superscript; break; case EFONT: font = src.font; break; case ECHAR_REPLACEMENT: charReplacement = src.charReplacement; break; case EFOREGROUND: foreground = src.foreground; break; case EBACKGROUND: background = src.background; break; case EUNDERLINE: underline = src.underline; break; case ESTRIKETHROUGH: strikethrough = src.strikethrough; break; case ERUN_DIRECTION: runDirection = src.runDirection; break; case EBIDI_EMBEDDING: bidiEmbedding = src.bidiEmbedding; break; case EJUSTIFICATION: justification = src.justification; break; case EINPUT_METHOD_HIGHLIGHT: imHighlight = src.imHighlight; break; case EINPUT_METHOD_UNDERLINE: imUnderline = src.imUnderline; break; case ESWAP_COLORS: swapColors = src.swapColors; break; case ENUMERIC_SHAPING: numericShaping = src.numericShaping; break; case EKERNING: kerning = src.kerning; break; case ELIGATURES: ligatures = src.ligatures; break; case ETRACKING: tracking = src.tracking; break; default: throw new InternalError(); } } private boolean i_equals(EAttribute a, AttributeValues src) { switch (a) { case EFAMILY: return equals(family, src.family); case EWEIGHT: return weight == src.weight; case EWIDTH: return width == src.width; case EPOSTURE: return posture == src.posture; case ESIZE: return size == src.size; case ETRANSFORM: return equals(transform, src.transform); case ESUPERSCRIPT: return superscript == src.superscript; case EFONT: return equals(font, src.font); case ECHAR_REPLACEMENT: return equals(charReplacement, src.charReplacement); case EFOREGROUND: return equals(foreground, src.foreground); case EBACKGROUND: return equals(background, src.background); case EUNDERLINE: return underline == src.underline; case ESTRIKETHROUGH: return strikethrough == src.strikethrough; case ERUN_DIRECTION: return runDirection == src.runDirection; case EBIDI_EMBEDDING: return bidiEmbedding == src.bidiEmbedding; case EJUSTIFICATION: return justification == src.justification; case EINPUT_METHOD_HIGHLIGHT: return equals(imHighlight, src.imHighlight); case EINPUT_METHOD_UNDERLINE: return imUnderline == src.imUnderline; case ESWAP_COLORS: return swapColors == src.swapColors; case ENUMERIC_SHAPING: return equals(numericShaping, src.numericShaping); case EKERNING: return kerning == src.kerning; case ELIGATURES: return ligatures == src.ligatures; case ETRACKING: return tracking == src.tracking; default: throw new InternalError(); } } private void i_set(EAttribute a, Object o) { switch (a) { case EFAMILY: family = ((String)o).trim(); break; case EWEIGHT: weight = ((Number)o).floatValue(); break; case EWIDTH: width = ((Number)o).floatValue(); break; case EPOSTURE: posture = ((Number)o).floatValue(); break; case ESIZE: size = ((Number)o).floatValue(); break; case ETRANSFORM: { if (o instanceof TransformAttribute) { TransformAttribute ta = (TransformAttribute)o; if (ta.isIdentity()) { transform = null; } else { transform = ta.getTransform(); } } else { transform = new AffineTransform((AffineTransform)o); } updateDerivedTransforms(); } break; case ESUPERSCRIPT: superscript = (byte)((Integer)o).intValue(); break; case EFONT: font = (Font)o; break; case ECHAR_REPLACEMENT: charReplacement = (GraphicAttribute)o; break; case EFOREGROUND: foreground = (Paint)o; break; case EBACKGROUND: background = (Paint)o; break; case EUNDERLINE: underline = (byte)((Integer)o).intValue(); break; case ESTRIKETHROUGH: strikethrough = ((Boolean)o).booleanValue(); break; case ERUN_DIRECTION: { if (o instanceof Boolean) { runDirection = (byte)(TextAttribute.RUN_DIRECTION_LTR.equals(o) ? 0 : 1); } else { runDirection = (byte)((Integer)o).intValue(); } } break; case EBIDI_EMBEDDING: bidiEmbedding = (byte)((Integer)o).intValue(); break; case EJUSTIFICATION: justification = ((Number)o).floatValue(); break; case EINPUT_METHOD_HIGHLIGHT: { if (o instanceof Annotation) { Annotation at = (Annotation)o; imHighlight = (InputMethodHighlight)at.getValue(); } else { imHighlight = (InputMethodHighlight)o; } } break; case EINPUT_METHOD_UNDERLINE: imUnderline = (byte)((Integer)o).intValue(); break; case ESWAP_COLORS: swapColors = ((Boolean)o).booleanValue(); break; case ENUMERIC_SHAPING: numericShaping = (NumericShaper)o; break; case EKERNING: kerning = (byte)((Integer)o).intValue(); break; case ELIGATURES: ligatures = (byte)((Integer)o).intValue(); break; case ETRACKING: tracking = ((Number)o).floatValue(); break; default: throw new InternalError(); } } private Object i_get(EAttribute a) { switch (a) { case EFAMILY: return family; case EWEIGHT: return Float.valueOf(weight); case EWIDTH: return Float.valueOf(width); case EPOSTURE: return Float.valueOf(posture); case ESIZE: return Float.valueOf(size); case ETRANSFORM: return transform == null ? TransformAttribute.IDENTITY : new TransformAttribute(transform); case ESUPERSCRIPT: return Integer.valueOf(superscript); case EFONT: return font; case ECHAR_REPLACEMENT: return charReplacement; case EFOREGROUND: return foreground; case EBACKGROUND: return background; case EUNDERLINE: return Integer.valueOf(underline); case ESTRIKETHROUGH: return Boolean.valueOf(strikethrough); case ERUN_DIRECTION: { switch (runDirection) { // todo: figure out a way to indicate this value // case -1: return Integer.valueOf(runDirection); case 0: return TextAttribute.RUN_DIRECTION_LTR; case 1: return TextAttribute.RUN_DIRECTION_RTL; default: return null; } } // not reachable case EBIDI_EMBEDDING: return Integer.valueOf(bidiEmbedding); case EJUSTIFICATION: return Float.valueOf(justification); case EINPUT_METHOD_HIGHLIGHT: return imHighlight; case EINPUT_METHOD_UNDERLINE: return Integer.valueOf(imUnderline); case ESWAP_COLORS: return Boolean.valueOf(swapColors); case ENUMERIC_SHAPING: return numericShaping; case EKERNING: return Integer.valueOf(kerning); case ELIGATURES: return Integer.valueOf(ligatures); case ETRACKING: return Float.valueOf(tracking); default: throw new InternalError(); } } private boolean i_validate(EAttribute a) { switch (a) { case EFAMILY: if (family == null || family.length() == 0) family = DEFAULT.family; return true; case EWEIGHT: return weight > 0 && weight < 10; case EWIDTH: return width >= .5f && width < 10; case EPOSTURE: return posture >= -1 && posture <= 1; case ESIZE: return size >= 0; case ETRANSFORM: if (transform != null && transform.isIdentity()) transform = DEFAULT.transform; return true; case ESUPERSCRIPT: return superscript >= -7 && superscript <= 7; case EFONT: return true; case ECHAR_REPLACEMENT: return true; case EFOREGROUND: return true; case EBACKGROUND: return true; case EUNDERLINE: return underline >= -1 && underline < 6; case ESTRIKETHROUGH: return true; case ERUN_DIRECTION: return runDirection >= -2 && runDirection <= 1; case EBIDI_EMBEDDING: return bidiEmbedding >= -61 && bidiEmbedding < 62; case EJUSTIFICATION: justification = max(0, min (justification, 1)); return true; case EINPUT_METHOD_HIGHLIGHT: return true; case EINPUT_METHOD_UNDERLINE: return imUnderline >= -1 && imUnderline < 6; case ESWAP_COLORS: return true; case ENUMERIC_SHAPING: return true; case EKERNING: return kerning >= 0 && kerning <= 1; case ELIGATURES: return ligatures >= 0 && ligatures <= 1; case ETRACKING: return tracking >= -1 && tracking <= 10; default: throw new InternalError("unknown attribute: " + a); } } // Until textlayout is fixed to use AttributeValues, we'll end up // creating a map from the values for it. This is a compromise between // creating the whole map and just checking a particular value. // Plan to remove these. public static float getJustification(Map<?, ?> map) { if (map != null) { if (map instanceof AttributeMap && ((AttributeMap) map).getValues() != null) { return ((AttributeMap)map).getValues().justification; } Object obj = map.get(TextAttribute.JUSTIFICATION); if (obj != null && obj instanceof Number) { return max(0, min(1, ((Number)obj).floatValue())); } } return DEFAULT.justification; } public static NumericShaper getNumericShaping(Map<?, ?> map) { if (map != null) { if (map instanceof AttributeMap && ((AttributeMap) map).getValues() != null) { return ((AttributeMap)map).getValues().numericShaping; } Object obj = map.get(TextAttribute.NUMERIC_SHAPING); if (obj != null && obj instanceof NumericShaper) { return (NumericShaper)obj; } } return DEFAULT.numericShaping; } /** * If this has an imHighlight, create copy of this with those attributes * applied to it. Otherwise return this unchanged. */ public AttributeValues applyIMHighlight() { if (imHighlight != null) { InputMethodHighlight hl = null; if (imHighlight instanceof InputMethodHighlight) { hl = (InputMethodHighlight)imHighlight; } else { hl = (InputMethodHighlight)((Annotation)imHighlight).getValue(); } Map imStyles = hl.getStyle(); if (imStyles == null) { Toolkit tk = Toolkit.getDefaultToolkit(); imStyles = tk.mapInputMethodHighlight(hl); } if (imStyles != null) { return clone().merge(imStyles); } } return this; } public static AffineTransform getBaselineTransform(Map<?, ?> map) { if (map != null) { AttributeValues av = null; if (map instanceof AttributeMap && ((AttributeMap) map).getValues() != null) { av = ((AttributeMap)map).getValues(); } else if (map.get(TextAttribute.TRANSFORM) != null) { av = AttributeValues.fromMap((Map<Attribute, ?>)map); // yuck } if (av != null) { return av.baselineTransform; } } return null; } public static AffineTransform getCharTransform(Map<?, ?> map) { if (map != null) { AttributeValues av = null; if (map instanceof AttributeMap && ((AttributeMap) map).getValues() != null) { av = ((AttributeMap)map).getValues(); } else if (map.get(TextAttribute.TRANSFORM) != null) { av = AttributeValues.fromMap((Map<Attribute, ?>)map); // yuck } if (av != null) { return av.charTransform; } } return null; } public void updateDerivedTransforms() { // this also updates the mask for the baseline transform if (transform == null) { baselineTransform = null; charTransform = null; } else { charTransform = new AffineTransform(transform); baselineTransform = extractXRotation(charTransform, true); if (charTransform.isIdentity()) { charTransform = null; } if (baselineTransform.isIdentity()) { baselineTransform = null; } } if (baselineTransform == null) { nondefault &= ~EBASELINE_TRANSFORM.mask; } else { nondefault |= EBASELINE_TRANSFORM.mask; } } public static AffineTransform extractXRotation(AffineTransform tx, boolean andTranslation) { return extractRotation(new Point2D.Double(1, 0), tx, andTranslation); } public static AffineTransform extractYRotation(AffineTransform tx, boolean andTranslation) { return extractRotation(new Point2D.Double(0, 1), tx, andTranslation); } private static AffineTransform extractRotation(Point2D.Double pt, AffineTransform tx, boolean andTranslation) { tx.deltaTransform(pt, pt); AffineTransform rtx = AffineTransform.getRotateInstance(pt.x, pt.y); try { AffineTransform rtxi = rtx.createInverse(); double dx = tx.getTranslateX(); double dy = tx.getTranslateY(); tx.preConcatenate(rtxi); if (andTranslation) { if (dx != 0 || dy != 0) { tx.setTransform(tx.getScaleX(), tx.getShearY(), tx.getShearX(), tx.getScaleY(), 0, 0); rtx.setTransform(rtx.getScaleX(), rtx.getShearY(), rtx.getShearX(), rtx.getScaleY(), dx, dy); } } } catch (NoninvertibleTransformException e) { return null; } return rtx; }}Lines 501–907 of 907. Previous lines
StringBuilder b = new StringBuilder(); b.append('{'); for (int m = defined, i = 0; m != 0; ++i) { EAttribute ea = EAttribute.atts[i]; if ((m & ea.mask) != 0) { m &= ~ea.mask; if (b.length() > 1) { b.append(", "); } b.append(ea); b.append('='); switch (ea) { case EFAMILY: b.append('"'); b.append(family); b.append('"'); break; case EWEIGHT: b.append(weight); break; case EWIDTH: b.append(width); break; case EPOSTURE: b.append(posture); break; case ESIZE: b.append(size); break; case ETRANSFORM: b.append(transform); break; case ESUPERSCRIPT: b.append(superscript); break; case EFONT: b.append(font); break; case ECHAR_REPLACEMENT: b.append(charReplacement); break; case EFOREGROUND: b.append(foreground); break; case EBACKGROUND: b.append(background); break; case EUNDERLINE: b.append(underline); break; case ESTRIKETHROUGH: b.append(strikethrough); break; case ERUN_DIRECTION: b.append(runDirection); break; case EBIDI_EMBEDDING: b.append(bidiEmbedding); break; case EJUSTIFICATION: b.append(justification); break; case EINPUT_METHOD_HIGHLIGHT: b.append(imHighlight); break; case EINPUT_METHOD_UNDERLINE: b.append(imUnderline); break; case ESWAP_COLORS: b.append(swapColors); break; case ENUMERIC_SHAPING: b.append(numericShaping); break; case EKERNING: b.append(kerning); break; case ELIGATURES: b.append(ligatures); break; case ETRACKING: b.append(tracking); break; default: throw new InternalError(); } if ((nondefault & ea.mask) == 0) { b.append('*'); } } } b.append("[btx=" + baselineTransform + ", ctx=" + charTransform + "]"); b.append('}'); return b.toString(); } // internal utilities private static boolean equals(Object lhs, Object rhs) { return lhs == null ? rhs == null : lhs.equals(rhs); } private void update(EAttribute a) { defined |= a.mask; if (i_validate(a)) { if (i_equals(a, DEFAULT)) { nondefault &= ~a.mask; } else { nondefault |= a.mask; } } else { setDefault(a); } } // dispatch private void i_set(EAttribute a, AttributeValues src) { switch (a) { case EFAMILY: family = src.family; break; case EWEIGHT: weight = src.weight; break; case EWIDTH: width = src.width; break; case EPOSTURE: posture = src.posture; break; case ESIZE: size = src.size; break; case ETRANSFORM: transform = src.transform; updateDerivedTransforms(); break; case ESUPERSCRIPT: superscript = src.superscript; break; case EFONT: font = src.font; break; case ECHAR_REPLACEMENT: charReplacement = src.charReplacement; break; case EFOREGROUND: foreground = src.foreground; break; case EBACKGROUND: background = src.background; break; case EUNDERLINE: underline = src.underline; break; case ESTRIKETHROUGH: strikethrough = src.strikethrough; break; case ERUN_DIRECTION: runDirection = src.runDirection; break; case EBIDI_EMBEDDING: bidiEmbedding = src.bidiEmbedding; break; case EJUSTIFICATION: justification = src.justification; break; case EINPUT_METHOD_HIGHLIGHT: imHighlight = src.imHighlight; break; case EINPUT_METHOD_UNDERLINE: imUnderline = src.imUnderline; break; case ESWAP_COLORS: swapColors = src.swapColors; break; case ENUMERIC_SHAPING: numericShaping = src.numericShaping; break; case EKERNING: kerning = src.kerning; break; case ELIGATURES: ligatures = src.ligatures; break; case ETRACKING: tracking = src.tracking; break; default: throw new InternalError(); } } private boolean i_equals(EAttribute a, AttributeValues src) { switch (a) { case EFAMILY: return equals(family, src.family); case EWEIGHT: return weight == src.weight; case EWIDTH: return width == src.width; case EPOSTURE: return posture == src.posture; case ESIZE: return size == src.size; case ETRANSFORM: return equals(transform, src.transform); case ESUPERSCRIPT: return superscript == src.superscript; case EFONT: return equals(font, src.font); case ECHAR_REPLACEMENT: return equals(charReplacement, src.charReplacement); case EFOREGROUND: return equals(foreground, src.foreground); case EBACKGROUND: return equals(background, src.background); case EUNDERLINE: return underline == src.underline; case ESTRIKETHROUGH: return strikethrough == src.strikethrough; case ERUN_DIRECTION: return runDirection == src.runDirection; case EBIDI_EMBEDDING: return bidiEmbedding == src.bidiEmbedding; case EJUSTIFICATION: return justification == src.justification; case EINPUT_METHOD_HIGHLIGHT: return equals(imHighlight, src.imHighlight); case EINPUT_METHOD_UNDERLINE: return imUnderline == src.imUnderline; case ESWAP_COLORS: return swapColors == src.swapColors; case ENUMERIC_SHAPING: return equals(numericShaping, src.numericShaping); case EKERNING: return kerning == src.kerning; case ELIGATURES: return ligatures == src.ligatures; case ETRACKING: return tracking == src.tracking; default: throw new InternalError(); } } private void i_set(EAttribute a, Object o) { switch (a) { case EFAMILY: family = ((String)o).trim(); break; case EWEIGHT: weight = ((Number)o).floatValue(); break; case EWIDTH: width = ((Number)o).floatValue(); break; case EPOSTURE: posture = ((Number)o).floatValue(); break; case ESIZE: size = ((Number)o).floatValue(); break; case ETRANSFORM: { if (o instanceof TransformAttribute) { TransformAttribute ta = (TransformAttribute)o; if (ta.isIdentity()) { transform = null; } else { transform = ta.getTransform(); } } else { transform = new AffineTransform((AffineTransform)o); } updateDerivedTransforms(); } break; case ESUPERSCRIPT: superscript = (byte)((Integer)o).intValue(); break; case EFONT: font = (Font)o; break; case ECHAR_REPLACEMENT: charReplacement = (GraphicAttribute)o; break; case EFOREGROUND: foreground = (Paint)o; break; case EBACKGROUND: background = (Paint)o; break; case EUNDERLINE: underline = (byte)((Integer)o).intValue(); break; case ESTRIKETHROUGH: strikethrough = ((Boolean)o).booleanValue(); break; case ERUN_DIRECTION: { if (o instanceof Boolean) { runDirection = (byte)(TextAttribute.RUN_DIRECTION_LTR.equals(o) ? 0 : 1); } else { runDirection = (byte)((Integer)o).intValue(); } } break; case EBIDI_EMBEDDING: bidiEmbedding = (byte)((Integer)o).intValue(); break; case EJUSTIFICATION: justification = ((Number)o).floatValue(); break; case EINPUT_METHOD_HIGHLIGHT: { if (o instanceof Annotation) { Annotation at = (Annotation)o; imHighlight = (InputMethodHighlight)at.getValue(); } else { imHighlight = (InputMethodHighlight)o; } } break; case EINPUT_METHOD_UNDERLINE: imUnderline = (byte)((Integer)o).intValue(); break; case ESWAP_COLORS: swapColors = ((Boolean)o).booleanValue(); break; case ENUMERIC_SHAPING: numericShaping = (NumericShaper)o; break; case EKERNING: kerning = (byte)((Integer)o).intValue(); break; case ELIGATURES: ligatures = (byte)((Integer)o).intValue(); break; case ETRACKING: tracking = ((Number)o).floatValue(); break; default: throw new InternalError(); } } private Object i_get(EAttribute a) { switch (a) { case EFAMILY: return family; case EWEIGHT: return Float.valueOf(weight); case EWIDTH: return Float.valueOf(width); case EPOSTURE: return Float.valueOf(posture); case ESIZE: return Float.valueOf(size); case ETRANSFORM: return transform == null ? TransformAttribute.IDENTITY : new TransformAttribute(transform); case ESUPERSCRIPT: return Integer.valueOf(superscript); case EFONT: return font; case ECHAR_REPLACEMENT: return charReplacement; case EFOREGROUND: return foreground; case EBACKGROUND: return background; case EUNDERLINE: return Integer.valueOf(underline); case ESTRIKETHROUGH: return Boolean.valueOf(strikethrough); case ERUN_DIRECTION: { switch (runDirection) { // todo: figure out a way to indicate this value // case -1: return Integer.valueOf(runDirection); case 0: return TextAttribute.RUN_DIRECTION_LTR; case 1: return TextAttribute.RUN_DIRECTION_RTL; default: return null; } } // not reachable case EBIDI_EMBEDDING: return Integer.valueOf(bidiEmbedding); case EJUSTIFICATION: return Float.valueOf(justification); case EINPUT_METHOD_HIGHLIGHT: return imHighlight; case EINPUT_METHOD_UNDERLINE: return Integer.valueOf(imUnderline); case ESWAP_COLORS: return Boolean.valueOf(swapColors); case ENUMERIC_SHAPING: return numericShaping; case EKERNING: return Integer.valueOf(kerning); case ELIGATURES: return Integer.valueOf(ligatures); case ETRACKING: return Float.valueOf(tracking); default: throw new InternalError(); } } private boolean i_validate(EAttribute a) { switch (a) { case EFAMILY: if (family == null || family.length() == 0) family = DEFAULT.family; return true; case EWEIGHT: return weight > 0 && weight < 10; case EWIDTH: return width >= .5f && width < 10; case EPOSTURE: return posture >= -1 && posture <= 1; case ESIZE: return size >= 0; case ETRANSFORM: if (transform != null && transform.isIdentity()) transform = DEFAULT.transform; return true; case ESUPERSCRIPT: return superscript >= -7 && superscript <= 7; case EFONT: return true; case ECHAR_REPLACEMENT: return true; case EFOREGROUND: return true; case EBACKGROUND: return true; case EUNDERLINE: return underline >= -1 && underline < 6; case ESTRIKETHROUGH: return true; case ERUN_DIRECTION: return runDirection >= -2 && runDirection <= 1; case EBIDI_EMBEDDING: return bidiEmbedding >= -61 && bidiEmbedding < 62; case EJUSTIFICATION: justification = max(0, min (justification, 1)); return true; case EINPUT_METHOD_HIGHLIGHT: return true; case EINPUT_METHOD_UNDERLINE: return imUnderline >= -1 && imUnderline < 6; case ESWAP_COLORS: return true; case ENUMERIC_SHAPING: return true; case EKERNING: return kerning >= 0 && kerning <= 1; case ELIGATURES: return ligatures >= 0 && ligatures <= 1; case ETRACKING: return tracking >= -1 && tracking <= 10; default: throw new InternalError("unknown attribute: " + a); } } // Until textlayout is fixed to use AttributeValues, we'll end up // creating a map from the values for it. This is a compromise between // creating the whole map and just checking a particular value. // Plan to remove these. public static float getJustification(Map<?, ?> map) { if (map != null) { if (map instanceof AttributeMap && ((AttributeMap) map).getValues() != null) { return ((AttributeMap)map).getValues().justification; } Object obj = map.get(TextAttribute.JUSTIFICATION); if (obj != null && obj instanceof Number) { return max(0, min(1, ((Number)obj).floatValue())); } } return DEFAULT.justification; } public static NumericShaper getNumericShaping(Map<?, ?> map) { if (map != null) { if (map instanceof AttributeMap && ((AttributeMap) map).getValues() != null) { return ((AttributeMap)map).getValues().numericShaping; } Object obj = map.get(TextAttribute.NUMERIC_SHAPING); if (obj != null && obj instanceof NumericShaper) { return (NumericShaper)obj; } } return DEFAULT.numericShaping; } /** * If this has an imHighlight, create copy of this with those attributes * applied to it. Otherwise return this unchanged. */ public AttributeValues applyIMHighlight() { if (imHighlight != null) { InputMethodHighlight hl = null; if (imHighlight instanceof InputMethodHighlight) { hl = (InputMethodHighlight)imHighlight; } else { hl = (InputMethodHighlight)((Annotation)imHighlight).getValue(); } Map imStyles = hl.getStyle(); if (imStyles == null) { Toolkit tk = Toolkit.getDefaultToolkit(); imStyles = tk.mapInputMethodHighlight(hl); } if (imStyles != null) { return clone().merge(imStyles); } } return this; } public static AffineTransform getBaselineTransform(Map<?, ?> map) { if (map != null) { AttributeValues av = null; if (map instanceof AttributeMap && ((AttributeMap) map).getValues() != null) { av = ((AttributeMap)map).getValues(); } else if (map.get(TextAttribute.TRANSFORM) != null) { av = AttributeValues.fromMap((Map<Attribute, ?>)map); // yuck } if (av != null) { return av.baselineTransform; } } return null; } public static AffineTransform getCharTransform(Map<?, ?> map) { if (map != null) { AttributeValues av = null; if (map instanceof AttributeMap && ((AttributeMap) map).getValues() != null) { av = ((AttributeMap)map).getValues(); } else if (map.get(TextAttribute.TRANSFORM) != null) { av = AttributeValues.fromMap((Map<Attribute, ?>)map); // yuck } if (av != null) { return av.charTransform; } } return null; } public void updateDerivedTransforms() { // this also updates the mask for the baseline transform if (transform == null) { baselineTransform = null; charTransform = null; } else { charTransform = new AffineTransform(transform); baselineTransform = extractXRotation(charTransform, true); if (charTransform.isIdentity()) { charTransform = null; } if (baselineTransform.isIdentity()) { baselineTransform = null; } } if (baselineTransform == null) { nondefault &= ~EBASELINE_TRANSFORM.mask; } else { nondefault |= EBASELINE_TRANSFORM.mask; } } public static AffineTransform extractXRotation(AffineTransform tx, boolean andTranslation) { return extractRotation(new Point2D.Double(1, 0), tx, andTranslation); } public static AffineTransform extractYRotation(AffineTransform tx, boolean andTranslation) { return extractRotation(new Point2D.Double(0, 1), tx, andTranslation); } private static AffineTransform extractRotation(Point2D.Double pt, AffineTransform tx, boolean andTranslation) { tx.deltaTransform(pt, pt); AffineTransform rtx = AffineTransform.getRotateInstance(pt.x, pt.y); try { AffineTransform rtxi = rtx.createInverse(); double dx = tx.getTranslateX(); double dy = tx.getTranslateY(); tx.preConcatenate(rtxi); if (andTranslation) { if (dx != 0 || dy != 0) { tx.setTransform(tx.getScaleX(), tx.getShearY(), tx.getShearX(), tx.getScaleY(), 0, 0); rtx.setTransform(rtx.getScaleX(), rtx.getShearY(), rtx.getShearX(), rtx.getScaleY(), dx, dy); } } } catch (NoninvertibleTransformException e) { return null; } return rtx; } }