com.adobe.xfa.text.markup.MarkupEngineOut 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
//----------------------------------------------------------------------
//
// ADOBE CONFIDENTIAL
// __________________
//
// Copyright 1995 - 2003 Adobe Systems Incorporated. All
// Rights Reserved.
//
// NOTICE: All information contained herein is, and remains
// the property of Adobe Systems Incorporated and its
// suppliers, if any. The intellectual and technical
// concepts contained herein are proprietary to Adobe Systems
// Incorporated and its suppliers and may be covered by U.S.
// and Foreign Patents, patents in process, and are protected
// by trade secret or copyright law. Dissemination of this
// information or reproduction of this material is strictly
// forbidden unless prior written permission is obtained from
// Adobe Systems Incorporated.
//
//----------------------------------------------------------------------
package com.adobe.xfa.text.markup;
import com.adobe.xfa.font.FontInfo;
import com.adobe.xfa.gfx.GFXColour;
import com.adobe.xfa.gfx.GFXTextAttr;
import com.adobe.xfa.text.TextAttr;
import com.adobe.xfa.text.TextMeasurement;
import com.adobe.xfa.text.TextTab;
import com.adobe.xfa.text.TextTabList;
import com.adobe.xfa.ut.UnitSpan;
/**
* Class MarkupEngineout represents the output markup engine.
* Referring to it as an engine is perhaps a bit of a misnomer in that
* it doesn't actualloy drive the generation of output markup; that is
* instead controlled by a text stream, which makes a series of calls to
* the output engine.
*
*
* One derives a class from this in order to implement a markup engine
* for a particular language.
*
*
* For more information, please see the extenral documentation.
*
*
* @exclude from published api -- Mike Tardif, May 2006.
*/
public class MarkupEngineOut extends MarkupOut {
private MarkupAttr mpMarkupAttr;
private final StringBuilder mpTranslation = new StringBuilder();
// How many levels deep are we nested?
private int miNestedDepth = 0;
// Keep track of our attribute state
private final TextAttr moAttrState = new TextAttr();
/**
* Obtain the output markup.
* @return Result of the markup operation, as a text string.
*/
public String translation () {
if (mpTranslation.length() > 0) {
// Ensure that all scoping blocks are terminated
while (miNestedDepth > 0) {
closeScopedBlock();
}
}
return mpTranslation.toString();
}
/**
* Reset the (derived) markup engine to its initial state.
*/
public void reset () {
moAttrState.setDefault (true);
moAttrState.typefaceEnable (false);
moAttrState.sizeEnable (false);
mpTranslation.delete (0, mpTranslation.length());
miNestedDepth = 0;
// mbFirstPara = true;
flushJustification();
flushSpacing();
flushIndentation();
}
/**
* Overridden: Output raw text content.
* @param sStrText - Text content to add to the markup output.
*/
public void text (String sStrText) {
mpTranslation.append (flushJustification());
mpTranslation.append (flushSpacing());
mpTranslation.append (flushIndentation());
StringBuilder oStrTextNew = new StringBuilder (sStrText);
String sUc = "\\uc";
int lBytes = 1;
for (int i = 0; i < oStrTextNew.length(); i++) {
char c = oStrTextNew.charAt (i); // TODO: C++ implementation doesn't use UniChar()
if ((c == '\\') || (mpMarkupAttr.hasBlockScoping() && (c == mpMarkupAttr.blockPrefix() || c == mpMarkupAttr.blockSuffix()))) {
// Escape the escape character, block prefix and suffix
oStrTextNew.insert (i, "\\");
i++;
} else if (c == '\t') {
String sReplace = mpMarkupAttr.lookup (MarkupAttr.MARKUP_TAB);
oStrTextNew.replace (i, i+1, sReplace);
if (sReplace.length() > 0) {
i += sReplace.length() - 1;
}
} else if (c == '\n') {
String sReplace = mpMarkupAttr.lookup (MarkupAttr.MARKUP_LINE);
oStrTextNew.replace (i, i+1, sReplace);
if (sReplace.length() > 0) {
i += sReplace.length() - 1;
}
} else if (c < 31) { //handle single byte special characters
String sReplacement = convertSpecialChar (c);
oStrTextNew.replace (i, i+1, sReplacement);
if (sReplacement.length() > 0) {
i += sReplacement.length() - 1;
}
} else if (c > 126) { //handle multi-byte special characters
char u = oStrTextNew.charAt (i); // TODO: it looks like the C++ version of this code has changed
StringBuilder sReplacement = new StringBuilder();
//create the unicode version
String sUnicode = "\\u";
sUnicode += Integer.toString (u);
//create the hex version
StringBuilder sHex = new StringBuilder (convertSpecialChar (u));
int count = 4;
while (sHex.length() > count) {
String sInsert = "\\'";
if (sHex.length() < (count + 2)) {
sInsert += "0";
}
sHex.replace (count, count, sInsert);
count += 4;
}
//check if we need to change the byte count (default = 1)
count = count / 4;
if (count != lBytes) {
sReplacement.append (sUc);
sReplacement.append (Integer.toString (count));
}
sReplacement.append (sUnicode);
sReplacement.append (sHex);
oStrTextNew.replace (i, i+1, sReplacement.toString());
if (sReplacement.length() > 0) {
i += sReplacement.length() - 1;
}
}
}
if (blockText()) {
mpTranslation.append ("{");
}
mpTranslation.append (oStrTextNew); // We used to add a line feed here to
if (blockText()) {
// keep our lines shorter; but it turns out
// that wasn't great when writing JetForm
// rich text to a data file.
mpTranslation.append ("}");
}
}
/**
* Overridden: Output an attribute change.
* @param oAttr - Attribute change to add to the markup output.
*/
public void attr (TextAttr oAttr) {
// Get a working copy of the attributes
TextAttr oChangedAttrs = new TextAttr (oAttr);
// Disable those attributes that haven't changed
oChangedAttrs.dropSame (moAttrState, false);
// Do the paragraph attributes first, in case the reader can't handle
// paragraph changes after other stuff. Paragraph attributes are not
// recognized by JetForm 4.x
String sIndentation = "";
String sJustification = "";
String sSpacing = "";
String sTabs = "";
if (mpMarkupAttr.hasParagraphAttr()) {
sIndentation = outputIndentation (oChangedAttrs);
sJustification = outputJustification (oChangedAttrs);
sSpacing = outputSpacing (oChangedAttrs);
sTabs = outputTabs (oChangedAttrs);
}
String sFont = outputFont (oChangedAttrs);
String sEffects = outputEffects (oChangedAttrs);
mpTranslation.append (sIndentation);
mpTranslation.append (sJustification);
mpTranslation.append (sSpacing);
mpTranslation.append (sTabs);
mpTranslation.append (sFont);
mpTranslation.append (sEffects);
// Track this new state for next time around
moAttrState.override (oAttr);
if (! oAttr.typefaceEnable()) {
// If the typeface wasn't specified in our new attributes,
// then unspecify it here as well. It's likely an indication that
// we want to return to the ambient typeface
moAttrState.typefaceEnable (false);
}
}
/**
* Overridden: Output a paragraph mark.
*/
//----------------------------------------------------------------------
//
// Para.
//
//----------------------------------------------------------------------
public void para () {
mpTranslation.append (flushJustification());
mpTranslation.append (mpMarkupAttr.lookup (MarkupAttr.MARKUP_PARAGRAPH_END));
mpTranslation.append (flushSpacing());
mpTranslation.append (flushIndentation());
}
/**
* Protected constructor.
* @param pMarkupAttr - Markup attribute table to use for this
* operation.
*/
protected MarkupEngineOut (MarkupAttr pMarkupAttr) {
mpMarkupAttr = pMarkupAttr;
reset();
}
/**
* Obtain the markup attrubute table.
* @return Markup attribute table pointer.
*/
protected MarkupAttr markupAttr () {
return mpMarkupAttr;
}
/**
* Non-const access to the translation text.
* @return Non-const pointer to the translation text.
*/
protected StringBuilder translationText () {
return mpTranslation;
}
//----------------------------------------------------------------------
//
// OutputEffects
// Appends the font effects.
//
//----------------------------------------------------------------------
protected String outputEffects (TextAttr oAttr) {
StringBuilder sOut = new StringBuilder();
//Underline
sOut.append (outputUnderline (oAttr));
if (oAttr.weightEnable()) {
// Bold On/OFF
sOut.append (mpMarkupAttr.lookup ((oAttr.weight() >= FontInfo.WEIGHT_BOLD) ? MarkupAttr.MARKUP_BOLD : MarkupAttr.MARKUP_BOLD_END));
}
if (oAttr.italicEnable()) {
// Italics
sOut.append (mpMarkupAttr.lookup (oAttr.italic() ? MarkupAttr.MARKUP_ITALIC : MarkupAttr.MARKUP_ITALIC_END));
}
if (oAttr.strikeoutEnable()) {
// Strikeout
sOut.append (mpMarkupAttr.lookup (oAttr.strikeout() == GFXTextAttr.STRIKEOUT_SINGLE ? MarkupAttr.MARKUP_STRIKEOUT : MarkupAttr.MARKUP_STRIKEOUT_END));
}
if (oAttr.baselineShiftEnable()) {
// Baseline Shift
UnitSpan oShift = oAttr.baselineShift().applyShift (UnitSpan.ZERO, oAttr.size());
oShift = oShift.abs();
if (oAttr.baselineShift().isDownShift()) {
sOut.append (outputPointSize (MarkupAttr.MARKUP_DOWN, oShift, true, markupAttr().pointSizeFactor()));
} else {
sOut.append (outputPointSize (MarkupAttr.MARKUP_UP, oShift, true, markupAttr().pointSizeFactor()));
}
}
if (oAttr.colourEnable()) {
sOut.append (outputColour (oAttr.colour()));
}
return sOut.toString();
}
//----------------------------------------------------------------------
//
// OutputFont
// Appends the font related commands to the translation string.
// Returns a boolean indicating whether anything was actually written.
//
//----------------------------------------------------------------------
protected String outputFont (TextAttr oAttr) {
StringBuilder sOut = new StringBuilder();
if (oAttr.typefaceEnable()) {
sOut.append (outputFontFaceName (oAttr));
}
// Size (in tenths of a point).
sOut.append (outputPointSize (MarkupAttr.MARKUP_FONT_SIZE, oAttr.size(), oAttr.sizeEnable(), markupAttr().pointSizeFactor()));
return sOut.toString();
}
//----------------------------------------------------------------------
//
// OutputFontFaceName
// Appends the font name to the translation string.
//
//----------------------------------------------------------------------
protected String outputFontFaceName (TextAttr oAttr) {
if (oAttr.typefaceEnable()) {
return oAttr.typeface();
}
return TextAttr.defaultFull.typeface();
}
protected String outputColour (GFXColour oColour) {
return "";
}
//----------------------------------------------------------------------
//
// OutputIndentation
// Appends the indentation related commands to the translation string.
//
//----------------------------------------------------------------------
protected String outputIndentation (TextAttr oAttr) {
StringBuilder sOut = new StringBuilder();
UnitSpan oSpecial = oAttr.flattenMeasurement (oAttr.special());
sOut.append (outputPointSize (MarkupAttr.MARKUP_INDENT_FIRST_LINE, oSpecial, oAttr.specialEnable()));
if (oAttr.specialEnable() && (oSpecial.value() < 0)) {
// RTF stores the left indent as the sum of "our" left indent and the
// hanging value (if hanging).
// Outdent equivalent
UnitSpan oMarginL; // defaults to zero
if (oAttr.marginLEnable()) {
oMarginL = oAttr.flattenMeasurement (oAttr.marginL());
} else {
oMarginL = UnitSpan.ZERO;
}
oMarginL = oMarginL.subtract (oSpecial);
sOut.append (outputPointSize (MarkupAttr.MARKUP_INDENT_LEFT, oMarginL));
}
else {
sOut.append (outputPointSize (oAttr, MarkupAttr.MARKUP_INDENT_LEFT, oAttr.marginL(), oAttr.marginLEnable()));
}
sOut.append (outputPointSize (oAttr, MarkupAttr.MARKUP_INDENT_RIGHT, oAttr.marginR(), oAttr.marginREnable()));
sOut.append (outputPointSize (oAttr, MarkupAttr.MARKUP_SPACE_BEFORE, oAttr.spaceBefore(), oAttr.spaceBeforeEnable()));
sOut.append (outputPointSize (oAttr, MarkupAttr.MARKUP_SPACE_AFTER, oAttr.spaceAfter(), oAttr.spaceAfterEnable()));
return sOut.toString();
}
//----------------------------------------------------------------------
//
// OutputJustification
// Appends the justification related commands to the translation string.
//
//----------------------------------------------------------------------
protected String outputJustification (TextAttr oAttr) {
StringBuilder sOut = new StringBuilder();
if (oAttr.justifyHEnable()) {
switch (oAttr.justifyH()) {
case TextAttr.JUST_H_LEFT:
sOut.append (mpMarkupAttr.lookup (MarkupAttr.MARKUP_JUSTIFY_HORZ_LEFT));
break;
case TextAttr.JUST_H_CENTRE:
sOut.append (mpMarkupAttr.lookup (MarkupAttr.MARKUP_JUSTIFY_HORZ_CENTER));
break;
case TextAttr.JUST_H_RIGHT:
sOut.append (mpMarkupAttr.lookup (MarkupAttr.MARKUP_JUSTIFY_HORZ_RIGHT));
break;
case TextAttr.JUST_H_SPREAD:
sOut.append (mpMarkupAttr.lookup (MarkupAttr.MARKUP_JUSTIFY_SPREAD));
break;
case TextAttr.JUST_H_SPREAD_ALL:
sOut.append (mpMarkupAttr.lookup (MarkupAttr.MARKUP_JUSTIFY_SPREAD_ALL));
break;
default:
break; // ignore
}
}
if (oAttr.justifyVEnable()) {
switch (oAttr.justifyV()) {
case TextAttr.JUST_V_TOP:
sOut.append (mpMarkupAttr.lookup (MarkupAttr.MARKUP_JUSTIFY_VERT_TOP));
break;
case TextAttr.JUST_V_MIDDLE:
sOut.append (mpMarkupAttr.lookup (MarkupAttr.MARKUP_JUSTIFY_VERT_CENTER));
break;
case TextAttr.JUST_V_BOTTOM:
sOut.append (mpMarkupAttr.lookup (MarkupAttr.MARKUP_JUSTIFY_VERT_BOTTOM));
break;
default:
break; // ignore
}
}
return sOut.toString();
}
//----------------------------------------------------------------------
//
// OutputTabs
// Appends the tab information to the translation string.
//
//----------------------------------------------------------------------
protected String outputTabs (TextAttr oAttr) {
StringBuilder sOut = new StringBuilder();
if (oAttr.tabsEnable()) {
TextTabList oTabList = oAttr.tabs();
sOut.append (outputPointSize (MarkupAttr.MARKUP_TAB_DEFAULT, oTabList.uniform().tabStop()));
for (int i = 1; i <= oTabList.size(); i++) {
TextTab oTab = oTabList.tabAt (i);
switch (oTab.tabType()) {
case TextTab.TYPE_CENTRE:
sOut.append (mpMarkupAttr.lookup (MarkupAttr.MARKUP_TAB_ALIGN_CENTER));
break;
case TextTab.TYPE_RIGHT:
case TextTab.TYPE_ALIGN_BEFORE:
sOut.append (mpMarkupAttr.lookup (MarkupAttr.MARKUP_TAB_ALIGN_RIGHT));
break;
case TextTab.TYPE_DECIMAL:
sOut.append (mpMarkupAttr.lookup (MarkupAttr.MARKUP_TAB_ALIGN_DECIMAL));
break;
case TextTab.TYPE_LEFT:
case TextTab.TYPE_ALIGN_AFTER:
default:
sOut.append (mpMarkupAttr.lookup (MarkupAttr.MARKUP_TAB_ALIGN_LEFT));
break;
}
sOut.append (outputPointSize (MarkupAttr.MARKUP_TAB_POSITION, oTab.tabStop()));
}
}
return sOut.toString();
}
//----------------------------------------------------------------------
//
// OutputUnderline
// Appends the underline cmd to the translation string.
//
//----------------------------------------------------------------------
protected String outputUnderline (TextAttr oAttr) {
if (oAttr.underlineEnable()) {
// Underline and all combinations of styles single, double
// and all types: all and word.
int eMarkup;
switch (oAttr.underline()) {
case (GFXTextAttr.UNDER_WORD | GFXTextAttr.UNDER_SINGLE):
eMarkup = MarkupAttr.MARKUP_UNDERLINE_WORD;
break;
case (GFXTextAttr.UNDER_ALL | GFXTextAttr.UNDER_SINGLE):
eMarkup = MarkupAttr.MARKUP_UNDERLINE;
break;
case (GFXTextAttr.UNDER_ALL | GFXTextAttr.UNDER_DOUBLE):
eMarkup = MarkupAttr.MARKUP_UNDERLINE_DOUBLE;
break;
case (GFXTextAttr.UNDER_WORD | GFXTextAttr.UNDER_DOUBLE):
eMarkup = MarkupAttr.MARKUP_UNDERLINE_WORD_DOUBLE;
break;
default:
eMarkup = MarkupAttr.MARKUP_UNDERLINE_END;
break;
}
return mpMarkupAttr.lookup (eMarkup);
}
return "";
}
protected String outputSpacing (TextAttr oAttr) {
return "";
}
//----------------------------------------------------------------------
//
// Special character handling - default implementations
//
//----------------------------------------------------------------------
protected boolean isSpecialChar (char c) {
return false;
}
protected String convertSpecialChar (char c) {
String s = "";
return s + c;
}
protected String flushJustification () {
return "";
}
protected String flushIndentation () {
return "";
}
protected String flushSpacing () {
return "";
}
protected boolean blockText () {
return true;
}
//----------------------------------------------------------------------
//
// SetMarkupAttr - assigns the mpMarkupAttr member.
//
//----------------------------------------------------------------------
protected void setMarkupAttr (MarkupAttr pMarkupAttr) {
mpMarkupAttr = pMarkupAttr;
}
//----------------------------------------------------------------------
//
// OpenScopedBlock
//
// Appends the translation string with the block scope open character
// if the markup language supports it.
//
//----------------------------------------------------------------------
public void openScopedBlock () {
if (mpMarkupAttr.hasBlockScoping()) {
mpTranslation.append (mpMarkupAttr.blockPrefix());
miNestedDepth++;
}
}
//----------------------------------------------------------------------
//
// CloseScopedBlock
//
// Appends the translation string with the block scope close character
// if the markup language supports it.
//
//----------------------------------------------------------------------
public void closeScopedBlock () {
if (mpMarkupAttr.hasBlockScoping()) {
mpTranslation.append (mpMarkupAttr.blockSuffix());
miNestedDepth--;
}
}
protected void resetFont () {
moAttrState.typefaceEnable (false);
moAttrState.sizeEnable (false);
}
// Utility functions
//----------------------------------------------------------------------
//
// OutputPointSize - Utility function for numeric output.
//
//----------------------------------------------------------------------
protected String outputPointSize (TextAttr oAttr, int eTag, TextMeasurement oValue, boolean bEnable, int lUnitsPerPoint) {
return outputPointSize (eTag, oAttr.flattenMeasurement (oValue), bEnable, lUnitsPerPoint);
}
protected String outputPointSize (TextAttr oAttr, int eTag, TextMeasurement oValue, boolean bEnable) {
return outputPointSize (eTag, oAttr.flattenMeasurement (oValue), bEnable, 20);
}
protected String outputPointSize (int eTag, UnitSpan oValue, boolean bEnable, int lUnitsPerPoint) {
StringBuilder sOut = new StringBuilder();
if (bEnable) {
UnitSpan oCvt = new UnitSpan (UnitSpan.POINTS_1K, oValue.units(), oValue.value());
sOut.append (mpMarkupAttr.lookup (eTag));
sOut.append (Float.toString (Math.round ((oCvt.value() * lUnitsPerPoint) / 1000.0f)));
sOut.append (mpMarkupAttr.delimiter());
}
return sOut.toString();
}
protected String outputPointSize (int eTag, UnitSpan oValue, boolean bEnable) {
return outputPointSize (eTag, oValue, bEnable, 20);
}
protected String outputPointSize (int eTag, UnitSpan oValue) {
return outputPointSize (eTag, oValue, true);
}
protected TextAttr previousState () {
return moAttrState;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy