aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas L. Delmelle <adelmelle@apache.org>2007-09-21 22:51:22 +0000
committerAndreas L. Delmelle <adelmelle@apache.org>2007-09-21 22:51:22 +0000
commit6045d497f24d10551dba6c4c153e057c08204253 (patch)
treec20d4cccd101bee3f76a71d0107f9bf1ea87693c
parent901f7ecc09479f0e40c44453ce5d905aca355556 (diff)
downloadxmlgraphics-fop-6045d497f24d10551dba6c4c153e057c08204253.tar.gz
xmlgraphics-fop-6045d497f24d10551dba6c4c153e057c08204253.zip
PropertyCache phase 2:
* improvement of the PropertyCache itself should guarantee acceptable performance of the static caches in multi-session environments, which is a possible problem with synchronizedMap * changed CommonFont to use the cache: added CachedCommonFont to contain the properties that are always cacheable CommonFont itself is only cached if the remaining properties are absolutes * changed CommonHyphenation, KeepProperty, ColorProperty and FontFamilyProperty to use the cache Facilitate the implementation for font-selection-strategy: * Changed FontInfo.fontLookup to always return an array of FontTriplet * Changed CommonFont.getFontState to return an array of FontTriplet * Initial modifications to the related LMs: initialized with the font corresponding to the first of the triplets This line, and those below, will be ignored-- M src/java/org/apache/fop/render/rtf/TextAttributesConverter.java M src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java M src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java M src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java M src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java M src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java M src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java M src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java M src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java M src/java/org/apache/fop/fonts/FontInfo.java M src/java/org/apache/fop/fo/properties/CommonHyphenation.java M src/java/org/apache/fop/fo/properties/CommonAccessibility.java M src/java/org/apache/fop/fo/properties/CompoundPropertyMaker.java M src/java/org/apache/fop/fo/properties/FontFamilyProperty.java M src/java/org/apache/fop/fo/properties/FixedLength.java M src/java/org/apache/fop/fo/properties/PropertyCache.java M src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java M src/java/org/apache/fop/fo/properties/CommonFont.java M src/java/org/apache/fop/fo/properties/ColorProperty.java M src/java/org/apache/fop/fo/properties/KeepProperty.java M src/java/org/apache/fop/fo/PropertyList.java M src/java/org/apache/fop/fo/FOPropertyMapping.java M src/java/org/apache/fop/fo/expr/PropertyParser.java M src/java/org/apache/fop/fo/expr/ICCColorFunction.java M src/java/org/apache/fop/fo/expr/CMYKcolorFunction.java M src/java/org/apache/fop/fo/expr/RGBColorFunction.java M src/java/org/apache/fop/fo/expr/SystemColorFunction.java M status.xml git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@578311 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--src/java/org/apache/fop/fo/FOPropertyMapping.java2
-rw-r--r--src/java/org/apache/fop/fo/PropertyList.java6
-rw-r--r--src/java/org/apache/fop/fo/expr/CMYKcolorFunction.java2
-rw-r--r--src/java/org/apache/fop/fo/expr/ICCColorFunction.java2
-rw-r--r--src/java/org/apache/fop/fo/expr/PropertyParser.java2
-rw-r--r--src/java/org/apache/fop/fo/expr/RGBColorFunction.java2
-rw-r--r--src/java/org/apache/fop/fo/expr/SystemColorFunction.java2
-rw-r--r--src/java/org/apache/fop/fo/properties/ColorProperty.java46
-rw-r--r--src/java/org/apache/fop/fo/properties/CommonAccessibility.java2
-rwxr-xr-xsrc/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java11
-rwxr-xr-xsrc/java/org/apache/fop/fo/properties/CommonFont.java371
-rw-r--r--src/java/org/apache/fop/fo/properties/CommonHyphenation.java150
-rw-r--r--src/java/org/apache/fop/fo/properties/CompoundPropertyMaker.java6
-rw-r--r--src/java/org/apache/fop/fo/properties/FixedLength.java12
-rw-r--r--src/java/org/apache/fop/fo/properties/FontFamilyProperty.java52
-rw-r--r--src/java/org/apache/fop/fo/properties/KeepProperty.java44
-rw-r--r--src/java/org/apache/fop/fo/properties/PropertyCache.java360
-rw-r--r--src/java/org/apache/fop/fonts/FontInfo.java37
-rw-r--r--src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java12
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java8
-rwxr-xr-xsrc/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java8
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java6
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java30
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java6
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java6
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java10
-rw-r--r--src/java/org/apache/fop/render/rtf/TextAttributesConverter.java8
-rw-r--r--status.xml17
28 files changed, 975 insertions, 245 deletions
diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java
index 50cf8c4a9..0d53a44b3 100644
--- a/src/java/org/apache/fop/fo/FOPropertyMapping.java
+++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java
@@ -568,7 +568,7 @@ public final class FOPropertyMapping implements Constants {
if (nameval != null) {
FObj fobj = (fo == null ? propertyList.getFObj() : fo);
FOUserAgent ua = (fobj == null ? null : fobj.getUserAgent());
- return new ColorProperty(ua, nameval);
+ return ColorProperty.getInstance(ua, nameval);
}
return super.convertPropertyDatatype(p, propertyList, fo);
}
diff --git a/src/java/org/apache/fop/fo/PropertyList.java b/src/java/org/apache/fop/fo/PropertyList.java
index 8a59b5751..6d4dbd43c 100644
--- a/src/java/org/apache/fop/fo/PropertyList.java
+++ b/src/java/org/apache/fop/fo/PropertyList.java
@@ -577,7 +577,7 @@ public abstract class PropertyList {
*/
public CommonBorderPaddingBackground getBorderPaddingBackgroundProps()
throws PropertyException {
- return new CommonBorderPaddingBackground(this, fobj);
+ return new CommonBorderPaddingBackground(this);
}
/**
@@ -586,7 +586,7 @@ public abstract class PropertyList {
* @throws PropertyException if there's a problem while processing the properties
*/
public CommonHyphenation getHyphenationProps() throws PropertyException {
- return new CommonHyphenation(this);
+ return CommonHyphenation.getInstance(this);
}
/**
@@ -652,7 +652,7 @@ public abstract class PropertyList {
* @throws PropertyException if there's a problem while processing the properties
*/
public CommonFont getFontProps() throws PropertyException {
- return CommonFont(this);
+ return CommonFont.getInstance(this);
}
/**
diff --git a/src/java/org/apache/fop/fo/expr/CMYKcolorFunction.java b/src/java/org/apache/fop/fo/expr/CMYKcolorFunction.java
index ff3ca25eb..3aab1325d 100644
--- a/src/java/org/apache/fop/fo/expr/CMYKcolorFunction.java
+++ b/src/java/org/apache/fop/fo/expr/CMYKcolorFunction.java
@@ -43,7 +43,7 @@ class CMYKcolorFunction extends FunctionBase {
FOUserAgent ua = (pInfo == null)
? null
: (pInfo.getFO() == null ? null : pInfo.getFO().getUserAgent());
- return new ColorProperty(ua, sb.toString());
+ return ColorProperty.getInstance(ua, sb.toString());
}
diff --git a/src/java/org/apache/fop/fo/expr/ICCColorFunction.java b/src/java/org/apache/fop/fo/expr/ICCColorFunction.java
index 389bf42e9..ca66aac27 100644
--- a/src/java/org/apache/fop/fo/expr/ICCColorFunction.java
+++ b/src/java/org/apache/fop/fo/expr/ICCColorFunction.java
@@ -70,7 +70,7 @@ class ICCColorFunction extends FunctionBase {
FOUserAgent ua = (pInfo == null
? null
: (pInfo.getFO() == null ? null : pInfo.getFO().getUserAgent()));
- return new ColorProperty(ua, sb.toString());
+ return ColorProperty.getInstance(ua, sb.toString());
}
diff --git a/src/java/org/apache/fop/fo/expr/PropertyParser.java b/src/java/org/apache/fop/fo/expr/PropertyParser.java
index 3bb15cc4c..6dcbb0b0a 100644
--- a/src/java/org/apache/fop/fo/expr/PropertyParser.java
+++ b/src/java/org/apache/fop/fo/expr/PropertyParser.java
@@ -302,7 +302,7 @@ public final class PropertyParser extends PropertyTokenizer {
FOUserAgent ua = (propInfo == null)
? null
: (propInfo.getFO() == null ? null : propInfo.getFO().getUserAgent());
- prop = new ColorProperty(ua, currentTokenValue);
+ prop = ColorProperty.getInstance(ua, currentTokenValue);
break;
case TOK_FUNCTION_LPAR:
diff --git a/src/java/org/apache/fop/fo/expr/RGBColorFunction.java b/src/java/org/apache/fop/fo/expr/RGBColorFunction.java
index 6c6162731..9b3287154 100644
--- a/src/java/org/apache/fop/fo/expr/RGBColorFunction.java
+++ b/src/java/org/apache/fop/fo/expr/RGBColorFunction.java
@@ -50,7 +50,7 @@ class RGBColorFunction extends FunctionBase {
FOUserAgent ua = (pInfo == null)
? null
: (pInfo.getFO() == null ? null : pInfo.getFO().getUserAgent());
- return new ColorProperty(ua, "rgb(" + args[0] + "," + args[1] + "," + args[2] + ")");
+ return ColorProperty.getInstance(ua, "rgb(" + args[0] + "," + args[1] + "," + args[2] + ")");
}
diff --git a/src/java/org/apache/fop/fo/expr/SystemColorFunction.java b/src/java/org/apache/fop/fo/expr/SystemColorFunction.java
index 5398b7051..b32c38e54 100644
--- a/src/java/org/apache/fop/fo/expr/SystemColorFunction.java
+++ b/src/java/org/apache/fop/fo/expr/SystemColorFunction.java
@@ -39,7 +39,7 @@ class SystemColorFunction extends FunctionBase {
FOUserAgent ua = (pInfo == null)
? null
: (pInfo.getFO() == null ? null : pInfo.getFO().getUserAgent());
- return new ColorProperty(ua, "system-color(" + args[0] + ")");
+ return ColorProperty.getInstance(ua, "system-color(" + args[0] + ")");
}
diff --git a/src/java/org/apache/fop/fo/properties/ColorProperty.java b/src/java/org/apache/fop/fo/properties/ColorProperty.java
index 5eb399d3d..853a965bb 100644
--- a/src/java/org/apache/fop/fo/properties/ColorProperty.java
+++ b/src/java/org/apache/fop/fo/properties/ColorProperty.java
@@ -28,9 +28,12 @@ import org.apache.fop.fo.expr.PropertyException;
import org.apache.fop.util.ColorUtil;
/**
- * Superclass for properties that wrap Color values
+ * Class for properties that wrap Color values
*/
-public class ColorProperty extends Property {
+public final class ColorProperty extends Property {
+
+ /** cache holding canonical ColorProperty instances */
+ private static final PropertyCache cache = new PropertyCache();
/**
* The color represented by this property.
@@ -92,16 +95,28 @@ public class ColorProperty extends Property {
* @throws PropertyException if the value can't be parsed
* @see ColorUtil#parseColorString(FOUserAgent, String)
*/
- public ColorProperty(FOUserAgent foUserAgent, String value) throws PropertyException {
- this.color = ColorUtil.parseColorString(foUserAgent, value);
+ public static ColorProperty getInstance(FOUserAgent foUserAgent, String value) throws PropertyException {
+ ColorProperty instance = new ColorProperty(
+ ColorUtil.parseColorString(
+ foUserAgent, value));
+ return (ColorProperty) cache.fetch(instance);
}
/**
+ *
+ * @param value
+ * @return
+ */
+ public static ColorProperty getInstance(Color value) {
+ return (ColorProperty) cache.fetch(new ColorProperty(value));
+ }
+
+ /**
* Create a new ColorProperty with a given color.
*
* @param value the color to use.
*/
- public ColorProperty(Color value) {
+ private ColorProperty(Color value) {
this.color = value;
}
@@ -114,9 +129,7 @@ public class ColorProperty extends Property {
return color;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public String toString() {
return ColorUtil.colorToString(color);
}
@@ -135,5 +148,22 @@ public class ColorProperty extends Property {
public Object getObject() {
return this;
}
+
+ /** {@inheritDoc} */
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (o instanceof ColorProperty) {
+ return ((ColorProperty) o).color.equals(this.color);
+ }
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ public int hashCode() {
+ return this.color.hashCode();
+ }
}
diff --git a/src/java/org/apache/fop/fo/properties/CommonAccessibility.java b/src/java/org/apache/fop/fo/properties/CommonAccessibility.java
index 15ffbffc1..e97ba5a0a 100644
--- a/src/java/org/apache/fop/fo/properties/CommonAccessibility.java
+++ b/src/java/org/apache/fop/fo/properties/CommonAccessibility.java
@@ -40,7 +40,7 @@ public class CommonAccessibility {
public String role = null;
/**
- * Create a CommonAbsolutePosition object.
+ * Create a <code>CommonAccessibility</code> object.
* @param pList The PropertyList with propery values.
*/
public CommonAccessibility(PropertyList pList) throws PropertyException {
diff --git a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java
index 712ae9703..e41685019 100755
--- a/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java
+++ b/src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java
@@ -137,15 +137,16 @@ public class CommonBorderPaddingBackground {
/**
* Construct a CommonBorderPaddingBackground object.
+ *
* @param pList The PropertyList to get properties from.
* @param fobj The FO to create this instance for.
* @throws PropertyException if there's an error while binding the properties
*/
- public CommonBorderPaddingBackground(PropertyList pList, FObj fobj) throws PropertyException {
+ public CommonBorderPaddingBackground(PropertyList pList) throws PropertyException {
backgroundAttachment = pList.get(Constants.PR_BACKGROUND_ATTACHMENT).getEnum();
backgroundColor = pList.get(Constants.PR_BACKGROUND_COLOR).getColor(
- fobj == null ? null : fobj.getUserAgent());
+ pList.getFObj().getUserAgent());
if (backgroundColor.getAlpha() == 0) {
backgroundColor = null;
}
@@ -162,7 +163,7 @@ public class CommonBorderPaddingBackground {
//Additional processing: preload image
String url = ImageFactory.getURL(backgroundImage);
- FOUserAgent userAgent = fobj.getUserAgent();
+ FOUserAgent userAgent = pList.getFObj().getUserAgent();
ImageFactory fact = userAgent.getFactory().getImageFactory();
fopimage = fact.getImage(url, userAgent);
if (fopimage == null) {
@@ -207,9 +208,7 @@ public class CommonBorderPaddingBackground {
// If style = none, force width to 0, don't get Color (spec 7.7.20)
int style = pList.get(styleProp).getEnum();
if (style != Constants.EN_NONE) {
- FOUserAgent ua = (pList == null)
- ? null
- : (pList.getFObj() == null ? null : pList.getFObj().getUserAgent());
+ FOUserAgent ua = pList.getFObj().getUserAgent();
setBorderInfo(new BorderInfo(style,
pList.get(widthProp).getCondLength(),
pList.get(colorProp).getColor(ua)), side);
diff --git a/src/java/org/apache/fop/fo/properties/CommonFont.java b/src/java/org/apache/fop/fo/properties/CommonFont.java
index d0d38223f..a2d01ffa3 100755
--- a/src/java/org/apache/fop/fo/properties/CommonFont.java
+++ b/src/java/org/apache/fop/fo/properties/CommonFont.java
@@ -24,140 +24,329 @@ import java.util.List;
import org.apache.fop.datatypes.Length;
import org.apache.fop.datatypes.Numeric;
-import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.expr.PropertyException;
-import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
/**
- * Collection of properties used in
+ * Collection of CommonFont properties
*/
-public class CommonFont {
+public final class CommonFont {
+ /** cache holding canonical CommonFont instances (only those with
+ * absolute font-size and font-size-adjust) */
+ private static final PropertyCache cache = new PropertyCache();
+
/**
- * The "font-family" property.
+ * Class holding canonical instances of bundles of the
+ * cacheable (non-relative) CommonFont properties
+ *
*/
- private String[] fontFamily;
+ protected static final class CachedCommonFont {
+
+ /** cache holding all canonical instances */
+ private static final PropertyCache cache = new PropertyCache();
+
+ private int hash = 0;
+
+ /**
+ * The "font-family" property.
+ */
+ private final FontFamilyProperty fontFamily;
+
+ /**
+ * The "font-selection-strategy" property.
+ */
+ private final EnumProperty fontSelectionStrategy;
+
+ /**
+ * The "font-stretch" property.
+ */
+ private final EnumProperty fontStretch;
- /**
- * The "font-selection-strategy" property.
- */
- public int fontSelectionStrategy;
+ /**
+ * The "font-style" property.
+ */
+ private final EnumProperty fontStyle;
- /**
- * The "font-size" property.
- */
- public Length fontSize;
+ /**
+ * The "font-variant" property.
+ */
+ private final EnumProperty fontVariant;
- /**
- * The "font-stretch" property.
- */
- public int fontStretch;
+ /**
+ * The "font-weight" property.
+ */
+ private final EnumProperty fontWeight;
+
+ /**
+ * Constructor
+ *
+ * @param fontFamily the font-family property
+ * @param fontSelectionStrategy the font-selection-strategy property
+ * @param fontStretch the font-stretch property
+ * @param fontStyle the font-style property
+ * @param fontVariant the font-variant property
+ * @param fontWeight the font-weight property
+ */
+ private CachedCommonFont(FontFamilyProperty fontFamily,
+ EnumProperty fontSelectionStrategy,
+ EnumProperty fontStretch,
+ EnumProperty fontStyle,
+ EnumProperty fontVariant,
+ EnumProperty fontWeight) {
+ this.fontFamily = fontFamily;
+ this.fontSelectionStrategy = fontSelectionStrategy;
+ this.fontStretch = fontStretch;
+ this.fontStyle = fontStyle;
+ this.fontVariant = fontVariant;
+ this.fontWeight = fontWeight;
+ }
+
+ /**
+ * Returns the canonical instance corresponding to the given
+ * properties
+ *
+ * @param fontFamily the font-family property
+ * @param fontSelectionStrategy the font-selection-strategy property
+ * @param fontStretch the font-stretch property
+ * @param fontStyle the font-style property
+ * @param fontVariant the font-variant property
+ * @param fontWeight the font-weight property
+ * @return the canonical instance
+ */
+ private static final CachedCommonFont getInstance(FontFamilyProperty fontFamily,
+ EnumProperty fontSelectionStrategy,
+ EnumProperty fontStretch,
+ EnumProperty fontStyle,
+ EnumProperty fontVariant,
+ EnumProperty fontWeight) {
+ return cache.fetch(new CachedCommonFont(
+ fontFamily,
+ fontSelectionStrategy,
+ fontStretch,
+ fontStyle,
+ fontVariant,
+ fontWeight));
+ }
+
+ /** @return the first font-family name in the list */
+ private String getFirstFontFamily() {
+ return ((Property) fontFamily.list.get(0)).getString();
+ }
+
+ /** @return an array with the font-family names */
+ private String[] getFontFamily() {
+ List lst = fontFamily.getList();
+ String[] fontFamily = new String[lst.size()];
+ for (int i = 0, c = lst.size(); i < c; i++) {
+ fontFamily[i] = ((Property)lst.get(i)).getString();
+ }
+ return fontFamily;
+ }
+
+ /** {@inheritDoc} */
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (o instanceof CachedCommonFont) {
+ CachedCommonFont ccf = (CachedCommonFont) o;
+ return (ccf.fontFamily == this.fontFamily)
+ && (ccf.fontSelectionStrategy == this.fontSelectionStrategy)
+ && (ccf.fontStretch == this.fontStretch)
+ && (ccf.fontStyle == this.fontStyle)
+ && (ccf.fontVariant == this.fontVariant)
+ && (ccf.fontWeight == this.fontWeight);
+ }
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ public int hashCode() {
+ if (this.hash == 0) {
+ int hash = 17;
+ hash = 37 * hash + (fontFamily == null ? 0 : fontFamily.hashCode());
+ hash = 37 * hash + (fontSelectionStrategy == null ? 0 : fontSelectionStrategy.hashCode());
+ hash = 37 * hash + (fontStretch == null ? 0 : fontStretch.hashCode());
+ hash = 37 * hash + (fontStyle == null ? 0 : fontStyle.hashCode());
+ hash = 37 * hash + (fontVariant == null ? 0 : fontVariant.hashCode());
+ hash = 37 * hash + (fontStretch == null ? 0 : fontStretch.hashCode());
+ this.hash = hash;
+ }
+ return this.hash;
+ }
+
+ }
/**
- * The "font-size-adjust" property.
+ * The cached CommonFont properties (access these through the getters)
+ * The remaining properties, font-size and font-size-adjust,
+ * will only be cached values if they are absolute.
*/
- public Numeric fontSizeAdjust;
-
+ private final CachedCommonFont cachedCommonFont;
+
/**
- * The "font-style" property.
+ * The "font-size" property.
*/
- public int fontStyle;
+ public final Length fontSize;
/**
- * The "font-variant" property.
+ * The "font-size-adjust" property.
*/
- public int fontVariant;
+ public final Numeric fontSizeAdjust;
/**
- * The "font-weight" property.
+ * Construct a CommonFont instance
+ *
+ * @param ccf the cached CommonFont properties
+ * @param fontSize the font-size (possibly non-cached)
+ * @param fontSizeAdjust the font-size-adjust (possibly non-cached)
*/
- public int fontWeight;
-
- private Font fontState;
+ private CommonFont(CachedCommonFont ccf,
+ Length fontSize,
+ Numeric fontSizeAdjust) {
+ this.cachedCommonFont = ccf;
+ this.fontSize = fontSize;
+ this.fontSizeAdjust = fontSizeAdjust;
+ }
/**
- * Create a CommonFont object.
- * @param pList The PropertyList to get properties from.
+ * Returns a CommonFont instance for the given PropertyList
+ * If the font-size and font-size-adjust properties are absolute
+ * the entire instance will be cached.
+ * If not, then a distinct instance will be returned, with
+ * as much cached information as possible.
+ *
+ * @param pList the PropertyList to get the properties from
+ * @return a CommonFont instance corresponding to the properties
+ * @throws PropertyException if there was a problem getting the properties
*/
- public CommonFont(PropertyList pList) throws PropertyException {
- List lst = pList.get(Constants.PR_FONT_FAMILY).getList();
- fontFamily = new String[lst.size()];
- for (int i = 0, c = lst.size(); i < c; i++) {
- fontFamily[i] = ((Property)lst.get(i)).getString();
- }
- if (fontFamily.length == 0) {
- //Shouldn't happen, but we never know.
- fontFamily = new String[] {"any"};
+ public static CommonFont getInstance(PropertyList pList) throws PropertyException {
+ FontFamilyProperty fontFamily = (FontFamilyProperty) pList.get(Constants.PR_FONT_FAMILY);
+ EnumProperty fontSelectionStrategy = (EnumProperty) pList.get(Constants.PR_FONT_SELECTION_STRATEGY);
+ EnumProperty fontStretch = (EnumProperty) pList.get(Constants.PR_FONT_STRETCH);
+ EnumProperty fontStyle = (EnumProperty) pList.get(Constants.PR_FONT_STYLE);
+ EnumProperty fontVariant = (EnumProperty) pList.get(Constants.PR_FONT_VARIANT);
+ EnumProperty fontWeight = (EnumProperty) pList.get(Constants.PR_FONT_WEIGHT);
+ CachedCommonFont cachedCommonFont = CachedCommonFont.getInstance(
+ fontFamily,
+ fontSelectionStrategy,
+ fontStretch,
+ fontStyle,
+ fontVariant,
+ fontWeight);
+
+ Numeric fontSizeAdjust = pList.get(Constants.PR_FONT_SIZE_ADJUST).getNumeric();
+ Length fontSize = pList.get(Constants.PR_FONT_SIZE).getLength();
+ CommonFont cf = new CommonFont(cachedCommonFont, fontSize, fontSizeAdjust);
+ if (fontSize.isAbsolute() && fontSizeAdjust.isAbsolute()) {
+ return cache.fetch(cf);
+ } else {
+ return cf;
}
- fontSelectionStrategy = pList.get(Constants.PR_FONT_SELECTION_STRATEGY).getEnum();
- fontSize = pList.get(Constants.PR_FONT_SIZE).getLength();
- fontStretch = pList.get(Constants.PR_FONT_STRETCH).getEnum();
- fontSizeAdjust = pList.get(Constants.PR_FONT_SIZE_ADJUST).getNumeric();
- fontStyle = pList.get(Constants.PR_FONT_STYLE).getEnum();
- fontVariant = pList.get(Constants.PR_FONT_VARIANT).getEnum();
- fontWeight = pList.get(Constants.PR_FONT_WEIGHT).getEnum();
+
}
-
+
/** @return the first font-family name in the list */
public String getFirstFontFamily() {
- return this.fontFamily[0];
+ return cachedCommonFont.getFirstFontFamily();
+ }
+
+ /** @return the "font-selection-strategy" property */
+ public int getFontSelectionStrategy() {
+ return cachedCommonFont.fontSelectionStrategy.getEnum();
+ }
+
+ /** @return the "font-stretch" property */
+ public int getFontStretch() {
+ return cachedCommonFont.fontStretch.getEnum();
}
- /** @return the font-family names */
- public String[] getFontFamily() {
- return this.fontFamily;
+ /** @return the "font-style" property */
+ public int getFontStyle() {
+ return cachedCommonFont.fontStyle.getEnum();
+ }
+
+ /** @return the "font-variant" property */
+ public int getFontVariant() {
+ return cachedCommonFont.fontVariant.getEnum();
+ }
+
+ /** @return the "font-weight" property */
+ public int getFontWeight() {
+ return cachedCommonFont.fontWeight.getEnum();
}
/**
- * Create and return a Font object based on the properties.
+ * Create and return an array of <code>FontTriplets</code> based on
+ * the properties stored in the instance variables.
*
* @param fontInfo
* @return a Font object.
*/
- public Font getFontState(FontInfo fontInfo, PercentBaseContext context) {
- if (fontState == null) {
- /**@todo this is ugly. need to improve. */
-
- int font_weight;
- switch (fontWeight) {
- case Constants.EN_100: font_weight = 100; break;
- case Constants.EN_200: font_weight = 200; break;
- case Constants.EN_300: font_weight = 300; break;
- case Constants.EN_400: font_weight = 400; break;
- case Constants.EN_500: font_weight = 500; break;
- case Constants.EN_600: font_weight = 600; break;
- case Constants.EN_700: font_weight = 700; break;
- case Constants.EN_800: font_weight = 800; break;
- case Constants.EN_900: font_weight = 900; break;
- default: font_weight = 400;
- }
+ public FontTriplet[] getFontState(FontInfo fontInfo) {
+ int font_weight;
+ switch (cachedCommonFont.fontWeight.getEnum()) {
+ case Constants.EN_100: font_weight = 100; break;
+ case Constants.EN_200: font_weight = 200; break;
+ case Constants.EN_300: font_weight = 300; break;
+ case Constants.EN_400: font_weight = 400; break;
+ case Constants.EN_500: font_weight = 500; break;
+ case Constants.EN_600: font_weight = 600; break;
+ case Constants.EN_700: font_weight = 700; break;
+ case Constants.EN_800: font_weight = 800; break;
+ case Constants.EN_900: font_weight = 900; break;
+ default: font_weight = 400;
+ }
- String style;
- switch (fontStyle) {
- case Constants.EN_ITALIC:
- style = "italic";
- break;
- case Constants.EN_OBLIQUE:
- style = "oblique";
- break;
- case Constants.EN_BACKSLANT:
- style = "backslant";
- break;
- default:
- style = "normal";
- }
- // NOTE: this is incomplete. font-size may be specified with
- // various kinds of keywords too
- //int fontVariant = propertyList.get("font-variant").getEnum();
- FontTriplet triplet = fontInfo.fontLookup(getFontFamily(), style,
- font_weight);
- fontState = fontInfo.getFontInstance(triplet, fontSize.getValue(context));
+ String style;
+ switch (cachedCommonFont.fontStyle.getEnum()) {
+ case Constants.EN_ITALIC:
+ style = "italic";
+ break;
+ case Constants.EN_OBLIQUE:
+ style = "oblique";
+ break;
+ case Constants.EN_BACKSLANT:
+ style = "backslant";
+ break;
+ default:
+ style = "normal";
}
- return fontState;
+ // NOTE: this is incomplete. font-size may be specified with
+ // various kinds of keywords too
+ //int fontVariant = propertyList.get("font-variant").getEnum();
+ FontTriplet[] triplets = fontInfo.fontLookup(
+ cachedCommonFont.getFontFamily(),
+ style, font_weight);
+ return triplets;
}
+ /** {@inheritDoc} */
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (o instanceof CommonFont) {
+ CommonFont cf = (CommonFont) o;
+ return (cf.cachedCommonFont == this.cachedCommonFont
+ && cf.fontSize == this.fontSize
+ && cf.fontSizeAdjust == this.fontSizeAdjust);
+ }
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ public int hashCode() {
+ int hash = 17;
+ hash = 37 * hash + cachedCommonFont.hashCode();
+ hash = 37 * hash + fontSize.hashCode();
+ hash = 37 * hash + fontSizeAdjust.hashCode();
+ return hash;
+ }
}
diff --git a/src/java/org/apache/fop/fo/properties/CommonHyphenation.java b/src/java/org/apache/fop/fo/properties/CommonHyphenation.java
index e10fdad8e..d08d18312 100644
--- a/src/java/org/apache/fop/fo/properties/CommonHyphenation.java
+++ b/src/java/org/apache/fop/fo/properties/CommonHyphenation.java
@@ -28,57 +28,123 @@ import org.apache.fop.fo.expr.PropertyException;
* See Sec. 7.9 of the XSL-FO Standard.
* Public "structure" allows direct member access.
*/
-public class CommonHyphenation {
- /**
- * The "language" property.
- */
- public String language;
+public final class CommonHyphenation {
+
+ private static final PropertyCache cache = new PropertyCache();
+
+ private int hash = 0;
+
+ /** The "language" property */
+ public final StringProperty language;
- /**
- * The "country" property.
- */
- public String country;
+ /** The "country" property */
+ public final StringProperty country;
- /**
- * The "script" property.
- */
- public String script;
+ /** The "script" property */
+ public final StringProperty script;
- /**
- * The "hyphenate" property.
- */
- public int hyphenate;
+ /** The "hyphenate" property */
+ public final EnumProperty hyphenate;
- /**
- * The "hyphenation-character" property.
- */
- public char hyphenationCharacter;
+ /** The "hyphenation-character" property */
+ public final CharacterProperty hyphenationCharacter;
- /**
- * The "hyphenation-push-character" property.
- */
- public int hyphenationPushCharacterCount;
+ /** The "hyphenation-push-character-count" property */
+ public final NumberProperty hyphenationPushCharacterCount;
+
+ /** The "hyphenation-remain-character-count" property*/
+ public final NumberProperty hyphenationRemainCharacterCount;
/**
- * The "hyphenation-remain-character-count" property.
+ * Construct a CommonHyphenation object holding the given properties
+ *
*/
- public int hyphenationRemainCharacterCount;
-
+ private CommonHyphenation(StringProperty language,
+ StringProperty country,
+ StringProperty script,
+ EnumProperty hyphenate,
+ CharacterProperty hyphenationCharacter,
+ NumberProperty hyphenationPushCharacterCount,
+ NumberProperty hyphenationRemainCharacterCount) {
+ this.language = language;
+ this.country = country;
+ this.script = script;
+ this.hyphenate = hyphenate;
+ this.hyphenationCharacter = hyphenationCharacter;
+ this.hyphenationPushCharacterCount = hyphenationPushCharacterCount;
+ this.hyphenationRemainCharacterCount = hyphenationRemainCharacterCount;
+ }
+
/**
- * Create a CommonHyphenation object.
- * @param pList The PropertyList with propery values.
+ * Gets the canonical <code>CommonHyphenation</code> instance corresponding
+ * to the values of the related properties present on the given
+ * <code>PropertyList</code>
+ *
+ * @param propertyList the <code>PropertyList</code>
*/
- public CommonHyphenation(PropertyList pList) throws PropertyException {
- language = pList.get(Constants.PR_LANGUAGE).getString();
- country = pList.get(Constants.PR_COUNTRY).getString();
- script = pList.get(Constants.PR_SCRIPT).getString();
- hyphenate = pList.get(Constants.PR_HYPHENATE).getEnum();
- hyphenationCharacter = pList.get(Constants.PR_HYPHENATION_CHARACTER).getCharacter();
- hyphenationPushCharacterCount =
- pList.get(Constants.PR_HYPHENATION_PUSH_CHARACTER_COUNT).getNumber().intValue();
- hyphenationRemainCharacterCount =
- pList.get(Constants.PR_HYPHENATION_REMAIN_CHARACTER_COUNT).getNumber().intValue();
-
+ public static CommonHyphenation getInstance(PropertyList propertyList) throws PropertyException {
+ StringProperty language =
+ (StringProperty) propertyList.get(Constants.PR_LANGUAGE);
+ StringProperty country =
+ (StringProperty) propertyList.get(Constants.PR_COUNTRY);
+ StringProperty script =
+ (StringProperty) propertyList.get(Constants.PR_SCRIPT);
+ EnumProperty hyphenate =
+ (EnumProperty) propertyList.get(Constants.PR_HYPHENATE);
+ CharacterProperty hyphenationCharacter =
+ (CharacterProperty) propertyList.get(Constants.PR_HYPHENATION_CHARACTER);
+ NumberProperty hyphenationPushCharacterCount =
+ (NumberProperty) propertyList.get(Constants.PR_HYPHENATION_PUSH_CHARACTER_COUNT);
+ NumberProperty hyphenationRemainCharacterCount =
+ (NumberProperty) propertyList.get(Constants.PR_HYPHENATION_REMAIN_CHARACTER_COUNT);
+
+ CommonHyphenation instance = new CommonHyphenation(
+ language,
+ country,
+ script,
+ hyphenate,
+ hyphenationCharacter,
+ hyphenationPushCharacterCount,
+ hyphenationRemainCharacterCount);
+
+ return cache.fetch(instance);
+
}
-
+
+ /** {@inheritDoc */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof CommonHyphenation) {
+ CommonHyphenation ch = (CommonHyphenation) obj;
+ return (ch.language == this.language
+ && ch.country == this.country
+ && ch.script == this.script
+ && ch.hyphenate == this.hyphenate
+ && ch.hyphenationCharacter == this.hyphenationCharacter
+ && ch.hyphenationPushCharacterCount == this.hyphenationPushCharacterCount
+ && ch.hyphenationRemainCharacterCount == this.hyphenationRemainCharacterCount);
+ }
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ public int hashCode() {
+ if (hash == 0) {
+ int hash = 17;
+ hash = 37 * hash + (language == null ? 0 : language.hashCode());
+ hash = 37 * hash + (script == null ? 0 : script.hashCode());
+ hash = 37 * hash + (country == null ? 0 : country.hashCode());
+ hash = 37 * hash + (hyphenate == null ? 0 : hyphenate.hashCode());
+ hash = 37 * hash +
+ (hyphenationCharacter == null ? 0 : hyphenationCharacter.hashCode());
+ hash = 37 * hash +
+ (hyphenationPushCharacterCount == null ? 0 : hyphenationPushCharacterCount.hashCode());
+ hash = 37 * hash +
+ (hyphenationRemainCharacterCount == null ? 0 : hyphenationRemainCharacterCount.hashCode());
+ }
+ return hash;
+ }
+
}
diff --git a/src/java/org/apache/fop/fo/properties/CompoundPropertyMaker.java b/src/java/org/apache/fop/fo/properties/CompoundPropertyMaker.java
index 9852d5fdf..f15050fbe 100644
--- a/src/java/org/apache/fop/fo/properties/CompoundPropertyMaker.java
+++ b/src/java/org/apache/fop/fo/properties/CompoundPropertyMaker.java
@@ -26,12 +26,6 @@ import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.expr.PropertyException;
/**
- * @author me
- *
- * To change the template for this generated type comment go to
- * Window - Preferences - Java - Code Generation - Code and Comments
- */
-/**
* This class extends Property.Maker with support for sub-properties.
*/
public class CompoundPropertyMaker extends PropertyMaker {
diff --git a/src/java/org/apache/fop/fo/properties/FixedLength.java b/src/java/org/apache/fop/fo/properties/FixedLength.java
index e9b0a3f8c..2c497094f 100644
--- a/src/java/org/apache/fop/fo/properties/FixedLength.java
+++ b/src/java/org/apache/fop/fo/properties/FixedLength.java
@@ -24,7 +24,7 @@ import org.apache.fop.datatypes.PercentBaseContext;
/**
* An absolute length quantity in XSL
*/
-public class FixedLength extends LengthProperty {
+public final class FixedLength extends LengthProperty {
/** cache holding all canonical FixedLength instances */
private static final PropertyCache cache = new PropertyCache();
@@ -33,6 +33,7 @@ public class FixedLength extends LengthProperty {
/**
* Set the length given a number of units and a unit name.
+ *
* @param numUnits quantity of input units
* @param units input unit specifier (in, cm, etc.)
*/
@@ -41,16 +42,17 @@ public class FixedLength extends LengthProperty {
}
/**
- * Return the canonical FixedLength instance corresponding
+ * Return the cached FixedLength instance corresponding
* to the computed value
+ *
* @param numUnits input units
* @param units unit specifier
* @return the canonical FixedLength instance corresponding
* to the given number of units and unit specifier
*/
- public static FixedLength getInstance(double numUnits, String units) {
- return (FixedLength) cache.fetch(
- new FixedLength(numUnits, units));
+ public static FixedLength getInstance(double numUnits,
+ String units) {
+ return (FixedLength) cache.fetch(new FixedLength(numUnits, units));
}
diff --git a/src/java/org/apache/fop/fo/properties/FontFamilyProperty.java b/src/java/org/apache/fop/fo/properties/FontFamilyProperty.java
index 1b31351b8..610882aa4 100644
--- a/src/java/org/apache/fop/fo/properties/FontFamilyProperty.java
+++ b/src/java/org/apache/fop/fo/properties/FontFamilyProperty.java
@@ -19,6 +19,8 @@
package org.apache.fop.fo.properties;
+import java.util.Iterator;
+
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.expr.PropertyException;
@@ -26,8 +28,13 @@ import org.apache.fop.fo.expr.PropertyException;
/**
* Property class for the font-family property.
*/
-public class FontFamilyProperty extends ListProperty {
+public final class FontFamilyProperty extends ListProperty {
+ /** cache holding all canonical FontFamilyProperty instances */
+ private static final PropertyCache cache = new PropertyCache();
+
+ private int hash = 0;
+
/**
* Inner class for creating instances of ListProperty
*/
@@ -42,15 +49,12 @@ public class FontFamilyProperty extends ListProperty {
/**
* {@inheritDoc}
- * org.apache.fop.fo.PropertyList,
- * java.lang.String,
- * org.apache.fop.fo.FObj)
*/
public Property make(PropertyList propertyList, String value, FObj fo) throws PropertyException {
if ("inherit".equals(value)) {
return super.make(propertyList, value, fo);
} else {
- ListProperty prop = new ListProperty();
+ FontFamilyProperty prop = new FontFamilyProperty();
String tmpVal;
int startIndex = 0;
int commaIndex = value.indexOf(',');
@@ -89,7 +93,7 @@ public class FontFamilyProperty extends ListProperty {
prop.addProperty(StringProperty.getInstance(tmpVal));
}
}
- return prop;
+ return cache.fetch(prop);
}
}
@@ -110,12 +114,20 @@ public class FontFamilyProperty extends ListProperty {
/**
* @param prop the first Property to be added to the list
*/
- public FontFamilyProperty(Property prop) {
+ private FontFamilyProperty(Property prop) {
super();
addProperty(prop);
}
/**
+ * Default constructor.
+ *
+ */
+ private FontFamilyProperty() {
+ super();
+ }
+
+ /**
* Add a new property to the list
* @param prop Property to be added to the list
*/
@@ -137,4 +149,30 @@ public class FontFamilyProperty extends ListProperty {
}
}
+ /** {@inheritDoc} */
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (o instanceof FontFamilyProperty) {
+ FontFamilyProperty ffp = (FontFamilyProperty) o;
+ return (this.list != null
+ && this.list.equals(ffp.list));
+ }
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ public int hashCode() {
+ if (this.hash == 0) {
+ int hash = 17;
+ for (Iterator i = list.iterator(); i.hasNext();) {
+ Property p = (Property) i.next();
+ hash = 37 * hash + (p == null ? 0 : p.hashCode());
+ }
+ this.hash = hash;
+ }
+ return this.hash;
+ }
}
diff --git a/src/java/org/apache/fop/fo/properties/KeepProperty.java b/src/java/org/apache/fop/fo/properties/KeepProperty.java
index 9ac33fad3..2701c3f59 100644
--- a/src/java/org/apache/fop/fo/properties/KeepProperty.java
+++ b/src/java/org/apache/fop/fo/properties/KeepProperty.java
@@ -25,9 +25,14 @@ import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.expr.PropertyException;
/**
- * Superclass for properties that wrap Keep values
+ * Class for properties that wrap Keep values
*/
-public class KeepProperty extends Property implements CompoundDatatype {
+public final class KeepProperty extends Property implements CompoundDatatype {
+
+ /** class holding all canonical KeepProperty instances*/
+ private static final PropertyCache cache = new PropertyCache();
+
+ private boolean isCachedValue = false;
private Property withinLine;
private Property withinColumn;
private Property withinPage;
@@ -70,6 +75,10 @@ public class KeepProperty extends Property implements CompoundDatatype {
*/
public void setComponent(int cmpId, Property cmpnValue,
boolean bIsDefault) {
+ if (isCachedValue) {
+ log.warn("KeepProperty.setComponent() called on cached value. Ignoring...");
+ return;
+ }
if (cmpId == CP_WITHIN_LINE) {
setWithinLine(cmpnValue, bIsDefault);
} else if (cmpId == CP_WITHIN_COLUMN) {
@@ -152,10 +161,14 @@ public class KeepProperty extends Property implements CompoundDatatype {
}
/**
- * @return this.keep
+ * @return the canonical KeepProperty instance corresponding to
+ * this property
*/
public KeepProperty getKeep() {
- return this;
+ KeepProperty keep = (KeepProperty) cache.fetch(this);
+ /* make sure setComponent() can never alter cached values */
+ keep.isCachedValue = true;
+ return keep;
}
/**
@@ -165,4 +178,27 @@ public class KeepProperty extends Property implements CompoundDatatype {
return this;
}
+ /** {@inheritDoc} */
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (o instanceof KeepProperty) {
+ KeepProperty keep = (KeepProperty) o;
+ return (keep.withinColumn == this.withinColumn)
+ && (keep.withinLine == this.withinLine)
+ && (keep.withinPage == this.withinPage);
+ }
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ public int hashCode() {
+ int hash = 17;
+ hash = 37 * hash + (withinColumn == null ? 0 : withinColumn.hashCode());
+ hash = 37 * hash + (withinLine == null ? 0 : withinLine.hashCode());
+ hash = 37 * hash + (withinPage == null ? 0 : withinPage.hashCode());
+ return hash;
+ }
}
diff --git a/src/java/org/apache/fop/fo/properties/PropertyCache.java b/src/java/org/apache/fop/fo/properties/PropertyCache.java
index 0cca50bea..22f001a07 100644
--- a/src/java/org/apache/fop/fo/properties/PropertyCache.java
+++ b/src/java/org/apache/fop/fo/properties/PropertyCache.java
@@ -20,39 +20,353 @@
package org.apache.fop.fo.properties;
import java.lang.ref.WeakReference;
-import java.util.Collections;
-import java.util.Map;
-import java.util.WeakHashMap;
/**
- * Thin wrapper around a HashMap to implement the property caching idiom
- * in which a new Property instance is created then tested against cached
- * instances created previously. If an existing property is found, this is
- * retained and the newly created one is instantly eligible for garbage
- * collection.
+ * Dedicated cache, meant for storing canonical instances
+ * of property-related classes.
+ * The public access points are overloaded <code>fetch()</code> methods
+ * that each correspond to a cached type.
+ * It is designed especially to be used concurrently by multiple threads,
+ * drawing heavily upon the principles behind Java 1.5's
+ * <code>ConcurrentHashMap</code>.
*/
-public class PropertyCache {
+public final class PropertyCache {
- private Map propCache = Collections.synchronizedMap(new WeakHashMap());
+ /** bitmask to apply to the hash to get to the
+ * corresponding cache segment */
+ private static final int SEGMENT_MASK = 0x1F;
+ /** the segments array (length = 32) */
+ private CacheSegment[] segments = new CacheSegment[SEGMENT_MASK + 1];
+ /** the table of hash-buckets */
+ private CacheEntry[] table = new CacheEntry[8];
+
+ /* same hash function as used by java.util.HashMap */
+ private static int hash(Object x) {
+ int h = x.hashCode();
+
+ h += ~(h << 9);
+ h ^= (h >>> 14);
+ h += (h << 4);
+ h ^= (h >>> 10);
+ return h;
+ }
+
+ /* shortcut function */
+ private static boolean eq(Object p, Object q) {
+ return (p == q || (p != null && p.equals(q)));
+ }
+
+ /* Class modeling a cached entry */
+ private final class CacheEntry {
+ final CacheEntry next;
+ volatile WeakReference ref;
+ final int hash;
+
+ /* main constructor */
+ CacheEntry(Object p, CacheEntry next) {
+ this.next = next;
+ this.ref = new WeakReference(p);
+ this.hash = p.hashCode();
+ }
+
+ /* clone constructor */
+ CacheEntry(CacheEntry old, CacheEntry next) {
+ this.next = next;
+ this.ref = old.ref;
+ this.hash = old.hash;
+ }
+
+ }
+
+ /* Wrapper objects to synchronize on */
+ private final class CacheSegment {
+ private int count = 0;
+ }
+
+ /*
+ * Class modeling a cleanup thread.
+ *
+ * Once run() is called, the segment is locked and the hash-bucket
+ * will be traversed, removing any obsolete entries.
+ * If the cleanup has no effect, rehash() is called.
+ */
+ private final class CacheCleaner implements Runnable {
+
+ private int hash;
+
+ CacheCleaner(int hash) {
+ this.hash = hash;
+ }
+
+ public void run() {
+ //System.out.println("Cleaning segment " + this.segment);
+ CacheSegment segment = segments[this.hash & SEGMENT_MASK];
+ int oldCount;
+ int newCount;
+ synchronized (segment) {
+ oldCount = segment.count;
+ /* check first to see if another cleaner thread already
+ * pushed the number of entries back below the threshold
+ * if so, return immediately
+ */
+ if (segment.count < (2 * table.length)) {
+ return;
+ }
+
+ int index = this.hash & (table.length - 1);
+ CacheEntry first = table[index];
+ WeakReference ref;
+ for (CacheEntry e = first; e != null; e = e.next) {
+ ref = e.ref;
+ if (ref != null && ref.get() == null) {
+ /* remove obsolete entry
+ /* 1. clear value, cause interference for non-blocking get() */
+ e.ref = null;
+
+ /* 2. clone the segment, without the obsolete entry */
+ CacheEntry head = e.next;
+ for (CacheEntry c = first; c != e; c = c.next) {
+ head = new CacheEntry(c, head);
+ }
+ table[index] = head;
+ segment.count--;
+ }
+ }
+ newCount = segment.count;
+ }
+ if (oldCount == newCount) {
+ /* cleanup had no effect, try rehashing */
+ rehash(SEGMENT_MASK);
+ }
+ }
+ }
+
+ /*
+ * Puts a new instance in the cache.
+ * If the total number of entries for the corresponding
+ * segment exceeds twice the amount of hash-buckets, a
+ * cleanup thread will be launched to remove obsolete
+ * entries.
+ */
+ private final void put(Object o) {
+
+ int hash = hash(o);
+ CacheSegment segment = segments[hash & SEGMENT_MASK];
+
+ synchronized (segment) {
+ int index = hash & (table.length - 1);
+ CacheEntry entry = table[index];
+
+ if (entry == null) {
+ entry = new CacheEntry(o, null);
+ table[index] = entry;
+ segment.count++;
+ } else {
+ WeakReference ref = entry.ref;
+ if (ref != null && eq(ref.get(), o)) {
+ return;
+ } else {
+ CacheEntry newEntry = new CacheEntry(o, entry);
+ table[index] = newEntry;
+ segment.count++;
+ }
+ }
+
+ if (segment.count > (2 * table.length)) {
+ /* launch cleanup in a separate thread,
+ * so it acquires its own lock, and put()
+ * can return immediately */
+ Thread cleaner = new Thread(new CacheCleaner(hash));
+ cleaner.start();
+ }
+ }
+ }
+
+
+ /* Gets a cached instance. Returns null if not found */
+ private final Object get(Object o) {
+
+ int hash = hash(o);
+ int index = hash & (table.length - 1);
+
+ CacheEntry entry = table[index];
+ WeakReference r;
+ Object q;
+
+ /* try non-synched first */
+ for (CacheEntry e = entry; e != null; e = e.next) {
+ if (e.hash == o.hashCode()
+ && (r = e.ref) != null
+ && (q = r.get()) != null
+ && eq(q, o)) {
+ return q;
+ }
+ }
+
+ /* retry synched, only if the above attempt did not succeed,
+ * as another thread may, in the meantime, have added a
+ * corresponding entry */
+ CacheSegment segment = segments[hash & SEGMENT_MASK];
+ synchronized (segment) {
+ entry = table[index];
+ for (CacheEntry e = entry; e != null; e = e.next) {
+ if (e.hash == o.hashCode()
+ && (r = e.ref) != null
+ && (q = r.get()) != null
+ && eq(q, o)) {
+ return q;
+ }
+ }
+ }
+ return null;
+ }
+
+ /*
+ * Recursively acquires locks on all 32 segments,
+ * then performs a check on the segments first to see `
+ * how many precisely exceed the threshold ( 2 x table.length ).
+ * If this number exceeds half the amount of buckets,
+ * extends the cache and redistributes the entries.
+ *
+ * Example:
+ * For a cache with default size of 8 buckets, each bucket is
+ * a segment, and as such, rehash() will only have effect
+ * if more than 4 buckets exceed the size of 16 entries.
+ *
+ */
+ private final void rehash(int index) {
+
+ CacheSegment seg = segments[index];
+ synchronized (seg) {
+ if (index > 0) {
+ /* need to recursively acquire locks on all segments */
+ rehash(index - 1);
+ } else {
+ /* double the amount of buckets */
+ int newLength = table.length << 1;
+ if (newLength > 0) { //no overflow?
+ /* Check segmentcounts first */
+ int countSegments = 0;
+ int threshold = table.length * 2;
+ for (int i = segments.length; --i >= 0;) {
+ if (segments[i].count > threshold) {
+ countSegments++;
+ }
+ }
+
+ if (countSegments <= (table.length / 2)) {
+ return;
+ } else {
+ /* reset segmentcounts */
+ for (int i = segments.length; --i >= 0;) {
+ segments[i].count = 0;
+ }
+ }
+
+ CacheEntry[] newTable = new CacheEntry[newLength];
+
+ int hash, idx;
+ WeakReference ref;
+ Object o;
+ newLength--;
+ for (int i = table.length; --i >= 0;) {
+ for (CacheEntry c = table[i]; c != null; c = c.next) {
+ ref = c.ref;
+ if ((o = ref.get()) != null) {
+ hash = hash(o);
+ idx = hash & newLength;
+ newTable[idx] = new CacheEntry(c, newTable[idx]);
+ segments[hash & SEGMENT_MASK].count++;
+ }
+ }
+ }
+ table = newTable;
+ }
+ }
+ }
+ }
+
+ /**
+ * Default constructor.
+ */
+ public PropertyCache() {
+ for (int i = SEGMENT_MASK + 1; --i >= 0;) {
+ segments[i] = new CacheSegment();
+ }
+ }
+
+ /**
+ * Generic fetch() method.
+ * Checks if the given <code>Object</code> is present in the cache -
+ * if so, returns a reference to the cached instance.
+ * Otherwise the given object is added to the cache and returned.
+ *
+ * @param obj the Object to check for
+ * @return the cached instance
+ */
+ private final Object fetch(Object obj) {
+ if (obj == null) {
+ return null;
+ }
+
+ Object cacheEntry = get(obj);
+ if (cacheEntry != null) {
+ return cacheEntry;
+ }
+ put(obj);
+ return obj;
+ }
/**
- * Checks if the given property is present in the cache - if so, returns
- * a reference to the cached value. Otherwise the given object is added
- * to the cache and returned.
+ * Checks if the given <code>Property</code> is present in the cache -
+ * if so, returns a reference to the cached instance.
+ * Otherwise the given object is added to the cache and returned.
+ *
* @param prop the Property instance to check for
* @return the cached instance
*/
- public Property fetch(Property prop) {
+ public final Property fetch(Property prop) {
- WeakReference ref = (WeakReference) propCache.get(prop);
- if (ref != null) {
- Property cacheEntry = (Property)ref.get();
- if (cacheEntry != null) {
- return cacheEntry;
- }
- }
- propCache.put(prop, new WeakReference(prop));
- return prop;
+ return (Property) fetch((Object) prop);
+ }
+
+ /**
+ * Checks if the given <code>CommonHyphenation</code> is present in the cache -
+ * if so, returns a reference to the cached instance.
+ * Otherwise the given object is added to the cache and returned.
+ *
+ * @param chy the CommonHyphenation instance to check for
+ * @return the cached instance
+ */
+ public final CommonHyphenation fetch(CommonHyphenation chy) {
+
+ return (CommonHyphenation) fetch((Object) chy);
+ }
+
+ /**
+ * Checks if the given <code>CachedCommonFont</code> is present in the cache -
+ * if so, returns a reference to the cached instance.
+ * Otherwise the given object is added to the cache and returned.
+ *
+ * @param ccf the CachedCommonFont instance to check for
+ * @return the cached instance
+ */
+ public final CommonFont.CachedCommonFont fetch(CommonFont.CachedCommonFont ccf) {
+
+ return (CommonFont.CachedCommonFont) fetch((Object) ccf);
+ }
+
+ /**
+ * Checks if the given <code>CommonFont</code> is present in the cache -
+ * if so, returns a reference to the cached instance.
+ * Otherwise the given object is added to the cache and returned.
+ *
+ * @param cf the CommonFont instance to check for
+ * @return the cached instance
+ */
+ public final CommonFont fetch(CommonFont cf) {
+
+ return (CommonFont) fetch((Object) cf);
}
}
diff --git a/src/java/org/apache/fop/fonts/FontInfo.java b/src/java/org/apache/fop/fonts/FontInfo.java
index 995d59bf8..e833b7b93 100644
--- a/src/java/org/apache/fop/fonts/FontInfo.java
+++ b/src/java/org/apache/fop/fonts/FontInfo.java
@@ -41,6 +41,8 @@ import org.apache.commons.logging.LogFactory;
*/
public class FontInfo {
+ private static final FontTriplet[] TRIPLETS_TYPE = new FontTriplet[1];
+
/** logging instance */
protected static Log log = LogFactory.getLog(FontInfo.class);
@@ -232,26 +234,35 @@ public class FontInfo {
}
/**
- * Lookup a font.
+ * Looks up a set of fonts.
* <br>
- * Locate the font name for a given family, style and weight.
- * The font name can then be used as a key as it is unique for
+ * Locate the font name(s) for the given families, style and weight.
+ * The font name(s) can then be used as a key as they are unique for
* the associated document.
- * This also adds the font to the list of used fonts.
- * @param family font family (priority list)
- * @param style font style
- * @param weight font weight
- * @return font triplet of the font chosen
+ * This also adds the fonts to the list of used fonts.
+ * @param families font families (priority list)
+ * @param style font style
+ * @param weight font weight
+ * @return the set of font triplets of all supported and chosen font-families
+ * in the specified style and weight.
*/
- public FontTriplet fontLookup(String[] family, String style,
+ public FontTriplet[] fontLookup(String[] families, String style,
int weight) {
- for (int i = 0; i < family.length; i++) {
- FontTriplet triplet = fontLookup(family[i], style, weight, (i >= family.length - 1));
+ FontTriplet triplet;
+ List tmpTriplets = new ArrayList();
+ for (int i = 0; i < families.length; i++) {
+ triplet = fontLookup(families[i], style, weight, (i >= families.length - 1));
if (triplet != null) {
- return triplet;
+ tmpTriplets.add(triplet);
}
}
- throw new IllegalStateException("fontLookup must return a key on the last call");
+ if (tmpTriplets.size() != 0) {
+ FontTriplet[] triplets = (FontTriplet[]) tmpTriplets.toArray(TRIPLETS_TYPE);
+ return (FontTriplet[]) triplets;
+ }
+ throw new IllegalStateException(
+ "fontLookup must return an array with at least one "
+ + "FontTriplet on the last call.");
}
private void notifyFontReplacement(FontTriplet replacedKey, FontTriplet newKey) {
diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
index 0300a6cf2..597f41ad0 100644
--- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
@@ -30,6 +30,8 @@ import org.apache.fop.area.Block;
import org.apache.fop.area.LineArea;
import org.apache.fop.datatypes.Length;
import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.layoutmgr.inline.InlineLayoutManager;
import org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager;
import org.apache.fop.layoutmgr.inline.LineLayoutManager;
@@ -78,11 +80,11 @@ public class BlockLayoutManager extends BlockStackingLayoutManager
public void initialize() {
super.initialize();
- Font fs = getBlockFO().getCommonFont().getFontState(
- getBlockFO().getFOEventHandler().getFontInfo(), this);
-
- lead = fs.getAscender();
- follow = -fs.getDescender();
+ FontInfo fi = getBlockFO().getFOEventHandler().getFontInfo();
+ FontTriplet[] fontkeys = getBlockFO().getCommonFont().getFontState(fi);
+ Font initFont = fi.getFontInstance(fontkeys[0], getBlockFO().getCommonFont().fontSize.getValue(this));
+ lead = initFont.getAscender();
+ follow = -initFont.getDescender();
//middleShift = -fs.getXHeight() / 2;
lineHeight = getBlockFO().getLineHeight().getOptimum(this).getLength();
startIndent = getBlockFO().getCommonMarginBlock().startIndent.getValue(this);
diff --git a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java
index 25e196398..f470e137e 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java
@@ -21,6 +21,8 @@ package org.apache.fop.layoutmgr.inline;
import org.apache.fop.fo.flow.Character;
import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.layoutmgr.InlineKnuthSequence;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthGlue;
@@ -63,10 +65,12 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager {
/** {@inheritDoc} */
public void initialize() {
- font = fobj.getCommonFont().getFontState(fobj.getFOEventHandler().getFontInfo(), this);
+ FontInfo fi = fobj.getFOEventHandler().getFontInfo();
+ FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi);
+ font = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this));
SpaceVal ls = SpaceVal.makeLetterSpacing(fobj.getLetterSpacing());
letterSpaceIPD = ls.getSpace();
- hyphIPD = font.getCharWidth(fobj.getCommonHyphenation().hyphenationCharacter);
+ hyphIPD = font.getCharWidth(fobj.getCommonHyphenation().hyphenationCharacter.getCharacter());
borderProps = fobj.getCommonBorderPaddingBackground();
setCommonBorderPaddingBackground(borderProps);
org.apache.fop.area.inline.TextArea chArea = getCharacterInlineArea(fobj);
diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java
index 30402a5f2..e9b6c19ec 100755
--- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java
@@ -39,6 +39,8 @@ import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonMarginInline;
import org.apache.fop.fo.properties.SpaceProperty;
import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.layoutmgr.BlockKnuthSequence;
import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
import org.apache.fop.layoutmgr.BreakElement;
@@ -87,6 +89,8 @@ public class InlineLayoutManager extends InlineStackingLayoutManager {
protected int dominantBaseline;
/** The line height property */
protected SpaceProperty lineHeight;
+ /** The keep-together property */
+ //private KeepProperty keepTogether;
private AlignmentContext alignmentContext = null;
@@ -110,7 +114,9 @@ public class InlineLayoutManager extends InlineStackingLayoutManager {
/** {@inheritDoc} */
public void initialize() {
int padding = 0;
- font = fobj.getCommonFont().getFontState(fobj.getFOEventHandler().getFontInfo(), this);
+ FontInfo fi = fobj.getFOEventHandler().getFontInfo();
+ FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi);
+ font = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this));
lineHeight = fobj.getLineHeight();
borderProps = fobj.getCommonBorderPaddingBackground();
inlineProps = fobj.getCommonMarginInline();
diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java
index a7c5178b0..5f93ab98c 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java
@@ -26,6 +26,8 @@ import org.apache.fop.area.inline.Space;
import org.apache.fop.area.inline.TextArea;
import org.apache.fop.fo.flow.Leader;
import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.layoutmgr.InlineKnuthSequence;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthGlue;
@@ -67,7 +69,9 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager {
/** {@inheritDoc} */
public void initialize() {
- font = fobj.getCommonFont().getFontState(fobj.getFOEventHandler().getFontInfo(), this);
+ FontInfo fi = fobj.getFOEventHandler().getFontInfo();
+ FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi);
+ font = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this));
// the property leader-alignment does not affect vertical positioning
// (see section 7.21.1 in the XSL Recommendation)
// setAlignment(node.getLeaderAlignment());
diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
index ad1f6d231..d6f88f54f 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
@@ -59,6 +59,8 @@ import java.util.ArrayList;
import java.util.LinkedList;
import org.apache.fop.area.Trait;
import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.traits.MinOptMax;
@@ -569,7 +571,9 @@ public class LineLayoutManager extends InlineStackingLayoutManager
/** {@inheritDoc} */
public LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
- Font fs = fobj.getCommonFont().getFontState(fobj.getFOEventHandler().getFontInfo(), this);
+ FontInfo fi = fobj.getFOEventHandler().getFontInfo();
+ FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi);
+ Font fs = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this));
alignmentContext
= new AlignmentContext(fs, lineHeight.getValue(this), context.getWritingMode());
context.setAlignmentContext(alignmentContext);
@@ -941,7 +945,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager
? 0 : hyphenationLadderCount.getValue(),
this);
- if (hyphenationProperties.hyphenate == EN_TRUE
+ if (hyphenationProperties.hyphenate.getEnum() == EN_TRUE
&& fobj.getWrapOption() != EN_NO_WRAP) {
findHyphenationPoints(currPar);
}
@@ -967,8 +971,8 @@ public class LineLayoutManager extends InlineStackingLayoutManager
}
// now try something different
- log.debug("Hyphenation possible? " + (hyphenationProperties.hyphenate == EN_TRUE));
- if (hyphenationProperties.hyphenate == EN_TRUE
+ log.debug("Hyphenation possible? " + (hyphenationProperties.hyphenate.getEnum() == EN_TRUE));
+ if (hyphenationProperties.hyphenate.getEnum() == EN_TRUE
&& !(allowedBreaks == BreakingAlgorithm.ONLY_FORCED_BREAKS)) {
// consider every hyphenation point as a legal break
allowedBreaks = BreakingAlgorithm.ALL_BREAKS;
@@ -983,10 +987,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager
// the second try failed too, try with a huge threshold
// and force the algorithm to find
// a set of breaking points
- log.debug("No set of breaking points found with maxAdjustment = "
- + maxAdjustment
- + (hyphenationProperties.hyphenate == EN_TRUE
- ? " and hyphenation" : ""));
+ if (log.isDebugEnabled()) {
+ log.debug("No set of breaking points found with maxAdjustment = "
+ + maxAdjustment
+ + (hyphenationProperties.hyphenate.getEnum() == EN_TRUE
+ ? " and hyphenation" : ""));
+ }
maxAdjustment = 20;
iBPcount
= alg.findBreakingPoints(currPar,
@@ -1526,12 +1532,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager
// since these properties inherit and could be specified
// on an inline or wrapper below the block level.
Hyphenation hyph
- = Hyphenator.hyphenate(hyphenationProperties.language,
- hyphenationProperties.country,
+ = Hyphenator.hyphenate(hyphenationProperties.language.getString(),
+ hyphenationProperties.country.getString(),
getFObj().getUserAgent().getFactory().getHyphenationTreeResolver(),
sbChars.toString(),
- hyphenationProperties.hyphenationRemainCharacterCount,
- hyphenationProperties.hyphenationPushCharacterCount);
+ hyphenationProperties.hyphenationRemainCharacterCount.getValue(),
+ hyphenationProperties.hyphenationPushCharacterCount.getValue());
// They hyph structure contains the information we need
// Now start from prev: reset to that position, ask that LM to get
// a Position for the first hyphenation offset. If the offset isn't in
diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java
index fda62ea15..f3a83b9f2 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java
@@ -27,6 +27,8 @@ import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.area.inline.UnresolvedPageNumber;
import org.apache.fop.area.inline.TextArea;
import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.LayoutManager;
import org.apache.fop.layoutmgr.PositionIterator;
@@ -57,7 +59,9 @@ public class PageNumberCitationLayoutManager extends LeafNodeLayoutManager {
/** {@inheritDoc} */
public void initialize() {
- font = fobj.getCommonFont().getFontState(fobj.getFOEventHandler().getFontInfo(), this);
+ FontInfo fi = fobj.getFOEventHandler().getFontInfo();
+ FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi);
+ font = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this));
setCommonBorderPaddingBackground(fobj.getCommonBorderPaddingBackground());
}
diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java
index d09523e3c..88f1d283c 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java
@@ -24,6 +24,8 @@ import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.area.inline.TextArea;
import org.apache.fop.area.Trait;
import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.traits.MinOptMax;
@@ -49,7 +51,9 @@ public class PageNumberLayoutManager extends LeafNodeLayoutManager {
/** {@inheritDoc} */
public void initialize() {
- font = fobj.getCommonFont().getFontState(fobj.getFOEventHandler().getFontInfo(), this);
+ FontInfo fi = fobj.getFOEventHandler().getFontInfo();
+ FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi);
+ font = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this));
setCommonBorderPaddingBackground(fobj.getCommonBorderPaddingBackground());
}
diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
index adb76846c..e62f3dc2a 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
@@ -31,6 +31,8 @@ import org.apache.fop.area.inline.TextArea;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FOText;
import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.layoutmgr.InlineKnuthSequence;
import org.apache.fop.layoutmgr.KnuthBox;
import org.apache.fop.layoutmgr.KnuthElement;
@@ -186,12 +188,14 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
/** {@inheritDoc} */
public void initialize() {
- font = foText.getCommonFont().getFontState(foText.getFOEventHandler().getFontInfo(), this);
+ FontInfo fi = foText.getFOEventHandler().getFontInfo();
+ FontTriplet[] fontkeys = foText.getCommonFont().getFontState(fi);
+ font = fi.getFontInstance(fontkeys[0], foText.getCommonFont().fontSize.getValue(this));
// With CID fonts, space isn't neccesary currentFontState.width(32)
spaceCharIPD = font.getCharWidth(' ');
// Use hyphenationChar property
- hyphIPD = font.getCharWidth(foText.getCommonHyphenation().hyphenationCharacter);
+ hyphIPD = font.getCharWidth(foText.getCommonHyphenation().hyphenationCharacter.getCharacter());
SpaceVal ls = SpaceVal.makeLetterSpacing(foText.getLetterSpacing());
halfLS = new SpaceVal(MinOptMax.multiply(ls.getSpace(), 0.5),
@@ -504,7 +508,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager {
&& i == lastIndex
&& areaInfo.bHyphenated) {
// add the hyphenation character
- wordChars.append(foText.getCommonHyphenation().hyphenationCharacter);
+ wordChars.append(foText.getCommonHyphenation().hyphenationCharacter.getCharacter());
}
textArea.addWord(wordChars.toString(), 0, letterAdjust);
wordStartIndex = -1;
diff --git a/src/java/org/apache/fop/render/rtf/TextAttributesConverter.java b/src/java/org/apache/fop/render/rtf/TextAttributesConverter.java
index d85a634b8..d40c6a826 100644
--- a/src/java/org/apache/fop/render/rtf/TextAttributesConverter.java
+++ b/src/java/org/apache/fop/render/rtf/TextAttributesConverter.java
@@ -142,16 +142,16 @@ final class TextAttributesConverter {
RtfFontManager.getInstance().getFontNumber(font.getFirstFontFamily()));
rtfAttr.setHalfPoints(RtfText.ATTR_FONT_SIZE, font.fontSize);
- if (font.fontWeight == Constants.EN_700
- || font.fontWeight == Constants.EN_800
- || font.fontWeight == Constants.EN_900) {
+ if (font.getFontWeight() == Constants.EN_700
+ || font.getFontWeight() == Constants.EN_800
+ || font.getFontWeight() == Constants.EN_900) {
//Everything from 700 and above is declared as bold
rtfAttr.set("b", 1);
} else {
rtfAttr.set("b", 0);
}
- if (font.fontStyle == Constants.EN_ITALIC) {
+ if (font.getFontStyle() == Constants.EN_ITALIC) {
rtfAttr.set(RtfText.ATTR_ITALIC, 1);
} else {
rtfAttr.set(RtfText.ATTR_ITALIC, 0);
diff --git a/status.xml b/status.xml
index 645ca66c1..ccf8190de 100644
--- a/status.xml
+++ b/status.xml
@@ -28,6 +28,23 @@
<changes>
<release version="FOP Trunk">
+ <action context="code" dev="AD" type="update">
+ Facilitate the implementation for font-selection-strategy:
+ * Changed FontInfo.fontLookup to always return an array of FontTriplet
+ * Changed CommonFont.getFontState to return an array of FontTriplet
+ * Initial modifications to the related LMs: initialized with
+ the font corresponding to the first of the triplets
+ </action>
+ <action context="code" dev="AD" type="update">
+ PropertyCache phase 2:
+ * improvement of the PropertyCache itself should now guarantee acceptable
+ performance of the static caches in multi-session environments, which is
+ a possible problem with synchronizedMap
+ * changed CommonFont to use the cache:
+ added CachedCommonFont to contain the properties that are always cacheable
+ CommonFont itself is only cached if the remaining properties are absolutes
+ * changed CommonHyphenation, KeepProperty, ColorProperty and FontFamilyProperty to use the cache
+ </action>
<action context="Code" dev="AD" type="fix" fixes-bug="42705">
Fixed swallowing PCDATA in text-node children of
retrieved markers.