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.

BorderPainterTestCase.java 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  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. package org.apache.fop.render.intermediate;
  18. import java.awt.Color;
  19. import java.awt.Rectangle;
  20. import java.io.IOException;
  21. import org.junit.Test;
  22. import org.apache.fop.fo.Constants;
  23. import org.apache.fop.traits.BorderProps;
  24. import org.apache.fop.traits.BorderProps.Mode;
  25. import static org.junit.Assert.assertEquals;
  26. import static org.mockito.Mockito.atLeastOnce;
  27. import static org.mockito.Mockito.doThrow;
  28. import static org.mockito.Mockito.mock;
  29. import static org.mockito.Mockito.never;
  30. import static org.mockito.Mockito.times;
  31. import static org.mockito.Mockito.verify;
  32. import static org.mockito.Mockito.verifyZeroInteractions;
  33. public class BorderPainterTestCase {
  34. private static final BorderProps BORDER_PROPS = new BorderProps(Constants.EN_SOLID, 10, 50, 50,
  35. Color.BLACK, BorderProps.Mode.SEPARATE);
  36. @Test
  37. public void clipBackground() throws Exception {
  38. // Rectangular borders
  39. test(new ClipBackgroundTester(0, 0, 10, 10));
  40. test(new ClipBackgroundTester(5, 10, 10, 10));
  41. test(new ClipBackgroundTester(0, 0, 10, 10).setBorderWidth(1));
  42. test(new ClipBackgroundTester(0, 0, 10, 10).beforeBorder().setWidth(10).tester());
  43. // Rounded corners
  44. test(new ClipBackgroundTester(0, 0, 10, 10).setEndBefore(1, 1));
  45. test(new ClipBackgroundTester(0, 0, 10, 10).setEndAfter(1, 1));
  46. test(new ClipBackgroundTester(0, 0, 10, 10).setStartAfter(1, 1));
  47. test(new ClipBackgroundTester(0, 0, 10, 10).setStartBefore(1, 1));
  48. test(new ClipBackgroundTester(0, 0, 100, 100)
  49. .setCornerRadii(10)
  50. .beforeBorder().setWidth(5).tester()
  51. .startBorder().setWidth(5).tester());
  52. test(new ClipBackgroundTester(0, 0, 100, 100)
  53. .setCornerRadii(10)
  54. .beforeBorder().setWidth(10).tester()
  55. .startBorder().setWidth(10).tester());
  56. test(new ClipBackgroundTester(0, 0, 100, 100)
  57. .setCornerRadii(10)
  58. .beforeBorder().setWidth(5).tester());
  59. test(new ClipBackgroundTester(0, 0, 100, 100)
  60. .setCornerRadii(10)
  61. .setStartBefore(10, 10)
  62. .beforeBorder().setWidth(10).tester());
  63. }
  64. private void test(BorderPainterTester<?> tester) throws IOException {
  65. tester.test();
  66. }
  67. @Test (expected = IFException.class)
  68. public void drawBordersThrowsIFException() throws Exception {
  69. GraphicsPainter graphicsPainter = mock(GraphicsPainter.class);
  70. doThrow(new IOException()).when(graphicsPainter).saveGraphicsState();
  71. new BorderPainter(graphicsPainter).drawBorders(new Rectangle(0, 0, 1000, 1000), BORDER_PROPS,
  72. BORDER_PROPS, BORDER_PROPS, BORDER_PROPS, Color.WHITE);
  73. }
  74. @Test
  75. public void testDrawRectangularBorders() throws IOException {
  76. test(new DrawRectangularBordersTester(0, 0, 1000, 1000).setBorderWidth(10));
  77. test(new DrawRectangularBordersTester(0, 0, 1000, 1000));
  78. test(new DrawRectangularBordersTester(0, 0, 1000, 1000).setBorderWidth(10)
  79. .beforeBorder().setWidth(0).tester());
  80. }
  81. @Test
  82. public void testDrawRectangularBordersWithNullBorders() throws IOException, IFException {
  83. GraphicsPainter graphicsPainter = mock(GraphicsPainter.class);
  84. BorderProps nullBorderProps = null;
  85. new BorderPainter(graphicsPainter).drawRectangularBorders(new Rectangle(0, 0, 1000, 1000),
  86. nullBorderProps, nullBorderProps, nullBorderProps, nullBorderProps);
  87. verifyZeroInteractions(graphicsPainter);
  88. }
  89. @Test
  90. public void drawRoundedBorders() throws Exception {
  91. test(new DrawRoundedBordersTester(0, 0, 10, 10).setBorderWidth(10));
  92. test(new DrawRoundedBordersTester(0, 0, 10, 10).beforeBorder().setWidth(10).tester());
  93. test(new DrawRoundedBordersTester(0, 0, 10, 10).setBorderWidth(10).setCornerRadii(5)
  94. .beforeBorder().setWidth(0).tester());
  95. test(new DrawRoundedBordersTester(0, 0, 10, 10)
  96. .beforeBorder().setWidth(10).tester().endBorder().setWidth(10).tester());
  97. test(new DrawRoundedBordersTester(0, 0, 100, 100).setBorderWidth(15).setCornerRadii(10));
  98. test(new DrawRoundedBordersTester(0, 0, 100, 100).setBorderWidth(15).setCornerRadii(10)
  99. .beforeBorder().setWidth(5).tester());
  100. test(new DrawRoundedBordersTester(0, 0, 60, 60).setBorderWidth(4).setCornerRadii(30));
  101. }
  102. @Test
  103. public void testDrawRoundedBordersWithNullBorders() throws IOException, IFException {
  104. GraphicsPainter graphicsPainter = mock(GraphicsPainter.class);
  105. BorderProps nullBorderProps = null;
  106. new BorderPainter(graphicsPainter).drawRoundedBorders(new Rectangle(0, 0, 1000, 1000),
  107. nullBorderProps, nullBorderProps, nullBorderProps, nullBorderProps);
  108. verifyZeroInteractions(graphicsPainter);
  109. }
  110. @Test
  111. public void testCalculateCornerCorrectionFactor() {
  112. calculateCornerCorrectionFactorHelper(30000, 500000);
  113. calculateCornerCorrectionFactorHelper(30000, 10000);
  114. }
  115. private void calculateCornerCorrectionFactorHelper(int radius, int rectWidth) {
  116. BorderProps borderProps = new BorderProps(Constants.EN_SOLID, 4000, radius, radius, Color.BLACK,
  117. BorderProps.Mode.SEPARATE);
  118. int rectHeight = rectWidth + 100;
  119. double expected = (2 * radius > rectWidth) ? (double) rectWidth / (2 * radius) : 1.0;
  120. double actual = BorderPainter.calculateCornerCorrectionFactor(rectWidth, rectHeight, borderProps,
  121. borderProps, borderProps, borderProps);
  122. assertEquals(expected, actual, 0);
  123. }
  124. private abstract static class BorderPainterTester<T extends BorderPainterTester<?>> {
  125. protected final Rectangle borderExtent;
  126. protected BorderProps before;
  127. protected BorderProps after;
  128. protected BorderProps start;
  129. protected BorderProps end;
  130. protected final GraphicsPainter graphicsPainter;
  131. protected final BorderPainter sut;
  132. private final BorderPropsBuilder<T> beforeBuilder;
  133. private final BorderPropsBuilder<T> afterBuilder;
  134. private final BorderPropsBuilder<T> startBuilder;
  135. private final BorderPropsBuilder<T> endBuilder;
  136. public BorderPainterTester(int xOrigin, int yOrigin, int width, int height) {
  137. if (width <= 0 || height <= 0) {
  138. throw new IllegalArgumentException("Cannot test degenerate borders");
  139. }
  140. beforeBuilder = new BorderPropsBuilder<T>(getThis());
  141. afterBuilder = new BorderPropsBuilder<T>(getThis());
  142. startBuilder = new BorderPropsBuilder<T>(getThis());
  143. endBuilder = new BorderPropsBuilder<T>(getThis());
  144. this.borderExtent = new Rectangle(xOrigin, yOrigin, width, height);
  145. this.graphicsPainter = mock(GraphicsPainter.class);
  146. this.sut = new BorderPainter(graphicsPainter);
  147. }
  148. protected abstract T getThis();
  149. public BorderPropsBuilder<T> beforeBorder() {
  150. return beforeBuilder;
  151. }
  152. public BorderPropsBuilder<T> afterBorder() {
  153. return afterBuilder;
  154. }
  155. public BorderPropsBuilder<T> startBorder() {
  156. return startBuilder;
  157. }
  158. public BorderPropsBuilder<T> endBorder() {
  159. return endBuilder;
  160. }
  161. public T setBorderWidth(int width) {
  162. beforeBuilder.setWidth(width);
  163. endBuilder.setWidth(width);
  164. afterBuilder.setWidth(width);
  165. startBuilder.setWidth(width);
  166. return getThis();
  167. }
  168. public T setCornerRadii(int radius) {
  169. return setCornerRadii(radius, radius);
  170. }
  171. public T setCornerRadii(int xRadius, int yRadius) {
  172. setStartBefore(xRadius, yRadius);
  173. setEndBefore(xRadius, yRadius);
  174. setEndAfter(xRadius, yRadius);
  175. setStartAfter(xRadius, yRadius);
  176. return getThis();
  177. }
  178. public T setStartBefore(int xRadius, int yRadius) {
  179. startBuilder.setRadiusStart(xRadius);
  180. beforeBuilder.setRadiusStart(yRadius);
  181. return getThis();
  182. }
  183. public T setEndBefore(int xRadius, int yRadius) {
  184. endBuilder.setRadiusStart(xRadius);
  185. beforeBuilder.setRadiusEnd(yRadius);
  186. return getThis();
  187. }
  188. public T setEndAfter(int xRadius, int yRadius) {
  189. endBuilder.setRadiusEnd(xRadius);
  190. afterBuilder.setRadiusEnd(yRadius);
  191. return getThis();
  192. }
  193. public T setStartAfter(int xRadius, int yRadius) {
  194. startBuilder.setRadiusEnd(xRadius);
  195. afterBuilder.setRadiusStart(yRadius);
  196. return getThis();
  197. }
  198. public final void test() throws IOException {
  199. before = beforeBuilder.build();
  200. after = afterBuilder.build();
  201. end = endBuilder.build();
  202. start = startBuilder.build();
  203. testMethod();
  204. }
  205. protected abstract void testMethod() throws IOException;
  206. protected static int numberOfNonZeroBorders(BorderProps first, BorderProps... borders) {
  207. int i = first.width == 0 ? 0 : 1;
  208. for (BorderProps borderProp : borders) {
  209. if (borderProp.width > 0) {
  210. i++;
  211. }
  212. }
  213. return i;
  214. }
  215. protected int numberOfNonZeroBorders() {
  216. return numberOfNonZeroBorders(before, end, after, start);
  217. }
  218. }
  219. private static class BorderPropsBuilder<T extends BorderPainterTester<?>> {
  220. private final int style = 0;
  221. private final Color color = null;
  222. private final Mode mode = BorderProps.Mode.SEPARATE;
  223. private int width;
  224. private int radiusStart;
  225. private int radiusEnd;
  226. private final T tester;
  227. public BorderPropsBuilder(T tester) {
  228. this.tester = tester;
  229. }
  230. public T tester() {
  231. return tester;
  232. }
  233. public BorderPropsBuilder<T> setWidth(int width) {
  234. this.width = width;
  235. return this;
  236. }
  237. public BorderPropsBuilder<T> setRadiusStart(int radiusStart) {
  238. this.radiusStart = radiusStart;
  239. return this;
  240. }
  241. public BorderPropsBuilder<T> setRadiusEnd(int radiusEnd) {
  242. this.radiusEnd = radiusEnd;
  243. return this;
  244. }
  245. public BorderProps build() {
  246. return new BorderProps(style, width, radiusStart, radiusEnd, color, mode);
  247. }
  248. }
  249. private static final class DrawRectangularBordersTester
  250. extends BorderPainterTester<DrawRectangularBordersTester> {
  251. public DrawRectangularBordersTester(int xOrigin, int yOrigin, int width, int height)
  252. throws IOException {
  253. super(xOrigin, yOrigin, width, height);
  254. }
  255. public DrawRectangularBordersTester setStartBefore(int xRadius, int yRadius) {
  256. return notSupported();
  257. }
  258. public DrawRectangularBordersTester setEndBefore(int xRadius, int yRadius) {
  259. return notSupported();
  260. }
  261. public DrawRectangularBordersTester setEndAfter(int xRadius, int yRadius) {
  262. return notSupported();
  263. }
  264. public DrawRectangularBordersTester setStartAfter(int xRadius, int yRadius) {
  265. return notSupported();
  266. }
  267. private DrawRectangularBordersTester notSupported() {
  268. throw new UnsupportedOperationException();
  269. }
  270. public void testMethod() throws IOException {
  271. sut.drawRectangularBorders(borderExtent, before, after, start, end);
  272. verifyDrawing();
  273. }
  274. private void verifyDrawing() throws IOException {
  275. final int rectX = borderExtent.x;
  276. final int rectY = borderExtent.y;
  277. final int rectWidth = borderExtent.width;
  278. final int rectHeight = borderExtent.height;
  279. if (before.width > 0) {
  280. verify(graphicsPainter).moveTo(rectX, rectY);
  281. verify(graphicsPainter).lineTo(rectWidth, rectY);
  282. verify(graphicsPainter, times(numberOfNonZeroBorders(before, end)))
  283. .lineTo(rectWidth - end.width, rectY + before.width);
  284. verify(graphicsPainter, times(numberOfNonZeroBorders(before, start)))
  285. .lineTo(rectX + start.width, rectY + before.width);
  286. }
  287. if (end.width > 0) {
  288. verify(graphicsPainter).moveTo(rectWidth, rectY);
  289. verify(graphicsPainter).lineTo(rectWidth, rectHeight);
  290. verify(graphicsPainter, times(numberOfNonZeroBorders(end, after)))
  291. .lineTo(rectWidth - end.width, rectHeight - after.width);
  292. verify(graphicsPainter, times(numberOfNonZeroBorders(end, before)))
  293. .lineTo(rectWidth - end.width, rectY + before.width);
  294. }
  295. if (after.width > 0) {
  296. verify(graphicsPainter).moveTo(rectWidth, rectHeight);
  297. verify(graphicsPainter).lineTo(rectX, rectHeight);
  298. verify(graphicsPainter, times(numberOfNonZeroBorders(after, end)))
  299. .lineTo(rectX + start.width, rectHeight - after.width);
  300. verify(graphicsPainter, times(numberOfNonZeroBorders(after, start)))
  301. .lineTo(rectWidth - end.width, rectHeight - after.width);
  302. }
  303. if (start.width > 0) {
  304. verify(graphicsPainter).moveTo(rectX, rectHeight);
  305. verify(graphicsPainter).lineTo(rectX, rectY);
  306. verify(graphicsPainter, times(numberOfNonZeroBorders(start, before)))
  307. .lineTo(rectX + start.width, rectY + before.width);
  308. verify(graphicsPainter, times(numberOfNonZeroBorders(start, after)))
  309. .lineTo(rectX + start.width, rectHeight - after.width);
  310. }
  311. int numBorders = numberOfNonZeroBorders();
  312. verify(graphicsPainter, times(numBorders)).saveGraphicsState();
  313. verify(graphicsPainter, times(numBorders)).closePath();
  314. verify(graphicsPainter, times(numBorders)).restoreGraphicsState();
  315. verify(graphicsPainter, times(numBorders)).clip();
  316. }
  317. @Override
  318. protected DrawRectangularBordersTester getThis() {
  319. return this;
  320. }
  321. }
  322. private static final class DrawRoundedBordersTester extends BorderPainterTester<DrawRoundedBordersTester> {
  323. public DrawRoundedBordersTester(int xOrigin, int yOrigin, int width, int height) throws IOException {
  324. super(xOrigin, yOrigin, width, height);
  325. }
  326. public void testMethod() throws IOException {
  327. sut.drawRoundedBorders(borderExtent, before, after, start, end);
  328. verifyDrawing();
  329. }
  330. private void verifyDrawing() throws IOException {
  331. int numBorders = numberOfNonZeroBorders();
  332. final int rectWidth = borderExtent.width;
  333. final int rectHeight = borderExtent.height;
  334. if (before.width > 0) {
  335. verify(graphicsPainter, atLeastOnce()).lineTo(rectWidth - end.getRadiusStart(), 0);
  336. verify(graphicsPainter, atLeastOnce()).lineTo(calcLineEnd(start.width, before.width,
  337. start.getRadiusStart(), before.getRadiusStart()), before.width);
  338. }
  339. if (end.width > 0) {
  340. verify(graphicsPainter, atLeastOnce()).lineTo(rectHeight - after.getRadiusEnd(), 0);
  341. verify(graphicsPainter, atLeastOnce()).lineTo(calcLineEnd(before.width, end.width,
  342. before.getRadiusEnd(), end.getRadiusStart()), end.width);
  343. }
  344. if (after.width > 0) {
  345. verify(graphicsPainter, atLeastOnce()).lineTo(rectWidth - start.getRadiusEnd(), 0);
  346. verify(graphicsPainter, atLeastOnce()).lineTo(calcLineEnd(start.width, after.width,
  347. start.getRadiusEnd(), after.getRadiusStart()), after.width);
  348. }
  349. if (start.width > 0) {
  350. verify(graphicsPainter, atLeastOnce()).lineTo(rectHeight - after.getRadiusStart(), 0);
  351. verify(graphicsPainter, atLeastOnce()).lineTo(calcLineEnd(before.width, start.width,
  352. before.getRadiusStart(), before.getRadiusStart()), start.width);
  353. }
  354. // verify the drawing of the symmetric rounded corners (the ones that are a quarter of a circle)
  355. // verification is restricted to those since it is too complex in the general case
  356. if (before.width == end.width && before.getRadiusStart() == before.getRadiusEnd()
  357. && end.getRadiusStart() == end.getRadiusEnd()
  358. && before.getRadiusEnd() == end.getRadiusStart() && end.getRadiusStart() > 0) {
  359. verify(graphicsPainter, atLeastOnce()).arcTo(Math.PI * 5 / 4, Math.PI * 3 / 2,
  360. before.getRadiusStart(), end.getRadiusEnd(), before.getRadiusStart(),
  361. end.getRadiusEnd());
  362. }
  363. if (end.width == after.width && end.getRadiusStart() == end.getRadiusEnd()
  364. && after.getRadiusStart() == after.getRadiusEnd()
  365. && end.getRadiusEnd() == after.getRadiusStart() && after.getRadiusStart() > 0) {
  366. verify(graphicsPainter, atLeastOnce()).arcTo(Math.PI * 5 / 4, Math.PI * 3 / 2,
  367. end.getRadiusStart(), after.getRadiusEnd(), end.getRadiusStart(),
  368. after.getRadiusEnd());
  369. }
  370. if (after.width == start.width && after.getRadiusStart() == after.getRadiusEnd()
  371. && start.getRadiusStart() == start.getRadiusEnd()
  372. && after.getRadiusEnd() == start.getRadiusStart() && start.getRadiusStart() > 0) {
  373. verify(graphicsPainter, atLeastOnce()).arcTo(Math.PI * 5 / 4, Math.PI * 3 / 2,
  374. after.getRadiusStart(), start.getRadiusEnd(), after.getRadiusStart(),
  375. start.getRadiusEnd());
  376. }
  377. if (start.width == before.width && start.getRadiusStart() == start.getRadiusEnd()
  378. && before.getRadiusStart() == before.getRadiusEnd()
  379. && start.getRadiusEnd() == before.getRadiusStart() && before.getRadiusStart() > 0) {
  380. verify(graphicsPainter, atLeastOnce()).arcTo(Math.PI * 5 / 4, Math.PI * 3 / 2,
  381. start.getRadiusStart(), before.getRadiusEnd(), start.getRadiusStart(),
  382. before.getRadiusEnd());
  383. }
  384. verify(graphicsPainter, times(numBorders)).saveGraphicsState();
  385. verify(graphicsPainter, times(numBorders)).closePath();
  386. verify(graphicsPainter, times(numBorders)).restoreGraphicsState();
  387. verify(graphicsPainter, times(numBorders)).clip();
  388. }
  389. private int calcLineEnd(int xWidth, int yWidth, int xRadius, int yRadius) {
  390. return yWidth > yRadius ? yWidth : xWidth > 0 ? Math.max(xRadius, xWidth) : 0;
  391. }
  392. @Override
  393. protected DrawRoundedBordersTester getThis() {
  394. return this;
  395. }
  396. }
  397. private static final class ClipBackgroundTester extends BorderPainterTester<ClipBackgroundTester> {
  398. public ClipBackgroundTester(int xOrigin, int yOrigin, int width, int height) throws IOException {
  399. super(xOrigin, yOrigin, width, height);
  400. }
  401. public void testMethod() throws IOException {
  402. sut.clipBackground(borderExtent, before, after, start, end);
  403. verifyClipping();
  404. }
  405. private void verifyClipping() throws IOException {
  406. int xOrigin = borderExtent.x;
  407. int yOrigin = borderExtent.y;
  408. int xEnd = xOrigin + borderExtent.width;
  409. int yEnd = yOrigin + borderExtent.height;
  410. Corner startBeforeCorner = Corner.createStartBeforeCorner(getInnerRadiusStart(start),
  411. getInnerRadiusStart(before));
  412. Corner endBeforeCorner = Corner.createEndBeforeCorner(getInnerRadiusStart(end), getRadiusEnd(before));
  413. Corner endAfterCorner = Corner.createEndAfterCorner(getRadiusEnd(end), getRadiusEnd(after));
  414. Corner startAfterCorner = Corner.createStartAfterCorner(getRadiusEnd(start),
  415. getInnerRadiusStart(after));
  416. verify(graphicsPainter, times(1)).moveTo(xOrigin + startBeforeCorner.xRadius, yOrigin);
  417. verify(graphicsPainter, times(1)).lineTo(xEnd - endBeforeCorner.xRadius, yOrigin);
  418. endBeforeCorner.verifyCornerDrawn(graphicsPainter, xEnd - endBeforeCorner.xRadius,
  419. yOrigin + endBeforeCorner.yRadius);
  420. verify(graphicsPainter, times(1)).lineTo(xEnd, yEnd - endAfterCorner.yRadius);
  421. endAfterCorner.verifyCornerDrawn(graphicsPainter, xEnd - endAfterCorner.xRadius,
  422. yEnd - endAfterCorner.yRadius);
  423. verify(graphicsPainter, times(1)).lineTo(xOrigin + startAfterCorner.xRadius, yEnd);
  424. startAfterCorner.verifyCornerDrawn(graphicsPainter, xOrigin + startAfterCorner.xRadius,
  425. yEnd - startAfterCorner.yRadius);
  426. verify(graphicsPainter, times(1)).lineTo(xOrigin, yOrigin + startBeforeCorner.yRadius);
  427. startBeforeCorner.verifyCornerDrawn(graphicsPainter, xOrigin + startBeforeCorner.xRadius,
  428. yOrigin + startBeforeCorner.yRadius);
  429. verify(graphicsPainter, times(1)).clip();
  430. }
  431. private int getInnerRadiusStart(BorderProps borderProps) {
  432. return getInnerRadius(borderProps.getRadiusStart(), borderProps.width);
  433. }
  434. private int getRadiusEnd(BorderProps borderProps) {
  435. return getInnerRadius(borderProps.getRadiusEnd(), borderProps.width);
  436. }
  437. private int getInnerRadius(int radius, int borderWidth) {
  438. return Math.max(radius - borderWidth, 0);
  439. }
  440. private static class Corner {
  441. public final int xRadius;
  442. public final int yRadius;
  443. private final double startAngle;
  444. private final double endAngle;
  445. public Corner(int xRadius, int yRadius, double startAngle, double endAngle) {
  446. this.xRadius = xRadius;
  447. this.yRadius = yRadius;
  448. this.startAngle = startAngle;
  449. this.endAngle = endAngle;
  450. }
  451. public static Corner createStartBeforeCorner(int xRadius, int yRadius) {
  452. return new Corner(xRadius, yRadius, Math.PI, Math.PI * 3 / 2);
  453. }
  454. public static Corner createEndBeforeCorner(int xRadius, int yRadius) {
  455. return new Corner(xRadius, yRadius, Math.PI * 3 / 2, 0);
  456. }
  457. public static Corner createEndAfterCorner(int xRadius, int yRadius) {
  458. return new Corner(xRadius, yRadius, 0, Math.PI / 2);
  459. }
  460. public static Corner createStartAfterCorner(int xRadius, int yRadius) {
  461. return new Corner(xRadius, yRadius, Math.PI / 2, Math.PI);
  462. }
  463. public void verifyCornerDrawn(GraphicsPainter graphicsPainter, int xCenter, int yCenter)
  464. throws IOException {
  465. if (xRadius != 0 && yRadius != 0) {
  466. verify(graphicsPainter, times(1)).arcTo(startAngle, endAngle,
  467. xCenter, yCenter, xRadius, yRadius);
  468. } else {
  469. verify(graphicsPainter, never()).arcTo(startAngle, endAngle,
  470. xCenter, yCenter, xRadius, yRadius);
  471. }
  472. }
  473. }
  474. @Override
  475. protected ClipBackgroundTester getThis() {
  476. return this;
  477. }
  478. }
  479. }