com.adobe.xfa.text.TextBaselineShift Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
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