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.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. * Copyright 1999-2006 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /* $Id$ */
  17. package org.apache.fop.layoutmgr.inline;
  18. import org.apache.fop.fo.flow.Character;
  19. import org.apache.fop.fonts.Font;
  20. import org.apache.fop.layoutmgr.InlineKnuthSequence;
  21. import org.apache.fop.layoutmgr.KnuthElement;
  22. import org.apache.fop.layoutmgr.KnuthGlue;
  23. import org.apache.fop.layoutmgr.KnuthPenalty;
  24. import org.apache.fop.layoutmgr.KnuthSequence;
  25. import org.apache.fop.layoutmgr.LayoutContext;
  26. import org.apache.fop.layoutmgr.LeafPosition;
  27. import org.apache.fop.layoutmgr.Position;
  28. import org.apache.fop.layoutmgr.TraitSetter;
  29. import org.apache.fop.area.Trait;
  30. import org.apache.fop.traits.MinOptMax;
  31. import org.apache.fop.traits.SpaceVal;
  32. import java.util.List;
  33. import java.util.LinkedList;
  34. import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
  35. import org.apache.fop.layoutmgr.inline.AlignmentContext;
  36. /**
  37. * LayoutManager for the fo:character formatting object
  38. */
  39. public class CharacterLayoutManager extends LeafNodeLayoutManager {
  40. private Character fobj;
  41. private MinOptMax letterSpaceIPD;
  42. private int hyphIPD;
  43. private Font font;
  44. private CommonBorderPaddingBackground borderProps = null;
  45. /**
  46. * Constructor
  47. *
  48. * @param node the fo:character formatting object
  49. */
  50. public CharacterLayoutManager(Character node) {
  51. // @todo better null checking of node
  52. super(node);
  53. fobj = node;
  54. }
  55. /** @see org.apache.fop.layoutmgr.LayoutManager#initialize */
  56. public void initialize() {
  57. font = fobj.getCommonFont().getFontState(fobj.getFOEventHandler().getFontInfo(), this);
  58. SpaceVal ls = SpaceVal.makeLetterSpacing(fobj.getLetterSpacing());
  59. letterSpaceIPD = ls.getSpace();
  60. hyphIPD = font.getCharWidth(fobj.getCommonHyphenation().hyphenationCharacter);
  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 ch
  69. = new org.apache.fop.area.inline.TextArea();
  70. ch.addWord(String.valueOf(node.getCharacter()), 0);
  71. TraitSetter.setProducerID(ch, node.getId());
  72. TraitSetter.addTextDecoration(ch, fobj.getTextDecoration());
  73. return ch;
  74. }
  75. /** @see org.apache.fop.layoutmgr.LayoutManager#getNextKnuthElements(LayoutContext, int) */
  76. public LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
  77. MinOptMax ipd;
  78. curArea = get(context);
  79. KnuthSequence seq = new InlineKnuthSequence();
  80. if (curArea == null) {
  81. setFinished(true);
  82. return null;
  83. }
  84. ipd = new MinOptMax(font.getCharWidth(fobj.getCharacter()));
  85. curArea.setIPD(ipd.opt);
  86. curArea.setBPD(font.getAscender() - font.getDescender());
  87. TraitSetter.addFontTraits(curArea, font);
  88. curArea.addTrait(Trait.COLOR, fobj.getColor());
  89. // TODO: may need some special handling for fo:character
  90. alignmentContext = new AlignmentContext(font
  91. , font.getFontSize()
  92. , fobj.getAlignmentAdjust()
  93. , fobj.getAlignmentBaseline()
  94. , fobj.getBaselineShift()
  95. , fobj.getDominantBaseline()
  96. , context.getAlignmentContext());
  97. addKnuthElementsForBorderPaddingStart(seq);
  98. // create the AreaInfo object to store the computed values
  99. areaInfo = new AreaInfo((short) 0, ipd, false, alignmentContext);
  100. // node is a fo:Character
  101. if (letterSpaceIPD.min == letterSpaceIPD.max) {
  102. // constant letter space, only return a box
  103. seq.add(new KnuthInlineBox(areaInfo.ipdArea.opt, areaInfo.alignmentContext,
  104. notifyPos(new LeafPosition(this, 0)), false));
  105. } else {
  106. // adjustable letter space, return a sequence of elements;
  107. // at the moment the character is supposed to have no letter spaces,
  108. // but returning this sequence allows us to change only one element
  109. // if addALetterSpaceTo() is called
  110. seq.add(new KnuthInlineBox(areaInfo.ipdArea.opt, areaInfo.alignmentContext,
  111. notifyPos(new LeafPosition(this, 0)), false));
  112. seq.add(new KnuthPenalty(0, KnuthElement.INFINITE, false,
  113. new LeafPosition(this, -1), true));
  114. seq.add(new KnuthGlue(0, 0, 0,
  115. new LeafPosition(this, -1), true));
  116. seq.add(new KnuthInlineBox(0, null,
  117. notifyPos(new LeafPosition(this, -1)), true));
  118. }
  119. addKnuthElementsForBorderPaddingEnd(seq);
  120. LinkedList returnList = new LinkedList();
  121. returnList.add(seq);
  122. setFinished(true);
  123. return returnList;
  124. }
  125. /** @see InlineLevelLayoutManager#getWordChars(StringBuffer, Position) */
  126. public void getWordChars(StringBuffer sbChars, Position bp) {
  127. sbChars.append
  128. (((org.apache.fop.area.inline.TextArea) curArea).getText());
  129. }
  130. /** @see InlineLevelLayoutManager#hyphenate(Position, HyphContext) */
  131. public void hyphenate(Position pos, HyphContext hc) {
  132. if (hc.getNextHyphPoint() == 1) {
  133. // the character ends a syllable
  134. areaInfo.bHyphenated = true;
  135. isSomethingChanged = true;
  136. } else {
  137. // hc.getNextHyphPoint() returned -1 (no more hyphenation points)
  138. // or a number > 1;
  139. // the character does not end a syllable
  140. }
  141. hc.updateOffset(1);
  142. }
  143. /** @see InlineLevelLayoutManager#applyChanges(List) */
  144. public boolean applyChanges(List oldList) {
  145. setFinished(false);
  146. if (isSomethingChanged) {
  147. // there is nothing to do,
  148. // possible changes have already been applied
  149. // in the hyphenate() method
  150. return true;
  151. } else {
  152. return false;
  153. }
  154. }
  155. /** @see org.apache.fop.layoutmgr.LayoutManager#getChangedKnuthElements(List, int) */
  156. public LinkedList getChangedKnuthElements(List oldList, int alignment) {
  157. if (isFinished()) {
  158. return null;
  159. }
  160. LinkedList returnList = new LinkedList();
  161. addKnuthElementsForBorderPaddingStart(returnList);
  162. if (letterSpaceIPD.min == letterSpaceIPD.max
  163. || areaInfo.iLScount == 0) {
  164. // constant letter space, or no letter space
  165. returnList.add(new KnuthInlineBox(areaInfo.ipdArea.opt,
  166. areaInfo.alignmentContext,
  167. notifyPos(new LeafPosition(this, 0)), false));
  168. if (areaInfo.bHyphenated) {
  169. returnList.add
  170. (new KnuthPenalty(hyphIPD, KnuthPenalty.FLAGGED_PENALTY, true,
  171. new LeafPosition(this, -1), false));
  172. }
  173. } else {
  174. // adjustable letter space
  175. returnList.add
  176. (new KnuthInlineBox(areaInfo.ipdArea.opt
  177. - areaInfo.iLScount * letterSpaceIPD.opt,
  178. areaInfo.alignmentContext,
  179. notifyPos(new LeafPosition(this, 0)), false));
  180. returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false,
  181. new LeafPosition(this, -1), true));
  182. returnList.add
  183. (new KnuthGlue(areaInfo.iLScount * letterSpaceIPD.opt,
  184. areaInfo.iLScount * letterSpaceIPD.max - letterSpaceIPD.opt,
  185. areaInfo.iLScount * letterSpaceIPD.opt - letterSpaceIPD.min,
  186. new LeafPosition(this, -1), true));
  187. returnList.add(new KnuthInlineBox(0, null,
  188. notifyPos(new LeafPosition(this, -1)), true));
  189. if (areaInfo.bHyphenated) {
  190. returnList.add
  191. (new KnuthPenalty(hyphIPD, KnuthPenalty.FLAGGED_PENALTY, true,
  192. new LeafPosition(this, -1), false));
  193. }
  194. }
  195. addKnuthElementsForBorderPaddingEnd(returnList);
  196. setFinished(true);
  197. return returnList;
  198. }
  199. /** @see LeafNodeLayoutManager#addId */
  200. protected void addId() {
  201. getPSLM().addIDToPage(fobj.getId());
  202. }
  203. }