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.

CharacterLayoutManager.java 9.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  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.layoutmgr.inline;
  19. import java.util.LinkedList;
  20. import java.util.List;
  21. import org.apache.fop.area.Trait;
  22. import org.apache.fop.fo.flow.Character;
  23. import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
  24. import org.apache.fop.fonts.Font;
  25. import org.apache.fop.fonts.FontSelector;
  26. import org.apache.fop.layoutmgr.InlineKnuthSequence;
  27. import org.apache.fop.layoutmgr.KnuthElement;
  28. import org.apache.fop.layoutmgr.KnuthGlue;
  29. import org.apache.fop.layoutmgr.KnuthPenalty;
  30. import org.apache.fop.layoutmgr.KnuthSequence;
  31. import org.apache.fop.layoutmgr.LayoutContext;
  32. import org.apache.fop.layoutmgr.LeafPosition;
  33. import org.apache.fop.layoutmgr.Position;
  34. import org.apache.fop.layoutmgr.TraitSetter;
  35. import org.apache.fop.traits.MinOptMax;
  36. import org.apache.fop.traits.SpaceVal;
  37. import org.apache.fop.util.CharUtilities;
  38. /**
  39. * LayoutManager for the fo:character formatting object
  40. */
  41. public class CharacterLayoutManager extends LeafNodeLayoutManager {
  42. private MinOptMax letterSpaceIPD;
  43. private int hyphIPD;
  44. private Font font;
  45. private CommonBorderPaddingBackground borderProps = null;
  46. /**
  47. * Constructor
  48. *
  49. * @param node the fo:character formatting object
  50. */
  51. public CharacterLayoutManager(Character node) {
  52. super(node);
  53. }
  54. /** {@inheritDoc} */
  55. public void initialize() {
  56. Character fobj = (Character)this.fobj;
  57. font = FontSelector.selectFontForCharacter(fobj, this);
  58. SpaceVal ls = SpaceVal.makeLetterSpacing(fobj.getLetterSpacing());
  59. letterSpaceIPD = ls.getSpace();
  60. hyphIPD = fobj.getCommonHyphenation().getHyphIPD(font);
  61. borderProps = fobj.getCommonBorderPaddingBackground();
  62. setCommonBorderPaddingBackground(borderProps);
  63. org.apache.fop.area.inline.TextArea chArea = getCharacterInlineArea(fobj);
  64. chArea.setBaselineOffset(font.getAscender());
  65. setCurrentArea(chArea);
  66. }
  67. private org.apache.fop.area.inline.TextArea getCharacterInlineArea(Character node) {
  68. org.apache.fop.area.inline.TextArea text
  69. = new org.apache.fop.area.inline.TextArea();
  70. char ch = node.getCharacter();
  71. if (CharUtilities.isAnySpace(ch)) {
  72. // add space unless it's zero-width:
  73. if (!CharUtilities.isZeroWidthSpace(ch)) {
  74. text.addSpace(ch, 0, CharUtilities.isAdjustableSpace(ch));
  75. }
  76. } else {
  77. text.addWord(String.valueOf(ch), 0);
  78. }
  79. TraitSetter.setProducerID(text, node.getId());
  80. TraitSetter.addTextDecoration(text, node.getTextDecoration());
  81. TraitSetter.addPtr(text, node.getPtr()); // used for accessibility
  82. return text;
  83. }
  84. /** {@inheritDoc} */
  85. public List getNextKnuthElements(LayoutContext context, int alignment) {
  86. MinOptMax ipd;
  87. curArea = get(context);
  88. KnuthSequence seq = new InlineKnuthSequence();
  89. if (curArea == null) {
  90. setFinished(true);
  91. return null;
  92. }
  93. Character fobj = (Character)this.fobj;
  94. ipd = new MinOptMax(font.getCharWidth(fobj.getCharacter()));
  95. curArea.setIPD(ipd.opt);
  96. curArea.setBPD(font.getAscender() - font.getDescender());
  97. TraitSetter.addFontTraits(curArea, font);
  98. curArea.addTrait(Trait.COLOR, fobj.getColor());
  99. // TODO: may need some special handling for fo:character
  100. alignmentContext = new AlignmentContext(font
  101. , font.getFontSize()
  102. , fobj.getAlignmentAdjust()
  103. , fobj.getAlignmentBaseline()
  104. , fobj.getBaselineShift()
  105. , fobj.getDominantBaseline()
  106. , context.getAlignmentContext());
  107. addKnuthElementsForBorderPaddingStart(seq);
  108. // create the AreaInfo object to store the computed values
  109. areaInfo = new AreaInfo((short) 0, ipd, false, alignmentContext);
  110. // node is a fo:Character
  111. if (letterSpaceIPD.min == letterSpaceIPD.max) {
  112. // constant letter space, only return a box
  113. seq.add(new KnuthInlineBox(areaInfo.ipdArea.opt, areaInfo.alignmentContext,
  114. notifyPos(new LeafPosition(this, 0)), false));
  115. } else {
  116. // adjustable letter space, return a sequence of elements;
  117. // at the moment the character is supposed to have no letter spaces,
  118. // but returning this sequence allows us to change only one element
  119. // if addALetterSpaceTo() is called
  120. seq.add(new KnuthInlineBox(areaInfo.ipdArea.opt, areaInfo.alignmentContext,
  121. notifyPos(new LeafPosition(this, 0)), false));
  122. seq.add(new KnuthPenalty(0, KnuthElement.INFINITE, false,
  123. new LeafPosition(this, -1), true));
  124. seq.add(new KnuthGlue(0, 0, 0,
  125. new LeafPosition(this, -1), true));
  126. seq.add(new KnuthInlineBox(0, null,
  127. notifyPos(new LeafPosition(this, -1)), true));
  128. }
  129. addKnuthElementsForBorderPaddingEnd(seq);
  130. LinkedList returnList = new LinkedList();
  131. returnList.add(seq);
  132. setFinished(true);
  133. return returnList;
  134. }
  135. /** {@inheritDoc} */
  136. public void getWordChars(StringBuffer sbChars, Position bp) {
  137. sbChars.append
  138. (((org.apache.fop.area.inline.TextArea) curArea).getText());
  139. }
  140. /** {@inheritDoc} */
  141. public void hyphenate(Position pos, HyphContext hc) {
  142. if (hc.getNextHyphPoint() == 1) {
  143. // the character ends a syllable
  144. areaInfo.bHyphenated = true;
  145. isSomethingChanged = true;
  146. } else {
  147. // hc.getNextHyphPoint() returned -1 (no more hyphenation points)
  148. // or a number > 1;
  149. // the character does not end a syllable
  150. }
  151. hc.updateOffset(1);
  152. }
  153. /** {@inheritDoc} */
  154. public boolean applyChanges(List oldList) {
  155. setFinished(false);
  156. return isSomethingChanged;
  157. }
  158. /** {@inheritDoc} */
  159. public List getChangedKnuthElements(List oldList, int alignment) {
  160. if (isFinished()) {
  161. return null;
  162. }
  163. LinkedList returnList = new LinkedList();
  164. addKnuthElementsForBorderPaddingStart(returnList);
  165. if (letterSpaceIPD.min == letterSpaceIPD.max
  166. || areaInfo.iLScount == 0) {
  167. // constant letter space, or no letter space
  168. returnList.add(new KnuthInlineBox(areaInfo.ipdArea.opt,
  169. areaInfo.alignmentContext,
  170. notifyPos(new LeafPosition(this, 0)), false));
  171. if (areaInfo.bHyphenated) {
  172. returnList.add
  173. (new KnuthPenalty(hyphIPD, KnuthPenalty.FLAGGED_PENALTY, true,
  174. new LeafPosition(this, -1), false));
  175. }
  176. } else {
  177. // adjustable letter space
  178. returnList.add
  179. (new KnuthInlineBox(areaInfo.ipdArea.opt
  180. - areaInfo.iLScount * letterSpaceIPD.opt,
  181. areaInfo.alignmentContext,
  182. notifyPos(new LeafPosition(this, 0)), false));
  183. returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false,
  184. new LeafPosition(this, -1), true));
  185. returnList.add
  186. (new KnuthGlue(areaInfo.iLScount * letterSpaceIPD.opt,
  187. areaInfo.iLScount * letterSpaceIPD.max - letterSpaceIPD.opt,
  188. areaInfo.iLScount * letterSpaceIPD.opt - letterSpaceIPD.min,
  189. new LeafPosition(this, -1), true));
  190. returnList.add(new KnuthInlineBox(0, null,
  191. notifyPos(new LeafPosition(this, -1)), true));
  192. if (areaInfo.bHyphenated) {
  193. returnList.add
  194. (new KnuthPenalty(hyphIPD, KnuthPenalty.FLAGGED_PENALTY, true,
  195. new LeafPosition(this, -1), false));
  196. }
  197. }
  198. addKnuthElementsForBorderPaddingEnd(returnList);
  199. setFinished(true);
  200. return returnList;
  201. }
  202. }