You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CommonHyphenation.java 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /* $Id$ */
  18. package org.apache.fop.fo.properties;
  19. import org.apache.commons.logging.Log;
  20. import org.apache.commons.logging.LogFactory;
  21. import org.apache.fop.fo.Constants;
  22. import org.apache.fop.fo.PropertyList;
  23. import org.apache.fop.fo.expr.PropertyException;
  24. import org.apache.fop.fonts.FontMetrics;
  25. import org.apache.fop.fonts.Typeface;
  26. /**
  27. * Store all common hyphenation properties.
  28. * See Sec. 7.9 of the XSL-FO Standard.
  29. * Public "structure" allows direct member access.
  30. */
  31. public final class CommonHyphenation {
  32. /** Logger */
  33. private static final Log LOG = LogFactory.getLog(CommonHyphenation.class);
  34. private static final PropertyCache<CommonHyphenation> CACHE =
  35. new PropertyCache<CommonHyphenation>();
  36. private int hash = 0;
  37. /** The "language" property */
  38. public final StringProperty language; // CSOK: VisibilityModifier
  39. /** The "country" property */
  40. public final StringProperty country; // CSOK: VisibilityModifier
  41. /** The "script" property */
  42. public final StringProperty script; // CSOK: VisibilityModifier
  43. /** The "hyphenate" property */
  44. public final EnumProperty hyphenate; // CSOK: VisibilityModifier
  45. /** The "hyphenation-character" property */
  46. public final CharacterProperty hyphenationCharacter; // CSOK: VisibilityModifier
  47. /** The "hyphenation-push-character-count" property */
  48. public final NumberProperty hyphenationPushCharacterCount; // CSOK: VisibilityModifier
  49. /** The "hyphenation-remain-character-count" property*/
  50. public final NumberProperty hyphenationRemainCharacterCount; // CSOK: VisibilityModifier
  51. /**
  52. * Construct a CommonHyphenation object holding the given properties
  53. *
  54. */
  55. private CommonHyphenation(StringProperty language,
  56. StringProperty country,
  57. StringProperty script,
  58. EnumProperty hyphenate,
  59. CharacterProperty hyphenationCharacter,
  60. NumberProperty hyphenationPushCharacterCount,
  61. NumberProperty hyphenationRemainCharacterCount) {
  62. this.language = language;
  63. this.country = country;
  64. this.script = script;
  65. this.hyphenate = hyphenate;
  66. this.hyphenationCharacter = hyphenationCharacter;
  67. this.hyphenationPushCharacterCount = hyphenationPushCharacterCount;
  68. this.hyphenationRemainCharacterCount = hyphenationRemainCharacterCount;
  69. }
  70. /**
  71. * Gets the canonical <code>CommonHyphenation</code> instance corresponding
  72. * to the values of the related properties present on the given
  73. * <code>PropertyList</code>
  74. * @param propertyList the <code>PropertyList</code>
  75. * @return a common hyphenation instance
  76. * @throws PropertyException if a a property exception occurs
  77. */
  78. public static CommonHyphenation getInstance(PropertyList propertyList)
  79. throws PropertyException {
  80. StringProperty language
  81. = (StringProperty) propertyList.get(Constants.PR_LANGUAGE);
  82. StringProperty country
  83. = (StringProperty) propertyList.get(Constants.PR_COUNTRY);
  84. StringProperty script
  85. = (StringProperty) propertyList.get(Constants.PR_SCRIPT);
  86. EnumProperty hyphenate
  87. = (EnumProperty) propertyList.get(Constants.PR_HYPHENATE);
  88. CharacterProperty hyphenationCharacter
  89. = (CharacterProperty) propertyList.get(Constants.PR_HYPHENATION_CHARACTER);
  90. NumberProperty hyphenationPushCharacterCount
  91. = (NumberProperty) propertyList.get(Constants.PR_HYPHENATION_PUSH_CHARACTER_COUNT);
  92. NumberProperty hyphenationRemainCharacterCount
  93. = (NumberProperty) propertyList.get(Constants.PR_HYPHENATION_REMAIN_CHARACTER_COUNT);
  94. CommonHyphenation instance = new CommonHyphenation(
  95. language,
  96. country,
  97. script,
  98. hyphenate,
  99. hyphenationCharacter,
  100. hyphenationPushCharacterCount,
  101. hyphenationRemainCharacterCount);
  102. return CACHE.fetch(instance);
  103. }
  104. private static final char HYPHEN_MINUS = '-';
  105. private static final char MINUS_SIGN = '\u2212';
  106. /**
  107. * Returns the effective hyphenation character for a font. The hyphenation character specified
  108. * in XSL-FO may be substituted if it's not available in the font.
  109. * @param font the font
  110. * @return the effective hyphenation character.
  111. */
  112. public char getHyphChar(org.apache.fop.fonts.Font font) {
  113. char hyphChar = hyphenationCharacter.getCharacter();
  114. if (font.hasChar(hyphChar)) {
  115. return hyphChar; //short-cut
  116. }
  117. char effHyphChar = hyphChar;
  118. boolean warn = false;
  119. if (font.hasChar(HYPHEN_MINUS)) {
  120. effHyphChar = HYPHEN_MINUS;
  121. warn = true;
  122. } else if (font.hasChar(MINUS_SIGN)) {
  123. effHyphChar = MINUS_SIGN;
  124. FontMetrics metrics = font.getFontMetrics();
  125. if (metrics instanceof Typeface) {
  126. Typeface typeface = (Typeface)metrics;
  127. if ("SymbolEncoding".equals(typeface.getEncodingName())) {
  128. //SymbolEncoding doesn't have HYPHEN_MINUS, so replace by MINUS_SIGN
  129. } else {
  130. //only warn if the encoding is not SymbolEncoding
  131. warn = true;
  132. }
  133. }
  134. } else {
  135. effHyphChar = ' ';
  136. FontMetrics metrics = font.getFontMetrics();
  137. if (metrics instanceof Typeface) {
  138. Typeface typeface = (Typeface)metrics;
  139. if ("ZapfDingbatsEncoding".equals(typeface.getEncodingName())) {
  140. //ZapfDingbatsEncoding doesn't have HYPHEN_MINUS, so replace by ' '
  141. } else {
  142. //only warn if the encoding is not ZapfDingbatsEncoding
  143. warn = true;
  144. }
  145. }
  146. }
  147. if (warn) {
  148. LOG.warn("Substituted specified hyphenation character (0x"
  149. + Integer.toHexString(hyphChar)
  150. + ") with 0x" + Integer.toHexString(effHyphChar)
  151. + " because the font doesn't have the specified hyphenation character: "
  152. + font.getFontTriplet());
  153. }
  154. return effHyphChar;
  155. }
  156. /**
  157. * Returns the IPD for the hyphenation character for a font.
  158. * @param font the font
  159. * @return the IPD in millipoints for the hyphenation character.
  160. */
  161. public int getHyphIPD(org.apache.fop.fonts.Font font) {
  162. char hyphChar = getHyphChar(font);
  163. return font.getCharWidth(hyphChar);
  164. }
  165. /** {@inheritDoc} */
  166. public boolean equals(Object obj) {
  167. if (obj == this) {
  168. return true;
  169. }
  170. if (obj instanceof CommonHyphenation) {
  171. CommonHyphenation ch = (CommonHyphenation) obj;
  172. return (ch.language == this.language
  173. && ch.country == this.country
  174. && ch.script == this.script
  175. && ch.hyphenate == this.hyphenate
  176. && ch.hyphenationCharacter == this.hyphenationCharacter
  177. && ch.hyphenationPushCharacterCount == this.hyphenationPushCharacterCount
  178. && ch.hyphenationRemainCharacterCount == this.hyphenationRemainCharacterCount);
  179. }
  180. return false;
  181. }
  182. /** {@inheritDoc} */
  183. public int hashCode() {
  184. if (this.hash == 0) {
  185. int hash = 17;
  186. hash = 37 * hash + (language == null ? 0 : language.hashCode());
  187. hash = 37 * hash + (script == null ? 0 : script.hashCode());
  188. hash = 37 * hash + (country == null ? 0 : country.hashCode());
  189. hash = 37 * hash + (hyphenate == null ? 0 : hyphenate.hashCode());
  190. hash = 37 * hash
  191. + (hyphenationCharacter == null
  192. ? 0 : hyphenationCharacter.hashCode());
  193. hash = 37 * hash
  194. + (hyphenationPushCharacterCount == null
  195. ? 0 : hyphenationPushCharacterCount.hashCode());
  196. hash = 37 * hash
  197. + (hyphenationRemainCharacterCount == null
  198. ? 0 : hyphenationRemainCharacterCount.hashCode());
  199. this.hash = hash;
  200. }
  201. return this.hash;
  202. }
  203. }