Browse Source

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
tags/fop-0_95beta
Andreas L. Delmelle 16 years ago
parent
commit
6045d497f2
28 changed files with 975 additions and 245 deletions
  1. 1
    1
      src/java/org/apache/fop/fo/FOPropertyMapping.java
  2. 3
    3
      src/java/org/apache/fop/fo/PropertyList.java
  3. 1
    1
      src/java/org/apache/fop/fo/expr/CMYKcolorFunction.java
  4. 1
    1
      src/java/org/apache/fop/fo/expr/ICCColorFunction.java
  5. 1
    1
      src/java/org/apache/fop/fo/expr/PropertyParser.java
  6. 1
    1
      src/java/org/apache/fop/fo/expr/RGBColorFunction.java
  7. 1
    1
      src/java/org/apache/fop/fo/expr/SystemColorFunction.java
  8. 38
    8
      src/java/org/apache/fop/fo/properties/ColorProperty.java
  9. 1
    1
      src/java/org/apache/fop/fo/properties/CommonAccessibility.java
  10. 5
    6
      src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java
  11. 280
    91
      src/java/org/apache/fop/fo/properties/CommonFont.java
  12. 108
    42
      src/java/org/apache/fop/fo/properties/CommonHyphenation.java
  13. 0
    6
      src/java/org/apache/fop/fo/properties/CompoundPropertyMaker.java
  14. 7
    5
      src/java/org/apache/fop/fo/properties/FixedLength.java
  15. 45
    7
      src/java/org/apache/fop/fo/properties/FontFamilyProperty.java
  16. 40
    4
      src/java/org/apache/fop/fo/properties/KeepProperty.java
  17. 337
    23
      src/java/org/apache/fop/fo/properties/PropertyCache.java
  18. 24
    13
      src/java/org/apache/fop/fonts/FontInfo.java
  19. 7
    5
      src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
  20. 6
    2
      src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java
  21. 7
    1
      src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java
  22. 5
    1
      src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java
  23. 18
    12
      src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
  24. 5
    1
      src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java
  25. 5
    1
      src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java
  26. 7
    3
      src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
  27. 4
    4
      src/java/org/apache/fop/render/rtf/TextAttributesConverter.java
  28. 17
    0
      status.xml

+ 1
- 1
src/java/org/apache/fop/fo/FOPropertyMapping.java View File

@@ -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);
}

+ 3
- 3
src/java/org/apache/fop/fo/PropertyList.java View File

@@ -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);
}
/**

+ 1
- 1
src/java/org/apache/fop/fo/expr/CMYKcolorFunction.java View File

@@ -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());
}



+ 1
- 1
src/java/org/apache/fop/fo/expr/ICCColorFunction.java View File

@@ -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());
}



+ 1
- 1
src/java/org/apache/fop/fo/expr/PropertyParser.java View File

@@ -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:

+ 1
- 1
src/java/org/apache/fop/fo/expr/RGBColorFunction.java View File

@@ -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] + ")");

}


+ 1
- 1
src/java/org/apache/fop/fo/expr/SystemColorFunction.java View File

@@ -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] + ")");

}


+ 38
- 8
src/java/org/apache/fop/fo/properties/ColorProperty.java View File

@@ -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();
}
}


+ 1
- 1
src/java/org/apache/fop/fo/properties/CommonAccessibility.java View File

@@ -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 {

+ 5
- 6
src/java/org/apache/fop/fo/properties/CommonBorderPaddingBackground.java View File

@@ -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);

+ 280
- 91
src/java/org/apache/fop/fo/properties/CommonFont.java View File

@@ -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;
}
}

+ 108
- 42
src/java/org/apache/fop/fo/properties/CommonHyphenation.java View File

@@ -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;
}
}

+ 0
- 6
src/java/org/apache/fop/fo/properties/CompoundPropertyMaker.java View File

@@ -25,12 +25,6 @@ import org.apache.fop.fo.FObj;
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.
*/

+ 7
- 5
src/java/org/apache/fop/fo/properties/FixedLength.java View File

@@ -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));
}

+ 45
- 7
src/java/org/apache/fop/fo/properties/FontFamilyProperty.java View File

@@ -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,11 +114,19 @@ 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;
}
}

+ 40
- 4
src/java/org/apache/fop/fo/properties/KeepProperty.java View File

@@ -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;
}
}

+ 337
- 23
src/java/org/apache/fop/fo/properties/PropertyCache.java View File

@@ -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);
}
}

+ 24
- 13
src/java/org/apache/fop/fonts/FontInfo.java View File

@@ -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) {

+ 7
- 5
src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java View File

@@ -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);

+ 6
- 2
src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java View File

@@ -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);

+ 7
- 1
src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java View File

@@ -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();

+ 5
- 1
src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java View File

@@ -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());

+ 18
- 12
src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java View File

@@ -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

+ 5
- 1
src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java View File

@@ -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());
}


+ 5
- 1
src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java View File

@@ -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());
}


+ 7
- 3
src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java View File

@@ -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;

+ 4
- 4
src/java/org/apache/fop/render/rtf/TextAttributesConverter.java View File

@@ -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);

+ 17
- 0
status.xml View File

@@ -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.

Loading…
Cancel
Save