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 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /*
  2. * Copyright 1999-2004 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.fo;
  18. // FOP
  19. import org.apache.fop.fonts.Font;
  20. import org.apache.fop.fo.properties.Property;
  21. import org.apache.fop.fo.properties.CommonBorderAndPadding;
  22. import org.apache.fop.fo.properties.CommonMarginBlock;
  23. import org.apache.fop.fo.properties.CommonMarginInline;
  24. import org.apache.fop.fo.properties.CommonBackground;
  25. import org.apache.fop.fo.properties.CommonAccessibility;
  26. import org.apache.fop.fo.properties.CommonAural;
  27. import org.apache.fop.fo.properties.CommonRelativePosition;
  28. import org.apache.fop.fo.properties.CommonAbsolutePosition;
  29. import org.apache.fop.traits.BlockProps;
  30. import org.apache.fop.traits.InlineProps;
  31. import org.apache.fop.traits.SpaceVal;
  32. import org.apache.fop.traits.LayoutProps; // keep, break, span, space?
  33. import org.apache.fop.fonts.FontMetrics;
  34. import org.apache.fop.fo.properties.CommonHyphenation;
  35. /**
  36. * Helper class for managing groups of properties.
  37. */
  38. public class PropertyManager implements Constants {
  39. private PropertyList propertyList;
  40. private FOTreeControl foTreeControl = null;
  41. private Font fontState = null;
  42. private CommonBorderAndPadding borderAndPadding = null;
  43. private CommonHyphenation hyphProps = null;
  44. private TextInfo textInfo = null;
  45. private static final int[] SA_BEFORE = new int[] {
  46. PR_BORDER_BEFORE_COLOR, PR_BORDER_BEFORE_STYLE, PR_BORDER_BEFORE_WIDTH, PR_PADDING_BEFORE};
  47. private static final int[] SA_AFTER = new int[]{
  48. PR_BORDER_AFTER_COLOR, PR_BORDER_AFTER_STYLE, PR_BORDER_AFTER_WIDTH, PR_PADDING_AFTER};
  49. private static final int[] SA_START = new int[]{
  50. PR_BORDER_START_COLOR, PR_BORDER_START_STYLE, PR_BORDER_START_WIDTH, PR_PADDING_START};
  51. private static final int[] SA_END = new int[]{
  52. PR_BORDER_END_COLOR, PR_BORDER_END_STYLE, PR_BORDER_END_WIDTH, PR_PADDING_END};
  53. private static final String NONE = "none";
  54. /**
  55. * Main constructor
  56. * @param pList property list
  57. */
  58. public PropertyManager(PropertyList pList) {
  59. this.propertyList = pList;
  60. }
  61. /**
  62. * Returns the property list that is used for lookup.
  63. * @return the property list
  64. */
  65. public PropertyList getPropertyList() {
  66. return propertyList;
  67. }
  68. /**
  69. * Sets the Document object telling the property manager which fonts are
  70. * available.
  71. * @param foTreeControl foTreeControl implementation containing font
  72. * information
  73. */
  74. public void setFontInfo(FOTreeControl foTreeControl) {
  75. this.foTreeControl = foTreeControl;
  76. }
  77. /**
  78. * Constructs a FontState object. If it was constructed before it is
  79. * reused.
  80. * @param foTreeControl FOTreeControl implementation containing the font
  81. * information
  82. * @return a FontState object
  83. */
  84. public Font getFontState(FOTreeControl foTreeControl) {
  85. if (fontState == null) {
  86. if (foTreeControl == null) {
  87. foTreeControl = this.foTreeControl;
  88. } else if (this.foTreeControl == null) {
  89. this.foTreeControl = foTreeControl;
  90. }
  91. /**@todo this is ugly. need to improve. */
  92. String fontFamily = propertyList.get(PR_FONT_FAMILY).getString();
  93. String fontStyle = propertyList.get(PR_FONT_STYLE).getString();
  94. String fw = propertyList.get(PR_FONT_WEIGHT).getString();
  95. int fontWeight = 400;
  96. if (fw.equals("bolder")) {
  97. // +100 from inherited
  98. } else if (fw.equals("lighter")) {
  99. // -100 from inherited
  100. } else {
  101. try {
  102. fontWeight = Integer.parseInt(fw);
  103. } catch (NumberFormatException nfe) {
  104. } /** TODO: log that exception */
  105. }
  106. fontWeight = ((int) fontWeight / 100) * 100;
  107. if (fontWeight < 100) {
  108. fontWeight = 100;
  109. } else if (fontWeight > 900) {
  110. fontWeight = 900;
  111. }
  112. // NOTE: this is incomplete. font-size may be specified with
  113. // various kinds of keywords too
  114. int fontSize = propertyList.get(PR_FONT_SIZE).getLength().getValue();
  115. //int fontVariant = propertyList.get("font-variant").getEnum();
  116. String fname = foTreeControl.fontLookup(fontFamily, fontStyle,
  117. fontWeight);
  118. FontMetrics metrics = foTreeControl.getMetricsFor(fname);
  119. fontState = new Font(fname, metrics, fontSize);
  120. }
  121. return fontState;
  122. }
  123. /**
  124. * Constructs a BorderAndPadding object. If it was constructed before it is
  125. * reused.
  126. * @return a BorderAndPadding object
  127. */
  128. public CommonBorderAndPadding getBorderAndPadding() {
  129. if (borderAndPadding == null) {
  130. this.borderAndPadding = new CommonBorderAndPadding();
  131. initBorderInfo(CommonBorderAndPadding.BEFORE, SA_BEFORE);
  132. initBorderInfo(CommonBorderAndPadding.AFTER, SA_AFTER);
  133. initBorderInfo(CommonBorderAndPadding.START, SA_START);
  134. initBorderInfo(CommonBorderAndPadding.END, SA_END);
  135. }
  136. return borderAndPadding;
  137. }
  138. private void initBorderInfo(int whichSide, int[] saSide) {
  139. borderAndPadding.setPadding(whichSide,
  140. propertyList.get(saSide[3]).getCondLength());
  141. // If style = none, force width to 0, don't get Color (spec 7.7.20)
  142. int style = propertyList.get(saSide[1]).getEnum();
  143. if (style != Constants.NONE) {
  144. borderAndPadding.setBorder(whichSide, style,
  145. propertyList.get(saSide[2]).getCondLength(),
  146. propertyList.get(saSide[0]).getColorType());
  147. }
  148. }
  149. /**
  150. * Constructs a HyphenationProps objects. If it was constructed before it is
  151. * reused.
  152. * @return a HyphenationProps object
  153. */
  154. public CommonHyphenation getHyphenationProps() {
  155. if (hyphProps == null) {
  156. this.hyphProps = new CommonHyphenation();
  157. hyphProps.hyphenate =
  158. this.propertyList.get(PR_HYPHENATE).getEnum();
  159. hyphProps.hyphenationChar = this.propertyList.get(
  160. PR_HYPHENATION_CHARACTER).getCharacter();
  161. hyphProps.hyphenationPushCharacterCount = this.propertyList.get(
  162. PR_HYPHENATION_PUSH_CHARACTER_COUNT).getNumber().
  163. intValue();
  164. hyphProps.hyphenationRemainCharacterCount = this.propertyList.get(
  165. PR_HYPHENATION_REMAIN_CHARACTER_COUNT).getNumber().
  166. intValue();
  167. hyphProps.language =
  168. this.propertyList.get(PR_LANGUAGE).getString();
  169. hyphProps.country = this.propertyList.get(PR_COUNTRY).getString();
  170. }
  171. return hyphProps;
  172. }
  173. /*public int checkBreakBefore(Area area) {
  174. if (!(area instanceof ColumnArea)) {
  175. switch (propertyList.get("break-before").getEnum()) {
  176. case BreakBefore.PAGE:
  177. return Status.FORCE_PAGE_BREAK;
  178. case BreakBefore.ODD_PAGE:
  179. return Status.FORCE_PAGE_BREAK_ODD;
  180. case BreakBefore.EVEN_PAGE:
  181. return Status.FORCE_PAGE_BREAK_EVEN;
  182. case BreakBefore.COLUMN:
  183. return Status.FORCE_COLUMN_BREAK;
  184. default:
  185. return Status.OK;
  186. }
  187. } else {
  188. ColumnArea colArea = (ColumnArea)area;
  189. switch (propertyList.get("break-before").getEnum()) {
  190. case BreakBefore.PAGE:
  191. // if first ColumnArea, and empty, return OK
  192. if (!colArea.hasChildren() && (colArea.getColumnIndex() == 1))
  193. return Status.OK;
  194. else
  195. return Status.FORCE_PAGE_BREAK;
  196. case BreakBefore.ODD_PAGE:
  197. // if first ColumnArea, empty, _and_ in odd page,
  198. // return OK
  199. if (!colArea.hasChildren() && (colArea.getColumnIndex() == 1)
  200. && (colArea.getPage().getNumber() % 2 != 0))
  201. return Status.OK;
  202. else
  203. return Status.FORCE_PAGE_BREAK_ODD;
  204. case BreakBefore.EVEN_PAGE:
  205. // if first ColumnArea, empty, _and_ in even page,
  206. // return OK
  207. if (!colArea.hasChildren() && (colArea.getColumnIndex() == 1)
  208. && (colArea.getPage().getNumber() % 2 == 0))
  209. return Status.OK;
  210. else
  211. return Status.FORCE_PAGE_BREAK_EVEN;
  212. case BreakBefore.COLUMN:
  213. // if ColumnArea is empty return OK
  214. if (!area.hasChildren())
  215. return Status.OK;
  216. else
  217. return Status.FORCE_COLUMN_BREAK;
  218. default:
  219. return Status.OK;
  220. }
  221. }
  222. }
  223. public int checkBreakAfter(Area area) {
  224. switch (propertyList.get("break-after").getEnum()) {
  225. case BreakAfter.PAGE:
  226. return Status.FORCE_PAGE_BREAK;
  227. case BreakAfter.ODD_PAGE:
  228. return Status.FORCE_PAGE_BREAK_ODD;
  229. case BreakAfter.EVEN_PAGE:
  230. return Status.FORCE_PAGE_BREAK_EVEN;
  231. case BreakAfter.COLUMN:
  232. return Status.FORCE_COLUMN_BREAK;
  233. default:
  234. return Status.OK;
  235. }
  236. }*/
  237. /**
  238. * Constructs a MarginProps objects. If it was constructed before it is
  239. * reused.
  240. * @return a MarginProps object
  241. */
  242. public CommonMarginBlock getMarginProps() {
  243. CommonMarginBlock props = new CommonMarginBlock();
  244. // Common Margin Properties-Block
  245. props.marginTop =
  246. this.propertyList.get(PR_MARGIN_TOP).getLength().getValue();
  247. props.marginBottom =
  248. this.propertyList.get(PR_MARGIN_BOTTOM).getLength().getValue();
  249. props.marginLeft =
  250. this.propertyList.get(PR_MARGIN_LEFT).getLength().getValue();
  251. props.marginRight =
  252. this.propertyList.get(PR_MARGIN_RIGHT).getLength().getValue();
  253. // For now, we only get the optimum value for space-before and after
  254. props.spaceBefore = this.propertyList.get(PR_SPACE_BEFORE).
  255. getSpace().getOptimum().getLength().getValue();
  256. props.spaceAfter = this.propertyList.get(PR_SPACE_AFTER).
  257. getSpace().getOptimum().getLength().getValue();
  258. // For now we do the section 5.3.2 calculation here.
  259. // This is a hack that doesn't deal correctly with:
  260. // - Reference vs. non-reference areas.
  261. // - writing mode, it mixes start and left.
  262. // - inherited values of margins and indents.
  263. // When the indents properties calculate this values correctly,
  264. // the block below can be removed and replaced with simple
  265. // props.startIndent = this.propertyList.get(PR_START_INDENT)
  266. // props.endIndent = this.propertyList.get(PR_END_INDENT)
  267. CommonBorderAndPadding bpProps = getBorderAndPadding();
  268. int startIndent = 0;
  269. if (props.marginLeft != 0) {
  270. startIndent = props.marginLeft;
  271. } else {
  272. startIndent = this.propertyList.get(PR_START_INDENT).
  273. getLength().getValue();
  274. }
  275. props.startIndent = startIndent +
  276. bpProps.getBorderStartWidth(false) +
  277. bpProps.getPaddingStart(false);
  278. int endIndent = 0;
  279. if (props.marginRight != 0) {
  280. endIndent = props.marginRight;
  281. } else {
  282. endIndent = this.propertyList.get(PR_END_INDENT).
  283. getLength().getValue();
  284. }
  285. props.endIndent = endIndent +
  286. bpProps.getBorderEndWidth(false) +
  287. bpProps.getPaddingEnd(false);
  288. return props;
  289. }
  290. /**
  291. * Constructs a BackgroundProps objects. If it was constructed before it is
  292. * reused.
  293. * @return a BackgroundProps object
  294. */
  295. public CommonBackground getBackgroundProps() {
  296. CommonBackground bp = new CommonBackground();
  297. bp.backAttachment = propertyList.get(PR_BACKGROUND_ATTACHMENT).getEnum();
  298. bp.backColor = propertyList.get(PR_BACKGROUND_COLOR).getColorType();
  299. if (bp.backColor.getAlpha() == 0) {
  300. bp.backColor = null;
  301. }
  302. bp.backImage = propertyList.get(PR_BACKGROUND_IMAGE).getString();
  303. if (bp.backImage == null || NONE.equals(bp.backImage)) {
  304. bp.backImage = null;
  305. } else {
  306. bp.backRepeat = propertyList.get(PR_BACKGROUND_REPEAT).getEnum();
  307. Property prop = propertyList.get(PR_BACKGROUND_POSITION_HORIZONTAL);
  308. if (prop != null) {
  309. bp.backPosHorizontal = prop.getLength();
  310. }
  311. prop = propertyList.get(PR_BACKGROUND_POSITION_VERTICAL);
  312. if (prop != null) {
  313. bp.backPosVertical = prop.getLength();
  314. }
  315. }
  316. return bp;
  317. }
  318. /**
  319. * Constructs a MarginInlineProps objects. If it was constructed before it is
  320. * reused.
  321. * @return a MarginInlineProps object
  322. */
  323. public CommonMarginInline getMarginInlineProps() {
  324. CommonMarginInline props = new CommonMarginInline();
  325. return props;
  326. }
  327. /**
  328. * Constructs a InlineProps objects. If it was constructed before it is
  329. * reused.
  330. * @return a InlineProps object
  331. */
  332. public InlineProps getInlineProps() {
  333. InlineProps props = new InlineProps();
  334. props.spaceStart = new SpaceVal(propertyList.get(PR_SPACE_START).getSpace());
  335. props.spaceEnd = new SpaceVal(propertyList.get(PR_SPACE_END).getSpace());
  336. return props;
  337. }
  338. /**
  339. * Constructs a AccessibilityProps objects. If it was constructed before it is
  340. * reused.
  341. * @return a AccessibilityProps object
  342. */
  343. public CommonAccessibility getAccessibilityProps() {
  344. CommonAccessibility props = new CommonAccessibility();
  345. String str;
  346. str = this.propertyList.get(PR_SOURCE_DOCUMENT).getString();
  347. if (!NONE.equals(str)) {
  348. props.sourceDoc = str;
  349. }
  350. str = this.propertyList.get(PR_ROLE).getString();
  351. if (!NONE.equals(str)) {
  352. props.role = str;
  353. }
  354. return props;
  355. }
  356. /**
  357. * Constructs a AuralProps objects. If it was constructed before it is
  358. * reused.
  359. * @return a AuralProps object
  360. */
  361. public CommonAural getAuralProps() {
  362. CommonAural props = new CommonAural();
  363. return props;
  364. }
  365. /**
  366. * Constructs a RelativePositionProps objects. If it was constructed before it is
  367. * reused.
  368. * @return a RelativePositionProps object
  369. */
  370. public CommonRelativePosition getRelativePositionProps() {
  371. CommonRelativePosition props = new CommonRelativePosition();
  372. return props;
  373. }
  374. /**
  375. * Constructs a AbsolutePositionProps objects. If it was constructed before
  376. * it is reused.
  377. * @return a AbsolutePositionProps object
  378. */
  379. public CommonAbsolutePosition getAbsolutePositionProps() {
  380. CommonAbsolutePosition props = new CommonAbsolutePosition();
  381. props.absolutePosition =
  382. this.propertyList.get(PR_ABSOLUTE_POSITION).getEnum();
  383. props.top = this.propertyList.get(PR_TOP).getLength().getValue();
  384. props.bottom = this.propertyList.get(PR_BOTTOM).getLength().getValue();
  385. props.left = this.propertyList.get(PR_LEFT).getLength().getValue();
  386. props.right = this.propertyList.get(PR_RIGHT).getLength().getValue();
  387. return props;
  388. }
  389. /**
  390. * Constructs a BlockProps objects. If it was constructed before it is
  391. * reused.
  392. * @return a BlockProps object
  393. */
  394. public BlockProps getBlockProps() {
  395. BlockProps props = new BlockProps();
  396. props.firstIndent = this.propertyList.get(PR_TEXT_INDENT).getLength();
  397. props.lastIndent = 0;
  398. /*this.propertyList.get("last-line-end-indent").getLength().mvalue(); */
  399. props.textAlign = this.propertyList.get(PR_TEXT_ALIGN).getEnum();
  400. props.textAlignLast = this.propertyList.get(PR_TEXT_ALIGN_LAST).getEnum();
  401. props.lineStackType = this.propertyList.get(PR_LINE_STACKING_STRATEGY).getEnum();
  402. return props;
  403. }
  404. /**
  405. * Constructs a LayoutProps objects. If it was constructed before it is
  406. * reused.
  407. * @return a LayoutProps object
  408. */
  409. public LayoutProps getLayoutProps() {
  410. LayoutProps props = new LayoutProps();
  411. props.breakBefore = this.propertyList.get(PR_BREAK_BEFORE).getEnum();
  412. props.breakAfter = this.propertyList.get(PR_BREAK_AFTER).getEnum();
  413. props.bIsSpan = (this.propertyList.get(PR_SPAN).getEnum() == Constants.ALL);
  414. props.spaceBefore = new SpaceVal(
  415. this.propertyList.get(PR_SPACE_BEFORE).getSpace());
  416. props.spaceAfter = new SpaceVal(
  417. this.propertyList.get(PR_SPACE_AFTER).getSpace());
  418. return props;
  419. }
  420. /**
  421. * Constructs a TextInfo objects. If it was constructed before it is
  422. * reused.
  423. * @param foTreeControl FOTreeControl implementation containing list of
  424. * available fonts
  425. * @return a TextInfo object
  426. */
  427. public TextInfo getTextLayoutProps(FOTreeControl foTreeControl) {
  428. if (textInfo == null) {
  429. textInfo = new TextInfo();
  430. textInfo.fs = getFontState(foTreeControl);
  431. textInfo.color = propertyList.get(PR_COLOR).getColorType();
  432. textInfo.verticalAlign =
  433. propertyList.get(PR_VERTICAL_ALIGN).getEnum();
  434. textInfo.wrapOption = propertyList.get(PR_WRAP_OPTION).getEnum();
  435. textInfo.bWrap = (textInfo.wrapOption == Constants.WRAP);
  436. textInfo.wordSpacing = new SpaceVal(
  437. propertyList.get(PR_WORD_SPACING).getSpace());
  438. /* textInfo.letterSpacing =
  439. new SpaceVal(propertyList.get("letter-spacing").getSpace());*/
  440. textInfo.whiteSpaceCollapse =
  441. propertyList.get(PR_WHITE_SPACE_COLLAPSE).getEnum();
  442. textInfo.lineHeight = this.propertyList.get(
  443. PR_LINE_HEIGHT).getLength().getValue();
  444. textInfo.textTransform
  445. = this.propertyList.get(PR_TEXT_TRANSFORM).getEnum();
  446. }
  447. return textInfo;
  448. }
  449. /**
  450. * Calculate absolute reference-orientation relative to media orientation.
  451. * @return the enumerated reference-orientation
  452. */
  453. public int getAbsRefOrient() {
  454. return propertyList.get(PR_REFERENCE_ORIENTATION).getNumber().intValue();
  455. }
  456. /**
  457. * @return the enumerated writing-mode
  458. */
  459. public int getWritingMode() {
  460. return propertyList.get(PR_WRITING_MODE).getEnum();
  461. }
  462. }