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.

FontShorthandProperty.java 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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.fop.fo.Constants;
  20. import org.apache.fop.fo.FObj;
  21. import org.apache.fop.fo.PropertyList;
  22. import org.apache.fop.fo.expr.PropertyException;
  23. /**
  24. * Property subclass for the font shorthand
  25. */
  26. public class FontShorthandProperty extends ListProperty {
  27. /**
  28. * Inner class for creating instances of FontShorthandProperty
  29. */
  30. public static class Maker extends PropertyMaker {
  31. private static final int[] PROP_IDS = {
  32. Constants.PR_FONT_SIZE, Constants.PR_FONT_FAMILY,
  33. Constants.PR_LINE_HEIGHT, Constants.PR_FONT_STYLE,
  34. Constants.PR_FONT_VARIANT, Constants.PR_FONT_WEIGHT
  35. };
  36. /**
  37. * @param propId ID of the property for which Maker should be created
  38. */
  39. public Maker(int propId) {
  40. super(propId);
  41. }
  42. /**
  43. * {@inheritDoc}
  44. */
  45. public Property make(PropertyList propertyList,
  46. String value, FObj fo) throws PropertyException {
  47. try {
  48. FontShorthandProperty newProp = new FontShorthandProperty();
  49. newProp.setSpecifiedValue(value);
  50. String specVal = value;
  51. Property prop = null;
  52. if ("inherit".equals(specVal)) {
  53. /* fill the list with the individual properties from the parent */
  54. for (int i = PROP_IDS.length; --i >= 0;) {
  55. prop = propertyList.getFromParent(PROP_IDS[i]);
  56. newProp.addProperty(prop, i);
  57. }
  58. } else {
  59. /* initialize list with nulls */
  60. for (int pos = PROP_IDS.length; --pos >= 0;) {
  61. newProp.addProperty(null, pos);
  62. }
  63. prop = checkEnumValues(specVal);
  64. if (prop == null) {
  65. /* not an enum:
  66. * value should consist at least of font-size and font-family
  67. * separated by a space
  68. * mind the possible spaces from quoted font-family names
  69. */
  70. int spaceIndex = value.indexOf(' ');
  71. int quoteIndex = (value.indexOf('\'') == -1)
  72. ? value.indexOf('\"') : value.indexOf('\'');
  73. if (spaceIndex == -1
  74. || (quoteIndex != -1 && spaceIndex > quoteIndex)) {
  75. /* no spaces or first space appears after the first
  76. * single/double quote, so malformed value string
  77. */
  78. throw new PropertyException("Invalid property value: "
  79. + "font=\"" + value + "\"");
  80. }
  81. PropertyMaker m = null;
  82. int fromIndex = spaceIndex + 1;
  83. int toIndex = specVal.length();
  84. /* at least one space that appears before the first
  85. * single/double quote, so extract the individual properties
  86. */
  87. boolean fontFamilyParsed = false;
  88. int commaIndex = value.indexOf(',');
  89. while (!fontFamilyParsed) {
  90. /* value contains a (list of) possibly quoted
  91. * font-family name(s)
  92. */
  93. if (commaIndex == -1) {
  94. /* no list, just a single name
  95. * (or first name in the list)
  96. */
  97. if (quoteIndex != -1) {
  98. /* a single name, quoted
  99. */
  100. fromIndex = quoteIndex;
  101. }
  102. m = FObj.getPropertyMakerFor(PROP_IDS[1]);
  103. prop = m.make(propertyList, specVal.substring(fromIndex), fo);
  104. newProp.addProperty(prop, 1);
  105. fontFamilyParsed = true;
  106. } else {
  107. if (quoteIndex != -1 && quoteIndex < commaIndex) {
  108. /* a quoted font-family name as first name
  109. * in the comma-separated list
  110. * fromIndex = index of the first quote
  111. */
  112. fromIndex = quoteIndex;
  113. quoteIndex = -1;
  114. } else {
  115. fromIndex = value.lastIndexOf(' ', commaIndex) + 1;
  116. }
  117. commaIndex = -1;
  118. }
  119. }
  120. toIndex = fromIndex - 1;
  121. fromIndex = value.lastIndexOf(' ', toIndex - 1) + 1;
  122. value = specVal.substring(fromIndex, toIndex);
  123. int slashIndex = value.indexOf('/');
  124. String fontSize = value.substring(0,
  125. (slashIndex == -1) ? value.length() : slashIndex);
  126. m = FObj.getPropertyMakerFor(PROP_IDS[0]);
  127. prop = m.make(propertyList, fontSize, fo);
  128. /* need to make sure subsequent call to LineHeightPropertyMaker.make()
  129. * doesn't generate the default font-size property...
  130. */
  131. propertyList.putExplicit(PROP_IDS[0], prop);
  132. newProp.addProperty(prop, 0);
  133. if (slashIndex != -1) {
  134. /* line-height */
  135. String lineHeight = value.substring(slashIndex + 1);
  136. m = FObj.getPropertyMakerFor(PROP_IDS[2]);
  137. prop = m.make(propertyList, lineHeight, fo);
  138. newProp.addProperty(prop, 2);
  139. }
  140. if (fromIndex != 0) {
  141. toIndex = fromIndex - 1;
  142. value = specVal.substring(0, toIndex);
  143. fromIndex = 0;
  144. spaceIndex = value.indexOf(' ');
  145. do {
  146. toIndex = (spaceIndex == -1) ? value.length() : spaceIndex;
  147. String val = value.substring(fromIndex, toIndex);
  148. for (int i = 6; --i >= 3;) {
  149. if (newProp.list.get(i) == null) {
  150. /* not set */
  151. m = FObj.getPropertyMakerFor(PROP_IDS[i]);
  152. val = m.checkValueKeywords(val);
  153. prop = m.checkEnumValues(val);
  154. if (prop != null) {
  155. newProp.addProperty(prop, i);
  156. }
  157. }
  158. }
  159. fromIndex = toIndex + 1;
  160. spaceIndex = value.indexOf(' ', fromIndex);
  161. } while (toIndex != value.length());
  162. }
  163. } else {
  164. //TODO: implement enum values
  165. log.warn("Enum values other than \"inherit\""
  166. + " not yet supported for the font shorthand.");
  167. return null;
  168. }
  169. }
  170. if (newProp.list.get(0) == null || newProp.list.get(1) == null) {
  171. throw new PropertyException("Invalid property value: "
  172. + "font-size and font-family are required for the font shorthand"
  173. + "\nfont=\"" + value + "\"");
  174. }
  175. return newProp;
  176. } catch (PropertyException pe) {
  177. pe.setLocator(propertyList.getFObj().getLocator());
  178. pe.setPropertyName(getName());
  179. throw pe;
  180. }
  181. }
  182. }
  183. private void addProperty(Property prop, int pos) {
  184. while (list.size() < (pos + 1)) {
  185. list.add(null);
  186. }
  187. list.set(pos, prop);
  188. }
  189. }