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.

InlineArea.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  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.area.inline;
  19. import java.io.Serializable;
  20. import java.util.List;
  21. import org.apache.fop.area.Area;
  22. import org.apache.fop.area.LineArea;
  23. import org.apache.fop.area.Trait;
  24. import org.apache.fop.complexscripts.bidi.InlineRun;
  25. /**
  26. * Inline Area
  27. * This area is for all inline areas that can be placed
  28. * in a line area.
  29. */
  30. public class InlineArea extends Area {
  31. private static final long serialVersionUID = -8940066479810170980L;
  32. /**
  33. * this class stores information about potential adjustments
  34. * that can be used in order to re-compute adjustments when a
  35. * page-number or a page-number-citation is resolved
  36. */
  37. protected class InlineAdjustingInfo implements Serializable {
  38. private static final long serialVersionUID = -5601387735459712149L;
  39. /** stretch of the inline area */
  40. protected int availableStretch;
  41. /** shrink of the inline area */
  42. protected int availableShrink;
  43. /** total adjustment (= ipd - width of fixed elements) */
  44. protected int adjustment;
  45. /**
  46. * Constructor
  47. *
  48. * @param stretch the available space for stretching
  49. * @param shrink the available space for shrinking
  50. * @param adj space adjustment type
  51. */
  52. protected InlineAdjustingInfo(int stretch, int shrink, int adj) {
  53. availableStretch = stretch;
  54. availableShrink = shrink;
  55. adjustment = adj;
  56. }
  57. /**
  58. * Apply the variation factor
  59. *
  60. * @param variationFactor the factor by which the adjustment is to be changed
  61. * @return the IPD increase
  62. */
  63. protected int applyVariationFactor(double variationFactor) {
  64. int oldAdjustment = adjustment;
  65. adjustment *= variationFactor;
  66. return adjustment - oldAdjustment;
  67. }
  68. }
  69. /**
  70. * offset position from before edge of parent area
  71. */
  72. protected int blockProgressionOffset;
  73. /**
  74. * parent area
  75. * it is needed in order to recompute adjust ratio and indents
  76. * when a page-number or a page-number-citation is resolved
  77. */
  78. private Area parentArea;
  79. /**
  80. * ipd variation of child areas: if this area has not already
  81. * been added and cannot notify its parent area, store the variation
  82. * and wait for the parent area to be set
  83. */
  84. private int storedIPDVariation;
  85. /**
  86. * The adjustment information object
  87. */
  88. protected InlineAdjustingInfo adjustingInfo;
  89. /**
  90. * Default constructor for inline area.
  91. */
  92. public InlineArea() {
  93. this (0, -1);
  94. }
  95. /**
  96. * Instantiate inline area.
  97. * @param blockProgressionOffset a block progression offset or zero
  98. * @param bidiLevel a resolved bidi level or -1
  99. */
  100. protected InlineArea(int blockProgressionOffset, int bidiLevel) {
  101. this.blockProgressionOffset = blockProgressionOffset;
  102. setBidiLevel(bidiLevel);
  103. }
  104. /**
  105. * @return the adjustment information object
  106. */
  107. public InlineAdjustingInfo getAdjustingInfo() {
  108. return adjustingInfo;
  109. }
  110. /**
  111. * Create a new adjustment information object
  112. * @param stretch the available space for stretching
  113. * @param shrink the available space for shrinking
  114. * @param adjustment space adjustment type
  115. */
  116. public void setAdjustingInfo(int stretch, int shrink, int adjustment) {
  117. adjustingInfo = new InlineAdjustingInfo(stretch, shrink, adjustment);
  118. }
  119. /**
  120. * Sets the adjustment information from an existing object
  121. * @param adjustingInfo the existing adjustment object
  122. */
  123. public void setAdjustingInfo(InlineAdjustingInfo adjustingInfo) {
  124. this.adjustingInfo = adjustingInfo;
  125. }
  126. /**
  127. * Modify the adjustment value in the adjustment information object
  128. * @param adjustment the new adjustment value
  129. */
  130. public void setAdjustment(int adjustment) {
  131. if (adjustingInfo != null) {
  132. adjustingInfo.adjustment = adjustment;
  133. }
  134. }
  135. /**
  136. * Increase the inline progression dimensions of this area.
  137. * This is used for inline parent areas that contain mulitple child areas.
  138. *
  139. * @param ipd the inline progression to increase by
  140. */
  141. public void increaseIPD(int ipd) {
  142. this.ipd += ipd;
  143. }
  144. /**
  145. * Set the block progression offset of this inline area.
  146. * This is used to set the offset of the inline area
  147. * which is relative to the before edge of the parent area.
  148. *
  149. * @param blockProgressionOffset the offset
  150. */
  151. public void setBlockProgressionOffset(int blockProgressionOffset) {
  152. this.blockProgressionOffset = blockProgressionOffset;
  153. }
  154. /**
  155. * Get the block progression offset of this inline area.
  156. * This returns the offset of the inline area
  157. * relative to the before edge of the parent area.
  158. *
  159. * @return the blockProgressionOffset
  160. */
  161. public int getBlockProgressionOffset() {
  162. return blockProgressionOffset;
  163. }
  164. /**
  165. * @param parentArea The parentArea to set.
  166. */
  167. public void setParentArea(Area parentArea) {
  168. this.parentArea = parentArea;
  169. }
  170. /**
  171. * @return Returns the parentArea.
  172. */
  173. public Area getParentArea() {
  174. return parentArea;
  175. }
  176. /**
  177. * Set the parent for the child area.
  178. *
  179. * {@inheritDoc}
  180. */
  181. @Override
  182. public void addChildArea(Area childArea) {
  183. super.addChildArea(childArea);
  184. if (childArea instanceof InlineArea) {
  185. ((InlineArea) childArea).setParentArea(this);
  186. }
  187. }
  188. /** @return true if the inline area is underlined. */
  189. public boolean hasUnderline() {
  190. return getTraitAsBoolean(Trait.UNDERLINE);
  191. }
  192. /** @return true if the inline area is overlined. */
  193. public boolean hasOverline() {
  194. return getTraitAsBoolean(Trait.OVERLINE);
  195. }
  196. /** @return true if the inline area has a line through. */
  197. public boolean hasLineThrough() {
  198. return getTraitAsBoolean(Trait.LINETHROUGH);
  199. }
  200. /** @return true if the inline area is blinking. */
  201. public boolean isBlinking() {
  202. return getTraitAsBoolean(Trait.BLINK);
  203. }
  204. /**
  205. * recursively apply the variation factor to all descendant areas
  206. * @param variationFactor the variation factor that must be applied to adjustments
  207. * @param lineStretch the total stretch of the line
  208. * @param lineShrink the total shrink of the line
  209. * @return true if there is an UnresolvedArea descendant
  210. */
  211. public boolean applyVariationFactor(double variationFactor,
  212. int lineStretch, int lineShrink) {
  213. // default behaviour: update the IPD and return false
  214. if (adjustingInfo != null) {
  215. setIPD(getIPD() + adjustingInfo.applyVariationFactor(variationFactor));
  216. }
  217. return false;
  218. }
  219. /**
  220. * Apply IPD variation.
  221. * @param ipdVariation the variation
  222. */
  223. public void handleIPDVariation(int ipdVariation) {
  224. if (log.isTraceEnabled()) {
  225. log.trace("Handling IPD variation for " + getClass().getSimpleName()
  226. + ": increase by " + ipdVariation + " mpt.");
  227. }
  228. increaseIPD(ipdVariation);
  229. notifyIPDVariation(ipdVariation);
  230. }
  231. /**
  232. * notify the parent area about the ipd variation of this area
  233. * or of a descendant area
  234. * @param ipdVariation the difference between new and old ipd
  235. */
  236. protected void notifyIPDVariation(int ipdVariation) {
  237. if (getParentArea() instanceof InlineArea) {
  238. ((InlineArea) getParentArea()).handleIPDVariation(ipdVariation);
  239. } else if (getParentArea() instanceof LineArea) {
  240. ((LineArea) getParentArea()).handleIPDVariation(ipdVariation);
  241. } else if (getParentArea() == null) {
  242. // parent area not yet set: store the variations
  243. storedIPDVariation += ipdVariation;
  244. }
  245. }
  246. /**
  247. * Returns the offset that this area would have if its offset and size were taking
  248. * children areas into account. The bpd of an inline area is taken from its nominal
  249. * font and doesn't depend on the bpds of its children elements. However, in the case
  250. * of a basic-link element we want the active area to cover all of the children
  251. * elements.
  252. *
  253. * @return the offset that this area would have if the before-edge of its
  254. * content-rectangle were coinciding with the <q>beforest</q> before-edge of its
  255. * children allocation-rectangles.
  256. * @see #getVirtualBPD()
  257. * @see BasicLinkArea
  258. */
  259. int getVirtualOffset() {
  260. return getBlockProgressionOffset();
  261. }
  262. /**
  263. * Returns the block-progression-dimension that this area would have if it were taking
  264. * its children elements into account. See {@linkplain #getVirtualOffset()}.
  265. *
  266. * @return the bpd
  267. */
  268. int getVirtualBPD() {
  269. return getBPD();
  270. }
  271. /**
  272. * Collection bidi inline runs.
  273. * @param runs current list of inline runs
  274. * @return modified list of inline runs, having appended new run
  275. */
  276. public List collectInlineRuns(List runs) {
  277. assert runs != null;
  278. runs.add(new InlineRun(this, new int[] {getBidiLevel()}));
  279. return runs;
  280. }
  281. /**
  282. * Determine if inline area IA is an ancestor inline area or same as this area.
  283. * @param ia inline area to test
  284. * @return true if specified inline area is an ancestor or same as this area
  285. */
  286. public boolean isAncestorOrSelf(InlineArea ia) {
  287. return (ia == this) || isAncestor(ia);
  288. }
  289. /**
  290. * Determine if inline area IA is an ancestor inline area of this area.
  291. * @param ia inline area to test
  292. * @return true if specified inline area is an ancestor of this area
  293. */
  294. public boolean isAncestor(InlineArea ia) {
  295. for (Area p = getParentArea(); p != null;) {
  296. if (p == ia) {
  297. return true;
  298. } else if (p instanceof InlineArea) {
  299. p = ((InlineArea) p).getParentArea();
  300. } else {
  301. p = null;
  302. }
  303. }
  304. return false;
  305. }
  306. }