123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- /* $Id$ */
-
- package org.apache.fop.fo.properties;
-
- import java.util.Locale;
-
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
-
- import org.apache.fop.fo.Constants;
- import org.apache.fop.fo.PropertyList;
- import org.apache.fop.fo.expr.PropertyException;
- import org.apache.fop.fonts.FontMetrics;
- import org.apache.fop.fonts.Typeface;
-
- /**
- * Store all common hyphenation properties.
- * See Sec. 7.9 of the XSL-FO Standard.
- * Public "structure" allows direct member access.
- */
- public final class CommonHyphenation {
-
- /** Logger */
- private static final Log LOG = LogFactory.getLog(CommonHyphenation.class);
-
- private static final PropertyCache<CommonHyphenation> CACHE =
- new PropertyCache<CommonHyphenation>();
-
- private int hash;
-
- /** The "language" property */
- public final StringProperty language;
-
- /** The "country" property */
- public final StringProperty country;
-
- /** The "script" property */
- public final StringProperty script;
-
- /** The "hyphenate" property */
- public final EnumProperty hyphenate;
-
- /** The "hyphenation-character" property */
- public final OptionalCharacterProperty hyphenationCharacter;
-
- /** The "hyphenation-push-character-count" property */
- public final NumberProperty hyphenationPushCharacterCount;
-
- /** The "hyphenation-remain-character-count" property*/
- public final NumberProperty hyphenationRemainCharacterCount;
-
- /**
- * Construct a CommonHyphenation object holding the given properties
- *
- */
- private CommonHyphenation(StringProperty language,
- StringProperty country,
- StringProperty script,
- EnumProperty hyphenate,
- OptionalCharacterProperty 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;
- }
-
- /**
- * 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>
- * @return a common hyphenation instance
- * @throws PropertyException if a a property exception occurs
- */
- 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);
- OptionalCharacterProperty hyphenationCharacter
- = (OptionalCharacterProperty) 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);
- }
-
- private static final char HYPHEN_MINUS = '-';
- private static final char MINUS_SIGN = '\u2212';
-
- /**
- * Returns the effective hyphenation character for a font. The hyphenation character specified
- * in XSL-FO may be substituted if it's not available in the font.
- * @param font the font
- * @return the effective hyphenation character.
- */
- public Character getHyphChar(org.apache.fop.fonts.Font font) {
- if (hyphenationCharacter.getObject() == null) {
- return null;
- }
- char hyphChar = hyphenationCharacter.getCharacter();
- if (font.hasChar(hyphChar)) {
- return hyphChar; //short-cut
- }
- char effHyphChar = hyphChar;
- boolean warn = false;
- if (font.hasChar(HYPHEN_MINUS)) {
- effHyphChar = HYPHEN_MINUS;
- warn = true;
- } else if (font.hasChar(MINUS_SIGN)) {
- effHyphChar = MINUS_SIGN;
- FontMetrics metrics = font.getFontMetrics();
- if (metrics instanceof Typeface) {
- Typeface typeface = (Typeface)metrics;
- if ("SymbolEncoding".equals(typeface.getEncodingName())) {
- //SymbolEncoding doesn't have HYPHEN_MINUS, so replace by MINUS_SIGN
- } else {
- //only warn if the encoding is not SymbolEncoding
- warn = true;
- }
- }
- } else {
- effHyphChar = ' ';
- FontMetrics metrics = font.getFontMetrics();
- if (metrics instanceof Typeface) {
- Typeface typeface = (Typeface)metrics;
- if ("ZapfDingbatsEncoding".equals(typeface.getEncodingName())) {
- //ZapfDingbatsEncoding doesn't have HYPHEN_MINUS, so replace by ' '
- } else {
- //only warn if the encoding is not ZapfDingbatsEncoding
- warn = true;
- }
- }
- }
- if (warn) {
- LOG.warn("Substituted specified hyphenation character (0x"
- + Integer.toHexString(hyphChar)
- + ") with 0x" + Integer.toHexString(effHyphChar)
- + " because the font doesn't have the specified hyphenation character: "
- + font.getFontTriplet());
- }
- return effHyphChar;
- }
-
- /**
- * Returns the IPD for the hyphenation character for a font.
- * @param font the font
- * @return the IPD in millipoints for the hyphenation character.
- */
- public int getHyphIPD(org.apache.fop.fonts.Font font) {
- Character hyphChar = getHyphChar(font);
- return (hyphChar == null) ? 0 : font.getCharWidth(hyphChar);
- }
-
- /**
- * Creates and returns a {@link Locale} representation of the language and country.
- *
- * @return the language (and the country if set) represented as a locale, {@code null}
- * if the language has not been set (i.e., has been left to its initial value of
- * "none")
- */
- public Locale getLocale() {
- return toLocale(language.getString(), country.getString());
- }
-
- /**
- * Creates and returns a {@link Locale} representation of the given language, and the
- * given country if set. The country is considered to be set if not {@code null} and
- * not set to "none".
- *
- * @return the language and country represented as a locale, {@code null} if the
- * language is null or "none" (case insensitive)
- */
- public static Locale toLocale(String language, String country) {
- Locale locale = null;
- if (isDefined(language)) {
- if (isDefined(country)) {
- locale = new Locale(language, country);
- } else {
- locale = new Locale(language);
- }
- }
- return locale;
- }
-
- private static boolean isDefined(String property) {
- return !(property == null || property.equalsIgnoreCase("none"));
- }
-
- /** {@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 (this.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());
- this.hash = hash;
- }
- return this.hash;
- }
-
- }
|