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

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