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.

PropertyManager.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /*
  2. * $Id$
  3. * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
  4. * For details on use and redistribution please refer to the
  5. * LICENSE file included with these sources.
  6. */
  7. package org.apache.fop.fo;
  8. import java.awt.geom.Rectangle2D;
  9. import org.apache.fop.area.CTM;
  10. import org.apache.fop.datatypes.FODimension;
  11. import org.apache.fop.fo.TextInfo; // should be somewhere else probably...
  12. import org.apache.fop.layout.FontState;
  13. import org.apache.fop.layout.FontInfo;
  14. import org.apache.fop.layout.BorderAndPadding;
  15. import org.apache.fop.layout.MarginProps;
  16. import org.apache.fop.layout.MarginInlineProps;
  17. import org.apache.fop.layout.BackgroundProps;
  18. import org.apache.fop.layout.AccessibilityProps;
  19. import org.apache.fop.layout.AuralProps;
  20. import org.apache.fop.layout.RelativePositionProps;
  21. import org.apache.fop.layout.AbsolutePositionProps;
  22. import org.apache.fop.traits.BlockProps;
  23. import org.apache.fop.traits.InlineProps;
  24. import org.apache.fop.traits.SpaceVal;
  25. import org.apache.fop.traits.LayoutProps; // keep, break, span, space?
  26. import org.apache.fop.fo.properties.BreakAfter;
  27. import org.apache.fop.fo.properties.BreakBefore;
  28. import org.apache.fop.fo.properties.Constants;
  29. import org.apache.fop.fo.properties.WritingMode;
  30. import org.apache.fop.fo.properties.Span;
  31. import org.apache.fop.layout.HyphenationProps;
  32. import org.apache.fop.apps.FOPException;
  33. import java.text.MessageFormat;
  34. import java.text.FieldPosition;
  35. import org.apache.fop.layout.Area;
  36. import org.apache.fop.layout.ColumnArea;
  37. public class PropertyManager {
  38. private PropertyList properties;
  39. private FontInfo m_fontInfo = null;
  40. private FontState fontState = null;
  41. private BorderAndPadding borderAndPadding = null;
  42. private HyphenationProps hyphProps = null;
  43. private TextInfo textInfo = null;
  44. private static String[] saBefore = new String[] {"before"};
  45. private static String[] saAfter = new String[] {"after"};
  46. private static String[] saStart = new String[] {"start"};
  47. private static String[] saEnd = new String[] {"end"};
  48. private static MessageFormat msgColorFmt =
  49. new MessageFormat("border-{0}-color");
  50. private static MessageFormat msgStyleFmt =
  51. new MessageFormat("border-{0}-style");
  52. private static MessageFormat msgWidthFmt =
  53. new MessageFormat("border-{0}-width");
  54. private static MessageFormat msgPaddingFmt =
  55. new MessageFormat("padding-{0}");
  56. public PropertyManager(PropertyList pList) {
  57. this.properties = pList;
  58. }
  59. public void setFontInfo(FontInfo fontInfo) {
  60. m_fontInfo = fontInfo;
  61. }
  62. public FontState getFontState(FontInfo fontInfo) throws FOPException {
  63. if (fontState == null) {
  64. if (fontInfo == null) {
  65. fontInfo = m_fontInfo;
  66. }
  67. else if (m_fontInfo == null) {
  68. m_fontInfo = fontInfo;
  69. }
  70. String fontFamily = properties.get("font-family").getString();
  71. String fontStyle = properties.get("font-style").getString();
  72. String fontWeight = properties.get("font-weight").getString();
  73. // NOTE: this is incomplete. font-size may be specified with
  74. // various kinds of keywords too
  75. int fontSize = properties.get("font-size").getLength().mvalue();
  76. int fontVariant = properties.get("font-variant").getEnum();
  77. // fontInfo is same for the whole FOP run but set in all FontState
  78. fontState = new FontState(fontInfo, fontFamily, fontStyle,
  79. fontWeight, fontSize, fontVariant);
  80. }
  81. return fontState;
  82. }
  83. public BorderAndPadding getBorderAndPadding() {
  84. if (borderAndPadding == null) {
  85. this.borderAndPadding = new BorderAndPadding();
  86. initBorderInfo(BorderAndPadding.BEFORE, saBefore);
  87. initBorderInfo(BorderAndPadding.AFTER, saAfter);
  88. initBorderInfo(BorderAndPadding.START, saStart);
  89. initBorderInfo(BorderAndPadding.END, saEnd);
  90. }
  91. return borderAndPadding;
  92. }
  93. private void initBorderInfo(int whichSide, String[] saSide) {
  94. borderAndPadding.setPadding(whichSide,
  95. properties.get(msgPaddingFmt.format(saSide)).getCondLength());
  96. // If style = none, force width to 0, don't get Color
  97. int style = properties.get(msgStyleFmt.format(saSide)).getEnum();
  98. if (style != Constants.NONE) {
  99. borderAndPadding.setBorder(whichSide, style,
  100. properties.get(msgWidthFmt.format(saSide)).getCondLength(),
  101. properties.get(msgColorFmt.format(saSide)).getColorType());
  102. }
  103. }
  104. public HyphenationProps getHyphenationProps() {
  105. if (hyphProps == null) {
  106. this.hyphProps = new HyphenationProps();
  107. hyphProps.hyphenate = this.properties.get("hyphenate").getEnum();
  108. hyphProps.hyphenationChar =
  109. this.properties.get("hyphenation-character").getCharacter();
  110. hyphProps.hyphenationPushCharacterCount =
  111. this.properties.get("hyphenation-push-character-count").getNumber().intValue();
  112. hyphProps.hyphenationRemainCharacterCount =
  113. this.properties.get("hyphenation-remain-character-count").getNumber().intValue();
  114. hyphProps.language = this.properties.get("language").getString();
  115. hyphProps.country = this.properties.get("country").getString();
  116. }
  117. return hyphProps;
  118. }
  119. public int checkBreakBefore(Area area) {
  120. if (!(area instanceof ColumnArea)) {
  121. switch (properties.get("break-before").getEnum()) {
  122. case BreakBefore.PAGE:
  123. return Status.FORCE_PAGE_BREAK;
  124. case BreakBefore.ODD_PAGE:
  125. return Status.FORCE_PAGE_BREAK_ODD;
  126. case BreakBefore.EVEN_PAGE:
  127. return Status.FORCE_PAGE_BREAK_EVEN;
  128. case BreakBefore.COLUMN:
  129. return Status.FORCE_COLUMN_BREAK;
  130. default:
  131. return Status.OK;
  132. }
  133. } else {
  134. ColumnArea colArea = (ColumnArea)area;
  135. switch (properties.get("break-before").getEnum()) {
  136. case BreakBefore.PAGE:
  137. // if first ColumnArea, and empty, return OK
  138. if (!colArea.hasChildren() && (colArea.getColumnIndex() == 1))
  139. return Status.OK;
  140. else
  141. return Status.FORCE_PAGE_BREAK;
  142. case BreakBefore.ODD_PAGE:
  143. // if first ColumnArea, empty, _and_ in odd page,
  144. // return OK
  145. if (!colArea.hasChildren() && (colArea.getColumnIndex() == 1)
  146. && (colArea.getPage().getNumber() % 2 != 0))
  147. return Status.OK;
  148. else
  149. return Status.FORCE_PAGE_BREAK_ODD;
  150. case BreakBefore.EVEN_PAGE:
  151. // if first ColumnArea, empty, _and_ in even page,
  152. // return OK
  153. if (!colArea.hasChildren() && (colArea.getColumnIndex() == 1)
  154. && (colArea.getPage().getNumber() % 2 == 0))
  155. return Status.OK;
  156. else
  157. return Status.FORCE_PAGE_BREAK_EVEN;
  158. case BreakBefore.COLUMN:
  159. // if ColumnArea is empty return OK
  160. if (!area.hasChildren())
  161. return Status.OK;
  162. else
  163. return Status.FORCE_COLUMN_BREAK;
  164. default:
  165. return Status.OK;
  166. }
  167. }
  168. }
  169. public int checkBreakAfter(Area area) {
  170. switch (properties.get("break-after").getEnum()) {
  171. case BreakAfter.PAGE:
  172. return Status.FORCE_PAGE_BREAK;
  173. case BreakAfter.ODD_PAGE:
  174. return Status.FORCE_PAGE_BREAK_ODD;
  175. case BreakAfter.EVEN_PAGE:
  176. return Status.FORCE_PAGE_BREAK_EVEN;
  177. case BreakAfter.COLUMN:
  178. return Status.FORCE_COLUMN_BREAK;
  179. default:
  180. return Status.OK;
  181. }
  182. }
  183. public MarginProps getMarginProps() {
  184. MarginProps props = new MarginProps();
  185. // Common Margin Properties-Block
  186. props.marginTop =
  187. this.properties.get("margin-top").getLength().mvalue();
  188. props.marginBottom =
  189. this.properties.get("margin-bottom").getLength().mvalue();
  190. props.marginLeft =
  191. this.properties.get("margin-left").getLength().mvalue();
  192. props.marginRight =
  193. this.properties.get("margin-right").getLength().mvalue();
  194. // For now, we only get the optimum value for space-before and after
  195. props.spaceBefore = this.properties.get("space-before").getSpace().
  196. getOptimum().getLength().mvalue();
  197. props.spaceAfter = this.properties.get("space-after").getSpace().
  198. getOptimum().getLength().mvalue();
  199. props.startIndent = this.properties.get("start-indent").getLength().mvalue();
  200. props.endIndent = this.properties.get("end-indent").getLength().mvalue();
  201. return props;
  202. }
  203. public BackgroundProps getBackgroundProps() {
  204. BackgroundProps bp = new BackgroundProps();
  205. return bp;
  206. }
  207. public MarginInlineProps getMarginInlineProps() {
  208. MarginInlineProps props = new MarginInlineProps();
  209. return props;
  210. }
  211. public InlineProps getInlineProps() {
  212. InlineProps props = new InlineProps();
  213. props.spaceStart = new SpaceVal(properties.get("space-start").
  214. getSpace());
  215. props.spaceEnd = new SpaceVal(properties.get("space-end").
  216. getSpace());
  217. return props;
  218. }
  219. public AccessibilityProps getAccessibilityProps() {
  220. AccessibilityProps props = new AccessibilityProps();
  221. String str;
  222. str = this.properties.get("source-document").getString();
  223. if(!"none".equals(str)) {
  224. props.sourceDoc = str;
  225. }
  226. str = this.properties.get("role").getString();
  227. if(!"none".equals(str)) {
  228. props.role = str;
  229. }
  230. return props;
  231. }
  232. public AuralProps getAuralProps() {
  233. AuralProps props = new AuralProps();
  234. return props;
  235. }
  236. public RelativePositionProps getRelativePositionProps() {
  237. RelativePositionProps props = new RelativePositionProps();
  238. return props;
  239. }
  240. public AbsolutePositionProps getAbsolutePositionProps() {
  241. AbsolutePositionProps props = new AbsolutePositionProps();
  242. return props;
  243. }
  244. public BlockProps getBlockProps() {
  245. BlockProps props = new BlockProps();
  246. props.firstIndent = this.properties.get("text-indent").
  247. getLength().mvalue();
  248. props.lastIndent = 0; /*this.properties.get("last-line-end-indent").getLength().mvalue(); */
  249. props.textAlign = this.properties.get("text-align").getEnum();
  250. props.textAlignLast = this.properties.get("text-align-last").
  251. getEnum();
  252. props.lineStackType = this.properties.
  253. get("line-stacking-strategy").getEnum();
  254. return props;
  255. }
  256. public LayoutProps getLayoutProps() {
  257. LayoutProps props = new LayoutProps();
  258. props.breakBefore = this.properties.get("break-before").getEnum();
  259. props.breakAfter = this.properties.get("break-after").getEnum();
  260. props.bIsSpan = (this.properties.get("span").getEnum() == Span.ALL);
  261. props.spaceBefore = new SpaceVal(this.properties.get("space-before").
  262. getSpace());
  263. props.spaceAfter = new SpaceVal(this.properties.get("space-after").
  264. getSpace());
  265. return props;
  266. }
  267. public TextInfo getTextLayoutProps(FontInfo fontInfo) {
  268. if (textInfo == null) {
  269. textInfo = new TextInfo();
  270. try {
  271. textInfo.fs = getFontState(fontInfo);
  272. } catch (FOPException fopex) {
  273. /* log.error("Error setting FontState for characters: " +
  274. fopex.getMessage());*/
  275. // Now what should we do ???
  276. }
  277. textInfo.color = properties.get("color").getColorType();
  278. textInfo.verticalAlign =
  279. properties.get("vertical-align").getEnum();
  280. textInfo.wrapOption = properties.get("wrap-option").getEnum();
  281. textInfo.bWrap = (textInfo.wrapOption == Constants.WRAP);
  282. textInfo.wordSpacing =
  283. new SpaceVal(properties.get("word-spacing").getSpace());
  284. /* textInfo.letterSpacing =
  285. new SpaceVal(properties.get("letter-spacing").getSpace());*/
  286. textInfo.whiteSpaceCollapse =
  287. properties.get("white-space-collapse").getEnum();
  288. textInfo.lineHeight = this.properties.
  289. get("line-height").getLength().mvalue();
  290. }
  291. return textInfo;
  292. }
  293. public CTM getCTMandRelDims(Rectangle2D absVPrect, FODimension reldims) {
  294. int width, height;
  295. // We will use the absolute reference-orientation to set up the CTM.
  296. // The value here is relative to its ancestor reference area.
  297. int absRefOrient =
  298. getAbsRefOrient(this.properties.get("reference-orientation").
  299. getNumber().intValue());
  300. if (absRefOrient % 180 == 0) {
  301. width = (int)absVPrect.getWidth();
  302. height = (int)absVPrect.getHeight();
  303. }
  304. else {
  305. // invert width and height since top left are rotated by 90 (cl or ccl)
  306. height = (int)absVPrect.getWidth();
  307. width = (int)absVPrect.getHeight();
  308. }
  309. /* Set up the CTM for the content of this reference area. This will transform
  310. * region content coordinates in writing-mode relative into absolute page-relative
  311. * which will then be translated based on the position of the region viewport
  312. * (Note: scrolling between region vp and ref area when doing online content!)
  313. */
  314. CTM ctm = new CTM(absVPrect.getX(), absVPrect.getY());
  315. // First transform for rotation
  316. if (absRefOrient != 0) {
  317. // Rotation implies translation to keep the drawing area in the
  318. // first quadrant. Note: rotation is counter-clockwise
  319. switch (absRefOrient) {
  320. case 90:
  321. ctm = ctm.translate(0, width); // width = absVPrect.height
  322. break;
  323. case 180:
  324. ctm = ctm.translate(width, height);
  325. break;
  326. case 270:
  327. ctm = ctm.translate(height,0); // height = absVPrect.width
  328. break;
  329. }
  330. ctm = ctm.rotate(absRefOrient);
  331. }
  332. int wm = this.properties.get("writing-mode").getEnum();
  333. /* Since we've already put adjusted width and height values for the
  334. * top and left positions implied by the reference-orientation, we
  335. * can set ipd and bpd appropriately based on the writing mode.
  336. */
  337. if (wm == WritingMode.LR_TB || wm == WritingMode.RL_TB) {
  338. reldims.ipd = width;
  339. reldims.bpd = height;
  340. }
  341. else {
  342. reldims.ipd=height;
  343. reldims.bpd=width;
  344. }
  345. // Set a rectangle to be the writing-mode relative version???
  346. // Now transform for writing mode
  347. return ctm.multiply(CTM.getWMctm(wm, reldims.ipd, reldims.bpd));
  348. }
  349. /**
  350. * Calculate absolute reference-orientation relative to media orientation.
  351. */
  352. private int getAbsRefOrient(int myRefOrient) {
  353. return myRefOrient;
  354. }
  355. }