/**
* Traits for this area stored in a HashMap
*/
- protected Map traits = null;
- protected Map<Integer, Object> props = null;
++ protected Map<Integer, Object> traits = null;
/**
* logging instance
* @param prop the value of the trait
*/
public void addTrait(Object traitCode, Object prop) {
- if (props == null) {
- props = new java.util.HashMap<Integer, Object>(20);
+ if (traits == null) {
- traits = new java.util.HashMap(20);
++ traits = new java.util.HashMap<Integer, Object>(20);
+ }
- traits.put(traitCode, prop);
++ traits.put((Integer) traitCode, prop);
+ }
+
+ /**
+ * Set traits on this area, copying from an existing traits map.
+ *
+ * @param traits the map of traits
+ */
+ public void setTraits ( Map traits ) {
+ if ( traits != null ) {
+ this.traits = new java.util.HashMap ( traits );
+ } else {
+ this.traits = null;
}
- props.put((Integer)traitCode, prop);
}
/**
*
* @return the map of traits
*/
- public Map getTraits() {
+ public Map<Integer, Object> getTraits() {
- return this.props;
+ return this.traits;
}
/** @return true if the area has traits */
/**
* Get a trait from this area.
*
- * @param oTraitCode the trait key
+ * @param traitCode the trait key
* @return the trait value
*/
- public Object getTrait(Object oTraitCode) {
- return (traits != null ? traits.get(oTraitCode) : null);
+ public Object getTrait(Integer traitCode) {
- return (props != null ? props.get(traitCode) : null);
++ return (traits != null ? traits.get(traitCode) : null);
}
/**
import java.io.Serializable;
import org.apache.fop.datatypes.FODimension;
- import org.apache.fop.fo.Constants;
+import org.apache.fop.traits.WritingMode;
+ import static org.apache.fop.fo.Constants.EN_LR_TB;
+ import static org.apache.fop.fo.Constants.EN_RL_TB;
+ import static org.apache.fop.fo.Constants.EN_TB_RL;
++import static org.apache.fop.fo.Constants.EN_TB_LR;
+
/**
* Describe a PDF or PostScript style coordinate transformation matrix (CTM).
* The matrix encodes translations, scaling and rotations of the coordinate
* CTM is being set.
* @return a new CTM with the required transform
*/
- public static CTM getWMctm(int wm, int ipd, int bpd) {
+ public static CTM getWMctm(WritingMode wm, int ipd, int bpd) {
CTM wmctm;
- switch (wm) {
+ switch (wm.getEnumValue()) {
- case Constants.EN_LR_TB:
+ case EN_LR_TB:
return new CTM(CTM_LRTB);
- case Constants.EN_RL_TB:
+ case EN_RL_TB:
wmctm = new CTM(CTM_RLTB);
wmctm.e = ipd;
return wmctm;
//return CTM_RLTB.translate(ipd, 0);
- case Constants.EN_TB_RL: // CJK
- case Constants.EN_TB_LR: // CJK
+ case EN_TB_RL: // CJK
++ case EN_TB_LR: // CJK
wmctm = new CTM(CTM_TBRL);
wmctm.e = bpd;
return wmctm;
* can set ipd and bpd appropriately based on the writing mode.
*/
- if (writingMode == EN_LR_TB || writingMode == EN_RL_TB) {
+ switch ( writingMode.getEnumValue() ) {
+ default:
- case Constants.EN_LR_TB:
- case Constants.EN_RL_TB:
++ case EN_LR_TB:
++ case EN_RL_TB:
reldims.ipd = width;
reldims.bpd = height;
- } else {
+ break;
- case Constants.EN_TB_LR:
- case Constants.EN_TB_RL:
++ case EN_TB_LR:
++ case EN_TB_RL:
reldims.ipd = height;
reldims.bpd = width;
+ break;
}
// Set a rectangle to be the writing-mode relative version???
// Now transform for writing mode
* and destroy the AdjustingInfo object if there are
* no UnresolvedAreas left
*/
- public void finalise() {
+ public void finish() {
- if (adjustingInfo.lineAlignment == Constants.EN_JUSTIFY) {
+ if (adjustingInfo.lineAlignment == EN_JUSTIFY) {
if (log.isTraceEnabled()) {
log.trace("Applying variation factor to justified line: " + adjustingInfo);
}
import org.apache.xmlgraphics.image.loader.ImageInfo;
- import org.apache.fop.fo.Constants;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.traits.BorderProps;
+import org.apache.fop.traits.Direction;
+import org.apache.fop.traits.WritingMode;
import org.apache.fop.util.ColorUtil;
+ import static org.apache.fop.fo.Constants.EN_REPEAT;
+ import static org.apache.fop.fo.Constants.EN_REPEATX;
+ import static org.apache.fop.fo.Constants.EN_REPEATY;
+ import static org.apache.fop.fo.Constants.EN_NOREPEAT;
+
// properties should be serialized by the holder
/**
* Area traits used for rendering.
/**
* Create a space area
- * @param s the space character
- * @param o the offset for the next area
- * @param a is this space adjustable?
+ * @param space the space character
+ * @param blockProgressionOffset the offset for the next area
+ * @param adjustable is this space adjustable?
+ * @param bidiLevel the bidirectional embedding level (or -1 if not defined)
*/
- public SpaceArea(char s, int o, boolean a) {
- space = s;
- offset = o;
- isAdjustable = a;
+ public SpaceArea(int blockProgressionOffset, int bidiLevel, char space, boolean adjustable) {
+ super ( blockProgressionOffset, bidiLevel );
+ this.space = space;
+ this.isAdjustable = adjustable;
}
- /**
- * @return Returns the space.
- */
+ /** @return Returns the space. */
public String getSpace() {
return String.valueOf(space);
}
}
/** {@inheritDoc} */
+ @Override
public String toString() {
- return "TextArea{text=" + getText() + "}";
+ StringBuffer sb = new StringBuffer(super.toString());
+ sb.append(" {text=\"");
+ sb.append(CharUtilities.toNCRefs(getText()));
+ sb.append("\"");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ private void updateLevel ( int newLevel ) {
+ if ( newLevel >= 0 ) {
+ int curLevel = getBidiLevel();
+ if ( curLevel >= 0 ) {
+ if ( newLevel < curLevel ) {
+ setBidiLevel ( newLevel );
+ }
+ } else {
+ setBidiLevel ( newLevel );
+ }
+ }
}
+
+ private static int findMinLevel ( int[] levels ) {
+ if ( levels != null ) {
+ int lMin = Integer.MAX_VALUE;
+ for ( int i = 0, n = levels.length; i < n; i++ ) {
+ int l = levels [ i ];
+ if ( ( l >= 0 ) && ( l < lMin ) ) {
+ lMin = l;
+ }
+ }
+ if ( lMin == Integer.MAX_VALUE ) {
+ return -1;
+ } else {
+ return lMin;
+ }
+ } else {
+ return -1;
+ }
+ }
+
}
/** An array of width for adjusting the individual letters (optional) */
protected int[] letterAdjust;
+ /**
+ * An array of resolved bidirectional levels corresponding to each character
+ * in word (optional)
+ */
+ protected int[] levels;
+
+ /**
+ * An array of glyph positioning adjustments to apply to each glyph 'char' in word (optional)
+ */
+ protected int[][] gposAdjustments;
+
+ /**
+ * A flag indicating whether the content of word is reversed in relation to
+ * its original logical order.
+ */
+ protected boolean reversed;
+
/**
* Create a word area
- * @param w the word string
- * @param o the offset for the next area
- * @param la the letter adjust array (may be null)
+ * @param blockProgressionOffset the offset for this area
+ * @param level the bidirectional embedding level (or -1 if not defined) for word as a group
+ * @param word the word string
+ * @param letterAdjust the letter adjust array (may be null)
+ * @param levels array of per-character (glyph) bidirectional levels,
+ * in case word area is heterogenously leveled
+ * @param gposAdjustments array of general position adjustments or null if none apply
*/
- public WordArea(String w, int o, int[] la) {
- word = w;
- offset = o;
- this.letterAdjust = la;
+ public WordArea
+ ( int blockProgressionOffset, int level, String word, int[] letterAdjust, int[] levels,
+ int[][] gposAdjustments ) {
+ super ( blockProgressionOffset, level );
+ int length = ( word != null ) ? word.length() : 0;
+ this.word = word;
+ this.letterAdjust = maybeAdjustLength ( letterAdjust, length );
+ this.levels = maybePopulateLevels ( levels, level, length );
+ this.gposAdjustments = maybeAdjustLength ( gposAdjustments, length );
+ this.reversed = false;
}
- /**
- * @return Returns the word.
- */
+ /** @return Returns the word. */
public String getWord() {
return word;
}
* @param lrtb the property ID to return under lrtb writingmode.
* @param rltb the property ID to return under rltb writingmode.
* @param tbrl the property ID to return under tbrl writingmode.
+ * @param tblr the property ID to return under tblr writingmode.
* @return one of the property IDs, depending on the writing mode.
*/
- public int getWritingMode(int lrtb, int rltb, int tbrl) {
- switch (writingMode) {
- case Constants.EN_LR_TB: return lrtb;
- case Constants.EN_RL_TB: return rltb;
- case Constants.EN_TB_RL: return tbrl;
+ public int selectFromWritingMode(int lrtb, int rltb, int tbrl, int tblr) {
+ int propID;
+ try {
+ switch (get(Constants.PR_WRITING_MODE).getEnum()) {
+ case Constants.EN_LR_TB:
+ propID = lrtb;
+ break;
+ case Constants.EN_RL_TB:
+ propID = rltb;
+ break;
+ case Constants.EN_TB_RL:
+ propID = tbrl;
+ break;
+ case Constants.EN_TB_LR:
+ propID = tblr;
+ break;
default:
- //nop
+ propID = -1;
+ break;
+ }
+ } catch ( PropertyException e ) {
+ propID = -1;
}
- return -1;
+ return propID;
}
- convertAttributeToProperty(attributes, attributeName, attributeValue);
+ private String addAttributeToList(Attributes attributes,
+ String attributeName) throws ValidationException {
+ String attributeValue = attributes.getValue(attributeName);
++ if ( attributeValue != null ) {
++ convertAttributeToProperty(attributes, attributeName, attributeValue);
++ }
+ return attributeValue;
+ }
+
/**
- * Adds the attributes, passed in by the parser to the PropertyList
+ * <p>Adds the attributes, passed in by the parser to the PropertyList.</p>
+ * <p>Note that certain attributes are given priority in terms of order of
+ * processing due to conversion dependencies, where the order is as follows:</p>
+ * <ol>
+ * <li>writing-mode</li>
+ * <li>column-number</li>
+ * <li>number-columns-spanned</li>
+ * <li>font</li>
+ * <li>font-size</li>
+ * <li><emph>all others in order of appearance</emph></li>
+ * </ol>
*
* @param attributes Collection of attributes passed to us from the parser.
* @throws ValidationException if there is an attribute that does not
*/
public void addAttributesToList(Attributes attributes)
throws ValidationException {
- String attributeName = "writing-mode";
- String attributeValue = attributes.getValue(attributeName);
- if ( attributeValue != null ) {
- convertAttributeToProperty(attributes, attributeName, attributeValue);
- }
+ /*
+ * Give writing-mode highest conversion priority.
+ */
++ addAttributeToList(attributes, "writing-mode");
+
/*
* If column-number/number-columns-spanned are specified, then we
* need them before all others (possible from-table-column() on any