All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.xfa.text.TextBaselineShift Maven / Gradle / Ivy

There is a newer version: 2024.11.18751.20241128T090041Z-241100
Show newest version
package com.adobe.xfa.text;

import com.adobe.xfa.ut.UnitSpan;


/**
 * This class defines a text baseline shift attribute.
 * It's loosely modelled after the proposed XSL baseline shift attribute
 * See baseline-shift
 *
 * The differences in implementation from the XSL variation include:
* 1. We support only baseline, <percentage> and <length> values
* 2. The adjusted baseline will be calculated relative to the preceding text, * rather than the parent.
* 3. There is no accompanying "shift-direction" attribute, so negative percentages and lengths will shift up, and positive values will shift down. * * @author John Brinkman * @exclude from published api -- Mike Tardif, May 2006. */ public class TextBaselineShift { public static final int BASELINE = 0; public static final int PERCENTAGE = 1; public static final int LENGTH = 2; public static final int SUBSCRIPT = 3; public static final int SUPERSCRIPT = 4; public final static TextBaselineShift DEFAULT_SHIFT = new TextBaselineShift(); private int meType = BASELINE; private UnitSpan moLength; private double mdPercentage; private int mnLevel; /** * Default constructor. Creates a baseline shift with a value "baseline" - * No baseline shift. */ public TextBaselineShift () { } /** * Copy constructor * @param oSource the TextBaselineShift object to copy */ public TextBaselineShift (TextBaselineShift oSource) { copy (oSource); } /** * Create a baseline shift with a percentage offset * @param dPercentage the amount to shift by. Negative percentages shift * up, positive values shift down. The percentage is relative to the current * line height. */ public TextBaselineShift (double dPercentage) { meType = PERCENTAGE; mdPercentage = dPercentage; } /** * Create a baseline shift with a fixed offset * @param oLength the absolute value to shift by. Negative values shift up, * positive values shift down. */ public TextBaselineShift (UnitSpan oLength) { meType = LENGTH; moLength = oLength; } /** * Create a baseline shift by type, with optional level. *

* This constructor is intended primarily to create subscript and * superscript baseline shifts. It can take any type code, but if that * code is not for a subscript or superscript, the shift is effectively * neutral. *

* @param eType - Type code for the new shift object. * @param nLevel - Subscript or superscript level. Ignored if the type * code is for something other than subscript or superscript. Defaults * to one. */ public TextBaselineShift (int eType, int nLevel) { meType = eType; if ((eType == SUBSCRIPT) || (eType == SUPERSCRIPT)) { mnLevel = nLevel; } } /** * Create a baseline shift from a string * @param sString a textual representation of the baseline value. Should be * something like "baseline" or "15%" or "2pt". */ public TextBaselineShift (String sString, boolean bSuppressInversion) { sString = sString.trim(); mdPercentage = 0.0; if (sString.equals ("baseline")) { meType = BASELINE; return; } else if (sString.equals ("sub")) { meType = SUBSCRIPT; mnLevel = 1; } else if (sString.equals ("super")) { meType = SUPERSCRIPT; mnLevel = 1; } int nFound = sString.indexOf ('%'); if (nFound >= 0) { sString = sString.substring(0, nFound); mdPercentage = Double.parseDouble (sString); mdPercentage = mdPercentage / 100.0; if (!bSuppressInversion) { mdPercentage = -mdPercentage; } meType = PERCENTAGE; } else { // Must be a unitspan moLength = new UnitSpan(sString); if (! bSuppressInversion) { moLength = new UnitSpan(moLength.units(), -moLength.value()); } meType = LENGTH; } } /** * Apply this baseline shift to a baseline value and return font size * @param oStartingBaseline the current baseline position * @param oLineHeight The height of the current line * @return A two UnitSpan array with the adjusted baseline value and the new font size. */ public UnitSpan[] flatten (UnitSpan oStartingBaseline, UnitSpan oLineHeight, UnitSpan poFontSize) { UnitSpan baseline = oStartingBaseline; UnitSpan fontSize = (poFontSize != null) ? poFontSize : oLineHeight; switch (meType) { case BASELINE: break; case PERCENTAGE: baseline = oStartingBaseline.add (oLineHeight.multiply (mdPercentage)); break; case LENGTH: baseline = oStartingBaseline.add (moLength); break; default: { boolean bIsSuper = meType == SUPERSCRIPT; double nBaseScale = bIsSuper ? 0.31 : 0.15; double nFontScale = 0.66; UnitSpan shift = oLineHeight.multiply (nBaseScale); if (bIsSuper) { shift = new UnitSpan (shift.units(), shift.value()); } for (int i = 0; i < mnLevel; i++) { baseline = baseline.add (shift); shift = shift.multiply (nFontScale); fontSize = fontSize.multiply (nFontScale); } } } UnitSpan[] result = new UnitSpan [2]; result[0] = baseline; result[1] = fontSize; return result; } /** * Apply this baseline shift to a baseline value * @param oStartingBaseline the current baseline position * @param oLineHeight The height of the current line * @return the adjusted baseline value. */ public UnitSpan applyShift (UnitSpan oStartingBaseline, UnitSpan oLineHeight) { if (isNeutral()) { return oStartingBaseline; } UnitSpan[] result = flatten (oStartingBaseline, oLineHeight, oLineHeight); return result[0]; } /** * Represent the value of this shift as a string * @return a string that represents this shift. A value such as: "baseline" or * "25%" or "0.15in" */ public String getString (boolean bSuppressInversion) { switch (meType) { case BASELINE: return "baseline"; case SUBSCRIPT: return "sub"; case SUPERSCRIPT: return "super"; case PERCENTAGE: double dValue = mdPercentage * 100.0; if (! bSuppressInversion) { dValue = -dValue; } return Double.toString (dValue) + '%'; // TODO: limit decimal places default: UnitSpan oValue = moLength; if (! bSuppressInversion) { oValue = new UnitSpan(oValue.units(), -oValue.value()); } return oValue.toString(); // TODO: had fancy conversion parameters } } /** * Return the type of shift. * @return A value from the TypeCode enumeration to indicate whether * this is an absolute, percentage or neutral shift. */ public int getType () { return meType; } /** * Return the absolute shift. * @return absolute shift amount. Value is meaningful only if this is * an absolute (length) type shift. */ public UnitSpan getLength () { return (moLength == null) ? UnitSpan.ZERO : moLength; } /** * Return the percentage shift. * @return Percentage shift amount. Value is meaningful only if this is * a percentage type shift. */ public double getPercentage () { return mdPercentage; } /** * Return the subscript or superscript level. * @return Subscript or superscript level. Value is meaningful only if * this is a subscript or superscript type shift. */ public int getLevel () { return mnLevel; } /** * Find out whether this shift has no effect. * @return Boolean indicating TRUE if the shift is neutral. */ public boolean isNeutral () { switch (meType) { case BASELINE: return true; case LENGTH: return (moLength == null) || (moLength.value() == 0); case PERCENTAGE: return mdPercentage == 0.0; default: return mnLevel == 0; } } /** * Find out whether this shift adjusts in the positive (down/subscript) * direction or not. * @return Boolean indicating TRUE if the shift is downward. */ public boolean isDownShift () { switch (meType) { case LENGTH: return moLength.value() > 0; case PERCENTAGE: return mdPercentage > 0.0; case SUBSCRIPT: return mnLevel != 0; default: return false; } } /** * Assignment operator * @param oSource the object to copy * @return this object */ public TextBaselineShift copyFrom (TextBaselineShift oSource) { copy (oSource); return this; } /** * Equality operator * @param object the object to compare * @return one if equal */ public boolean equals (Object object) { if (this == object) return true; // This overrides Object.equals(boolean) directly, so... if (object == null) return false; if (object.getClass() != getClass()) return false; TextBaselineShift cmp = (TextBaselineShift) object; if (isNeutral() && cmp.isNeutral()) { return true; } if (meType != cmp.meType) { return false; } switch (meType) { case BASELINE: return true; case PERCENTAGE: return mdPercentage == cmp.mdPercentage; case LENGTH: return moLength == cmp.moLength; default: return mnLevel == cmp.mnLevel; } } public int hashCode() { int hash = 43; hash = (hash * 31) ^ Boolean.valueOf(isNeutral()).hashCode(); hash = (hash * 31) ^ meType; switch (meType) { case BASELINE: hash = (hash * 31) ^ 1; break; case PERCENTAGE: { long bits = Double.doubleToLongBits(mdPercentage); hash = (hash * 31) ^ (int) (bits ^ (bits >>> 32)); break; } case LENGTH: hash = (hash * 31) ^ moLength.hashCode(); break; default: hash = (hash * 31) ^ mnLevel; break; } return hash; } /** * Inequality operator * @param oCompare the object to compare * @return one if not equal */ public boolean notEqual (TextBaselineShift oCompare) { return ! equals (oCompare); } private void copy (TextBaselineShift oSrc) { meType = oSrc.meType; mdPercentage = oSrc.mdPercentage; moLength = oSrc.moLength; mnLevel = oSrc.mnLevel; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy