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

com.adobe.xfa.text.markup.MarkupEngineOut Maven / Gradle / Ivy

There is a newer version: 2024.11.18751.20241128T090041Z-241100
Show newest version
//----------------------------------------------------------------------
//
//	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