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.

CommonBorderPaddingBackground.java 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  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.fo.properties;
  19. import java.awt.Color;
  20. import java.io.FileNotFoundException;
  21. import java.io.IOException;
  22. import java.util.Arrays;
  23. import org.apache.xmlgraphics.image.loader.ImageException;
  24. import org.apache.xmlgraphics.image.loader.ImageInfo;
  25. import org.apache.xmlgraphics.image.loader.ImageManager;
  26. import org.apache.xmlgraphics.image.loader.ImageSessionContext;
  27. import org.apache.fop.ResourceEventProducer;
  28. import org.apache.fop.apps.FOUserAgent;
  29. import org.apache.fop.datatypes.Length;
  30. import org.apache.fop.datatypes.PercentBaseContext;
  31. import org.apache.fop.datatypes.URISpecification;
  32. import org.apache.fop.fo.Constants;
  33. import org.apache.fop.fo.FObj;
  34. import org.apache.fop.fo.PropertyList;
  35. import org.apache.fop.fo.expr.PropertyException;
  36. import org.apache.fop.util.CompareUtil;
  37. /**
  38. * Stores all common border and padding properties.
  39. * See Sec. 7.7 of the XSL-FO Standard.
  40. */
  41. public class CommonBorderPaddingBackground {
  42. /**
  43. * cache holding all canonical instances
  44. * (w/ absolute background-position-* and padding-*)
  45. */
  46. private static final PropertyCache<CommonBorderPaddingBackground> CACHE
  47. = new PropertyCache<CommonBorderPaddingBackground>();
  48. private int hash = -1;
  49. /**
  50. * The "background-attachment" property.
  51. */
  52. public final int backgroundAttachment; // CSOK: VisibilityModifier
  53. /**
  54. * The "background-color" property.
  55. */
  56. public final Color backgroundColor; // CSOK: VisibilityModifier
  57. /**
  58. * The "background-image" property.
  59. */
  60. public final String backgroundImage; // CSOK: VisibilityModifier
  61. /**
  62. * The "background-repeat" property.
  63. */
  64. public final int backgroundRepeat; // CSOK: VisibilityModifier
  65. /**
  66. * The "background-position-horizontal" property.
  67. */
  68. public final Length backgroundPositionHorizontal; // CSOK: VisibilityModifier
  69. /**
  70. * The "background-position-vertical" property.
  71. */
  72. public final Length backgroundPositionVertical; // CSOK: VisibilityModifier
  73. private ImageInfo backgroundImageInfo;
  74. /** the "before" edge */
  75. public static final int BEFORE = 0;
  76. /** the "after" edge */
  77. public static final int AFTER = 1;
  78. /** the "start" edge */
  79. public static final int START = 2;
  80. /** the "end" edge */
  81. public static final int END = 3;
  82. /**
  83. * Utility class to express border info.
  84. */
  85. public static final class BorderInfo {
  86. /** cache holding all canonical instances */
  87. private static final PropertyCache<BorderInfo> CACHE
  88. = new PropertyCache<BorderInfo>();
  89. private int mStyle; // Enum for border style
  90. private Color mColor; // Border color
  91. private CondLengthProperty mWidth;
  92. private CondLengthProperty radiusStart;
  93. private CondLengthProperty radiusEnd;
  94. private int hash = -1;
  95. /**
  96. * Hidden constructor
  97. */
  98. private BorderInfo(int style, CondLengthProperty width, Color color,
  99. CondLengthProperty radiusStart, CondLengthProperty radiusEnd) {
  100. mStyle = style;
  101. mWidth = width;
  102. mColor = color;
  103. this.radiusStart = radiusStart;
  104. this.radiusEnd = radiusEnd;
  105. }
  106. /**
  107. * Returns a BorderInfo instance corresponding to the given values.
  108. *
  109. * @param style the border-style
  110. * @param width the border-width
  111. * @param color the border-color
  112. * @param radiusStart the start radius for rounded borders
  113. * @param radiusEnd the end radius for rounded borders
  114. * @return a cached BorderInfo instance
  115. */
  116. public static BorderInfo getInstance(int style, CondLengthProperty width, Color color,
  117. CondLengthProperty radiusStart, CondLengthProperty radiusEnd) {
  118. return CACHE.fetch(new BorderInfo(style, width, color, radiusStart, radiusEnd));
  119. }
  120. /**
  121. * @return the border-style
  122. */
  123. public int getStyle() {
  124. return this.mStyle;
  125. }
  126. /**
  127. * @return the border-color
  128. */
  129. public Color getColor() {
  130. return this.mColor;
  131. }
  132. /**
  133. * @return the border-width
  134. */
  135. public CondLengthProperty getWidth() {
  136. return this.mWidth;
  137. }
  138. /**
  139. * Convenience method returning the border-width,
  140. * taking into account values of "none" and "hidden"
  141. *
  142. * @return the retained border-width
  143. */
  144. public int getRetainedWidth() {
  145. if ((mStyle == Constants.EN_NONE)
  146. || (mStyle == Constants.EN_HIDDEN)) {
  147. return 0;
  148. } else {
  149. return mWidth.getLengthValue();
  150. }
  151. }
  152. /**
  153. * @return the border-*-start-radius
  154. */
  155. public CondLengthProperty getRadiusStart() {
  156. return this.radiusStart;
  157. }
  158. /**
  159. * @return the border-*-end-radius
  160. */
  161. public CondLengthProperty getRadiusEnd() {
  162. return this.radiusEnd;
  163. }
  164. @Override
  165. public String toString() {
  166. StringBuffer sb = new StringBuffer("BorderInfo");
  167. sb.append(" {");
  168. sb.append(mStyle);
  169. sb.append(", ");
  170. sb.append(mColor);
  171. sb.append(", ");
  172. sb.append(mWidth);
  173. sb.append(", ");
  174. sb.append(radiusStart);
  175. sb.append(", ");
  176. sb.append(radiusEnd);
  177. sb.append("}");
  178. return sb.toString();
  179. }
  180. @Override
  181. public boolean equals(Object obj) {
  182. if (this == obj) {
  183. return true;
  184. }
  185. if (obj instanceof BorderInfo) {
  186. BorderInfo bi = (BorderInfo)obj;
  187. return (this.mColor == bi.mColor
  188. && this.mStyle == bi.mStyle
  189. && this.mWidth == bi.mWidth
  190. && this.radiusStart == bi.radiusStart
  191. && this.radiusEnd == bi.radiusEnd);
  192. }
  193. BorderInfo other = (BorderInfo) obj;
  194. return CompareUtil.equal(mColor, other.mColor)
  195. && mStyle == other.mStyle
  196. && CompareUtil.equal(mWidth, other.mWidth);
  197. }
  198. @Override
  199. public int hashCode() {
  200. if (this.hash == -1) {
  201. int hash = 17;
  202. hash = 37 * hash + (mColor == null ? 0 : mColor.hashCode());
  203. hash = 37 * hash + mStyle;
  204. hash = 37 * hash + (mWidth == null ? 0 : mWidth.hashCode());
  205. hash = 37 * hash + (radiusStart == null ? 0 : radiusStart.hashCode());
  206. hash = 37 * hash + (radiusEnd == null ? 0 : radiusEnd.hashCode());
  207. this.hash = hash;
  208. }
  209. return this.hash;
  210. }
  211. }
  212. /**
  213. * A border info with style "none". Used as a singleton, in the collapsing-border model,
  214. * for elements which don't specify any border on some of their sides.
  215. */
  216. private static final BorderInfo DEFAULT_BORDER_INFO
  217. = BorderInfo.getInstance(Constants.EN_NONE, new ConditionalNullLength(), null,
  218. new ConditionalNullLength(), new ConditionalNullLength());
  219. /**
  220. * A conditional length of value 0. Returned by the
  221. * {@link CommonBorderPaddingBackground#getBorderInfo(int)} method when the
  222. * corresponding border isn't specified, to avoid to callers painful checks for null.
  223. */
  224. private static class ConditionalNullLength extends CondLengthProperty {
  225. @Override
  226. public Property getComponent(int cmpId) {
  227. throw new UnsupportedOperationException();
  228. }
  229. @Override
  230. public Property getConditionality() {
  231. throw new UnsupportedOperationException();
  232. }
  233. @Override
  234. public Length getLength() {
  235. throw new UnsupportedOperationException();
  236. }
  237. @Override
  238. public Property getLengthComponent() {
  239. throw new UnsupportedOperationException();
  240. }
  241. @Override
  242. public int getLengthValue() {
  243. return 0;
  244. }
  245. @Override
  246. public int getLengthValue(PercentBaseContext context) {
  247. return 0;
  248. }
  249. @Override
  250. public boolean isDiscard() {
  251. return true;
  252. }
  253. @Override
  254. public void setComponent(int cmpId, Property cmpnValue, boolean isDefault) {
  255. throw new UnsupportedOperationException();
  256. }
  257. @Override
  258. public String toString() {
  259. return "CondLength[0mpt, discard]";
  260. }
  261. }
  262. /**
  263. * Returns a default BorderInfo of style none.
  264. *
  265. * @return a BorderInfo instance with style set to {@link Constants#EN_NONE}
  266. */
  267. public static BorderInfo getDefaultBorderInfo() {
  268. return DEFAULT_BORDER_INFO;
  269. }
  270. private BorderInfo[] borderInfo = new BorderInfo[4];
  271. private CondLengthProperty[] padding = new CondLengthProperty[4];
  272. /**
  273. * Construct a CommonBorderPaddingBackground object.
  274. *
  275. * @param pList The PropertyList to get properties from.
  276. * @throws PropertyException if there's an error while binding the properties
  277. */
  278. CommonBorderPaddingBackground(PropertyList pList) throws PropertyException {
  279. backgroundAttachment = pList.get(Constants.PR_BACKGROUND_ATTACHMENT).getEnum();
  280. Color bc = pList.get(Constants.PR_BACKGROUND_COLOR).getColor(
  281. pList.getFObj().getUserAgent());
  282. if (bc.getAlpha() == 0) {
  283. backgroundColor = null;
  284. } else {
  285. backgroundColor = bc;
  286. }
  287. String img = pList.get(Constants.PR_BACKGROUND_IMAGE).getString();
  288. if (img == null || "none".equals(img)) {
  289. backgroundImage = "";
  290. backgroundRepeat = -1;
  291. backgroundPositionHorizontal = null;
  292. backgroundPositionVertical = null;
  293. } else {
  294. backgroundImage = img;
  295. backgroundRepeat = pList.get(Constants.PR_BACKGROUND_REPEAT).getEnum();
  296. backgroundPositionHorizontal = pList.get(
  297. Constants.PR_BACKGROUND_POSITION_HORIZONTAL).getLength();
  298. backgroundPositionVertical = pList.get(
  299. Constants.PR_BACKGROUND_POSITION_VERTICAL).getLength();
  300. }
  301. initBorderInfo(pList, BEFORE,
  302. Constants.PR_BORDER_BEFORE_COLOR,
  303. Constants.PR_BORDER_BEFORE_STYLE,
  304. Constants.PR_BORDER_BEFORE_WIDTH,
  305. Constants.PR_PADDING_BEFORE,
  306. Constants.PR_X_BORDER_BEFORE_RADIUS_START,
  307. Constants.PR_X_BORDER_BEFORE_RADIUS_END);
  308. initBorderInfo(pList, AFTER,
  309. Constants.PR_BORDER_AFTER_COLOR,
  310. Constants.PR_BORDER_AFTER_STYLE,
  311. Constants.PR_BORDER_AFTER_WIDTH,
  312. Constants.PR_PADDING_AFTER,
  313. Constants.PR_X_BORDER_AFTER_RADIUS_START,
  314. Constants.PR_X_BORDER_AFTER_RADIUS_END);
  315. initBorderInfo(pList, START,
  316. Constants.PR_BORDER_START_COLOR,
  317. Constants.PR_BORDER_START_STYLE,
  318. Constants.PR_BORDER_START_WIDTH,
  319. Constants.PR_PADDING_START,
  320. Constants.PR_X_BORDER_START_RADIUS_START,
  321. Constants.PR_X_BORDER_START_RADIUS_END);
  322. initBorderInfo(pList, END,
  323. Constants.PR_BORDER_END_COLOR,
  324. Constants.PR_BORDER_END_STYLE,
  325. Constants.PR_BORDER_END_WIDTH,
  326. Constants.PR_PADDING_END,
  327. Constants.PR_X_BORDER_END_RADIUS_START,
  328. Constants.PR_X_BORDER_END_RADIUS_END);
  329. }
  330. /**
  331. * Obtain a CommonBorderPaddingBackground instance based on the
  332. * related property valus in the given {@link PropertyList}
  333. *
  334. * @param pList the {@link PropertyList} to use
  335. * @return a CommonBorderPaddingBackground instance (cached if possible)
  336. * @throws PropertyException in case of an error
  337. */
  338. public static CommonBorderPaddingBackground getInstance(PropertyList pList) throws PropertyException {
  339. CommonBorderPaddingBackground newInstance = new CommonBorderPaddingBackground(pList);
  340. CommonBorderPaddingBackground cachedInstance = null;
  341. /* if padding-* and background-position-* resolve to absolute lengths
  342. * the whole instance can be cached */
  343. if ((newInstance.padding[BEFORE] == null
  344. || newInstance.padding[BEFORE].getLength().isAbsolute())
  345. && (newInstance.padding[AFTER] == null
  346. || newInstance.padding[AFTER].getLength().isAbsolute())
  347. && (newInstance.padding[START] == null
  348. || newInstance.padding[START].getLength().isAbsolute())
  349. && (newInstance.padding[END] == null
  350. || newInstance.padding[END].getLength().isAbsolute())
  351. && (newInstance.backgroundPositionHorizontal == null
  352. || newInstance.backgroundPositionHorizontal.isAbsolute())
  353. && (newInstance.backgroundPositionVertical == null
  354. || newInstance.backgroundPositionVertical.isAbsolute())) {
  355. cachedInstance = CACHE.fetch(newInstance);
  356. }
  357. synchronized (newInstance.backgroundImage.intern()) {
  358. /* for non-cached, or not-yet-cached instances, preload the image */
  359. if ((cachedInstance == null || cachedInstance == newInstance)
  360. && !("".equals(newInstance.backgroundImage))) {
  361. //Additional processing: preload image
  362. String uri = URISpecification.getURL(newInstance.backgroundImage);
  363. FObj fobj = pList.getFObj();
  364. FOUserAgent userAgent = pList.getFObj().getUserAgent();
  365. ImageManager manager = userAgent.getImageManager();
  366. ImageSessionContext sessionContext = userAgent.getImageSessionContext();
  367. ImageInfo info;
  368. try {
  369. info = manager.getImageInfo(uri, sessionContext);
  370. newInstance.backgroundImageInfo = info;
  371. } catch (ImageException e) {
  372. ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
  373. fobj.getUserAgent().getEventBroadcaster());
  374. eventProducer.imageError(fobj, uri, e, fobj.getLocator());
  375. } catch (FileNotFoundException fnfe) {
  376. ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
  377. fobj.getUserAgent().getEventBroadcaster());
  378. eventProducer.imageNotFound(fobj, uri, fnfe, fobj.getLocator());
  379. } catch (IOException ioe) {
  380. ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get(
  381. fobj.getUserAgent().getEventBroadcaster());
  382. eventProducer.imageIOError(fobj, uri, ioe, fobj.getLocator());
  383. }
  384. }
  385. }
  386. return (cachedInstance != null ? cachedInstance : newInstance);
  387. }
  388. private void initBorderInfo(PropertyList pList, int side,
  389. int colorProp, int styleProp, int widthProp, int paddingProp,
  390. int radiusStartProp, int radiusEndProp)
  391. throws PropertyException {
  392. padding[side] = pList.get(paddingProp).getCondLength();
  393. // If style = none, force width to 0, don't get Color (spec 7.7.20)
  394. int style = pList.get(styleProp).getEnum();
  395. // if (style != Constants.EN_NONE) {
  396. FOUserAgent ua = pList.getFObj().getUserAgent();
  397. setBorderInfo(BorderInfo.getInstance(style,
  398. pList.get(widthProp).getCondLength(),
  399. pList.get(colorProp).getColor(ua),
  400. pList.get(radiusStartProp).getCondLength(),
  401. pList.get(radiusEndProp).getCondLength()), side);
  402. // }
  403. }
  404. /**
  405. * Sets a border.
  406. * @param info the border information
  407. * @param side the side to apply the info to
  408. */
  409. private void setBorderInfo(BorderInfo info, int side) {
  410. this.borderInfo[side] = info;
  411. }
  412. /**
  413. * @param side the side to retrieve
  414. * @return the border info for a side
  415. */
  416. public BorderInfo getBorderInfo(int side) {
  417. if (this.borderInfo[side] == null) {
  418. return getDefaultBorderInfo();
  419. } else {
  420. return this.borderInfo[side];
  421. }
  422. }
  423. /**
  424. * @return the background image info object, null if there is
  425. * no background image.
  426. */
  427. public ImageInfo getImageInfo() {
  428. return this.backgroundImageInfo;
  429. }
  430. /**
  431. * @param discard indicates whether the .conditionality component should be
  432. * considered (start of a reference-area)
  433. * @return the width of the start-border, taking into account the specified conditionality
  434. */
  435. public int getBorderStartWidth(boolean discard) {
  436. return getBorderWidth(START, discard);
  437. }
  438. /**
  439. * @param discard indicates whether the .conditionality component should be
  440. * considered (end of a reference-area)
  441. * @return the width of the end-border, taking into account the specified conditionality
  442. */
  443. public int getBorderEndWidth(boolean discard) {
  444. return getBorderWidth(END, discard);
  445. }
  446. /**
  447. * @param discard indicates whether the .conditionality component should be
  448. * considered (start of a reference-area)
  449. * @return the width of the before-border, taking into account the specified conditionality
  450. */
  451. public int getBorderBeforeWidth(boolean discard) {
  452. return getBorderWidth(BEFORE, discard);
  453. }
  454. /**
  455. * @param discard indicates whether the .conditionality component should be
  456. * considered (end of a reference-area)
  457. * @return the width of the after-border, taking into account the specified conditionality
  458. */
  459. public int getBorderAfterWidth(boolean discard) {
  460. return getBorderWidth(AFTER, discard);
  461. }
  462. /**
  463. * @param discard indicates whether the .conditionality component should be
  464. * considered (start of a reference-area)
  465. * @param context the context to evaluate percentage values
  466. * @return the width of the start-padding, taking into account the specified conditionality
  467. */
  468. public int getPaddingStart(boolean discard, PercentBaseContext context) {
  469. return getPadding(START, discard, context);
  470. }
  471. /**
  472. * @param discard indicates whether the .conditionality component should be
  473. * considered (start of a reference-area)
  474. * @param context the context to evaluate percentage values
  475. * @return the width of the end-padding, taking into account the specified conditionality
  476. */
  477. public int getPaddingEnd(boolean discard, PercentBaseContext context) {
  478. return getPadding(END, discard, context);
  479. }
  480. /**
  481. * @param discard indicates whether the .conditionality component should be
  482. * considered (start of a reference-area)
  483. * @param context the context to evaluate percentage values
  484. * @return the width of the before-padding, taking into account the specified conditionality
  485. */
  486. public int getPaddingBefore(boolean discard, PercentBaseContext context) {
  487. return getPadding(BEFORE, discard, context);
  488. }
  489. /**
  490. * @param discard indicates whether the .conditionality component should be
  491. * considered (start of a reference-area)
  492. * @param context the context to evaluate percentage values
  493. * @return the width of the after-padding, taking into account the specified conditionality
  494. */
  495. public int getPaddingAfter(boolean discard, PercentBaseContext context) {
  496. return getPadding(AFTER, discard, context);
  497. }
  498. /**
  499. * @param side the side of the border
  500. * @param discard indicates whether the .conditionality component should be considered (end of a
  501. * reference-area)
  502. * @return the width of the start-border, taking into account the specified conditionality
  503. */
  504. public int getBorderWidth(int side, boolean discard) {
  505. if ((borderInfo[side] == null)
  506. || (borderInfo[side].mStyle == Constants.EN_NONE)
  507. || (borderInfo[side].mStyle == Constants.EN_HIDDEN)
  508. || (discard && borderInfo[side].mWidth.isDiscard())) {
  509. return 0;
  510. } else {
  511. return borderInfo[side].mWidth.getLengthValue();
  512. }
  513. }
  514. /**
  515. * Returns the border corner radius of the starting edge
  516. * i.e. the edge either adjacent to the before or start border.
  517. * @param side the border side
  518. * @param discard indicates whether the .conditionality component should be
  519. * considered (end of a reference-area)
  520. * @param context the context for percentage calculations
  521. * @return the border radius of the of the starting corner
  522. */
  523. public int getBorderRadiusStart(int side, boolean discard, PercentBaseContext context) {
  524. if (borderInfo[side] == null) {
  525. return 0;
  526. } else {
  527. return borderInfo[side].radiusStart.getLengthValue(context);
  528. }
  529. }
  530. /**
  531. * Returns the border corner radius of the ending edge
  532. * i.e. the edge either adjacent to the after or end border
  533. * @param side the border side
  534. * @param discard indicates whether the .conditionality component should be
  535. * considered (end of a reference-area)
  536. * @param context the context for percentage calculations
  537. * @return the border radius of the of the ending corner
  538. */
  539. public int getBorderRadiusEnd(int side, boolean discard, PercentBaseContext context) {
  540. if (borderInfo[side] == null) {
  541. return 0;
  542. } else {
  543. return borderInfo[side].radiusEnd.getLengthValue(context);
  544. }
  545. }
  546. /**
  547. * The border-color for the given side
  548. *
  549. * @param side one of {@link #BEFORE}, {@link #AFTER}, {@link #START}, {@link #END}
  550. * @return the border-color for the given side
  551. */
  552. public Color getBorderColor(int side) {
  553. if (borderInfo[side] != null) {
  554. return borderInfo[side].getColor();
  555. } else {
  556. return null;
  557. }
  558. }
  559. /**
  560. * The border-style for the given side
  561. *
  562. * @param side one of {@link #BEFORE}, {@link #AFTER}, {@link #START}, {@link #END}
  563. * @return the border-style for the given side
  564. */
  565. public int getBorderStyle(int side) {
  566. if (borderInfo[side] != null) {
  567. return borderInfo[side].mStyle;
  568. } else {
  569. return Constants.EN_NONE;
  570. }
  571. }
  572. /**
  573. * Return the padding for the given side, taking into account
  574. * the conditionality and evaluating any percentages in the given
  575. * context.
  576. *
  577. * @param side one of {@link #BEFORE}, {@link #AFTER}, {@link #START}, {@link #END}
  578. * @param discard true if the conditionality component should be considered
  579. * @param context the context for percentage-resolution
  580. * @return the computed padding for the given side
  581. */
  582. public int getPadding(int side, boolean discard, PercentBaseContext context) {
  583. if ((padding[side] == null) || (discard && padding[side].isDiscard())) {
  584. return 0;
  585. } else {
  586. return padding[side].getLengthValue(context);
  587. }
  588. }
  589. /**
  590. * Returns the CondLengthProperty for the padding on one side.
  591. * @param side the side
  592. * @return the requested CondLengthProperty
  593. */
  594. public CondLengthProperty getPaddingLengthProperty(int side) {
  595. return padding[side];
  596. }
  597. /**
  598. * Return all the border and padding width in the inline progression
  599. * dimension.
  600. * @param discard the discard flag.
  601. * @param context for percentage evaluation.
  602. * @return all the padding and border width.
  603. */
  604. public int getIPPaddingAndBorder(boolean discard, PercentBaseContext context) {
  605. return getPaddingStart(discard, context)
  606. + getPaddingEnd(discard, context)
  607. + getBorderStartWidth(discard)
  608. + getBorderEndWidth(discard);
  609. }
  610. /**
  611. * Return all the border and padding height in the block progression
  612. * dimension.
  613. * @param discard the discard flag.
  614. * @param context for percentage evaluation
  615. * @return all the padding and border height.
  616. */
  617. public int getBPPaddingAndBorder(boolean discard, PercentBaseContext context) {
  618. return getPaddingBefore(discard, context) + getPaddingAfter(discard, context)
  619. + getBorderBeforeWidth(discard) + getBorderAfterWidth(discard);
  620. }
  621. @Override
  622. public String toString() {
  623. return "CommonBordersAndPadding (Before, After, Start, End):\n"
  624. + "Borders: (" + getBorderBeforeWidth(false) + ", " + getBorderAfterWidth(false) + ", "
  625. + getBorderStartWidth(false) + ", " + getBorderEndWidth(false) + ")\n"
  626. + "Border Colors: (" + getBorderColor(BEFORE) + ", " + getBorderColor(AFTER) + ", "
  627. + getBorderColor(START) + ", " + getBorderColor(END) + ")\n"
  628. + "Padding: (" + getPaddingBefore(false, null) + ", " + getPaddingAfter(false, null)
  629. + ", " + getPaddingStart(false, null) + ", " + getPaddingEnd(false, null) + ")\n";
  630. }
  631. /**
  632. * @return true if there is any kind of background to be painted
  633. */
  634. public boolean hasBackground() {
  635. return ((backgroundColor != null || getImageInfo() != null));
  636. }
  637. /** @return true if border is non-zero. */
  638. public boolean hasBorder() {
  639. return ((getBorderBeforeWidth(false) + getBorderAfterWidth(false)
  640. + getBorderStartWidth(false) + getBorderEndWidth(false)) > 0);
  641. }
  642. /**
  643. * @param context for percentage based evaluation.
  644. * @return true if padding is non-zero.
  645. */
  646. public boolean hasPadding(PercentBaseContext context) {
  647. return ((getPaddingBefore(false, context) + getPaddingAfter(false, context)
  648. + getPaddingStart(false, context) + getPaddingEnd(false, context)) > 0);
  649. }
  650. /** @return true if there are any borders defined. */
  651. public boolean hasBorderInfo() {
  652. return (borderInfo[BEFORE] != null || borderInfo[AFTER] != null
  653. || borderInfo[START] != null || borderInfo[END] != null);
  654. }
  655. /**
  656. * Returns the "background-color" property.
  657. * @return the "background-color" property.
  658. */
  659. public Color getBackgroundColor() {
  660. return backgroundColor;
  661. }
  662. /**
  663. * Returns the "background-attachment" property.
  664. * @return the "background-attachment" property.
  665. */
  666. public int getBackgroundAttachment() {
  667. return backgroundAttachment;
  668. }
  669. /**
  670. * Returns the "background-image" property.
  671. * @return the "background-image" property.
  672. */
  673. public String getBackgroundImage() {
  674. return backgroundImage;
  675. }
  676. /**
  677. * Returns the "background-repeat" property.
  678. * @return the "background-repeat" property.
  679. */
  680. public int getBackgroundRepeat() {
  681. return backgroundRepeat;
  682. }
  683. /**
  684. * Returns the "background-position-horizontal" property.
  685. * @return the "background-position-horizontal" property.
  686. */
  687. public Length getBackgroundPositionHorizontal() {
  688. return backgroundPositionHorizontal;
  689. }
  690. /**
  691. * Returns the "background-position-vertical" property.
  692. * @return the "background-position-vertical" property.
  693. */
  694. public Length getBackgroundPositionVertical() {
  695. return backgroundPositionVertical;
  696. }
  697. /**
  698. * Returns the background image info
  699. * @return the background image info
  700. */
  701. public ImageInfo getBackgroundImageInfo() {
  702. return backgroundImageInfo;
  703. }
  704. /**
  705. * Returns the border info
  706. * @return the border info
  707. */
  708. public BorderInfo[] getBorderInfo() {
  709. return borderInfo;
  710. }
  711. /**
  712. * Returns the padding
  713. * @return the padding
  714. */
  715. public CondLengthProperty[] getPadding() {
  716. return padding;
  717. }
  718. @Override
  719. public boolean equals(Object obj) {
  720. if (this == obj) {
  721. return true;
  722. }
  723. if (obj instanceof CommonBorderPaddingBackground) {
  724. CommonBorderPaddingBackground cbpb = (CommonBorderPaddingBackground)obj;
  725. return (this.backgroundAttachment == cbpb.backgroundAttachment
  726. && this.backgroundColor == cbpb.backgroundColor
  727. && this.backgroundImage.equals(cbpb.backgroundImage)
  728. && this.backgroundPositionHorizontal == cbpb.backgroundPositionHorizontal
  729. && this.backgroundPositionVertical == cbpb.backgroundPositionVertical
  730. && this.backgroundRepeat == cbpb.backgroundRepeat
  731. && Arrays.equals(borderInfo, cbpb.borderInfo)
  732. && Arrays.equals(padding, cbpb.padding));
  733. } else {
  734. return false;
  735. }
  736. }
  737. @Override
  738. public int hashCode() {
  739. if (this.hash == -1) {
  740. int hash = getHashCode(backgroundColor,
  741. backgroundImage,
  742. backgroundPositionHorizontal,
  743. backgroundPositionVertical,
  744. borderInfo[BEFORE],
  745. borderInfo[AFTER],
  746. borderInfo[START],
  747. borderInfo[END],
  748. padding[BEFORE],
  749. padding[AFTER],
  750. padding[START],
  751. padding[END]);
  752. hash = 37 * hash + backgroundAttachment;
  753. hash = 37 * hash + backgroundRepeat;
  754. this.hash = hash;
  755. }
  756. return this.hash;
  757. }
  758. private int getHashCode(Object... objects) {
  759. int hash = 17;
  760. for (Object o : objects) {
  761. hash = 37 * hash + (o == null ? 0 : o.hashCode());
  762. }
  763. return hash;
  764. }
  765. }