Skip to content

Commit 8a3a77a

Browse files
committed
Implement supporting background-repeat CSS property
DEVSIX-4370
1 parent ee42409 commit 8a3a77a

29 files changed

+710
-117
lines changed

kernel/src/main/java/com/itextpdf/kernel/geom/Rectangle.java

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -260,24 +260,44 @@ public boolean contains(Rectangle rect) {
260260
/**
261261
* Check if this rectangle and the passed rectangle overlap
262262
*
263-
* @param rect a rectangle which is to be checked if it overlaps the passed rectangle.
263+
* @param rect a rectangle which is to be checked if it overlaps the passed rectangle
264264
* @return true if there is overlap of some kind
265265
*/
266-
public boolean overlaps(Rectangle rect) {
267-
// Two rectangles do not overlap if any of the following holds
268-
// 1. the lower left corner of the second rectangle is to the right of the upper-right corner of the first.
269-
return !((rect.getX() - (this.getX() + this.getWidth()) > EPS)
266+
public boolean overlaps(final Rectangle rect) {
267+
return overlaps(rect, -EPS);
268+
}
270269

271-
// 2. the lower left corner of the second rectangle is above the upper right corner of the first.
272-
|| (rect.getY() - (this.getY() + this.getHeight()) > EPS)
270+
/**
271+
* Check if this rectangle and the passed rectangle overlap
272+
*
273+
* @param rect a rectangle which is to be checked if it overlaps the passed rectangle
274+
* @param epsilon if greater than zero, then this is the maximum distance that one rectangle can go to another, but
275+
* they will not overlap, if less than zero, then this is the minimum required distance between the
276+
* rectangles so that they do not overlap
277+
* @return true if there is overlap of some kind
278+
*/
279+
public boolean overlaps(final Rectangle rect, final float epsilon) {
280+
// Two rectangles do not overlap if any of the following holds
273281

274-
// 3. the upper right corner of the second rectangle is to the left of the lower-left corner of the first.
275-
|| (this.getX() - (rect.getX() + rect.getWidth()) > EPS)
282+
// The first rectangle lies to the left of the second rectangle or touches very slightly
283+
if ((this.getX() + this.getWidth()) < (rect.getX() + epsilon)) {
284+
return false;
285+
}
286+
// The first rectangle lies to the right of the second rectangle or touches very slightly
287+
if ((this.getX() + epsilon) > (rect.getX() + rect.getWidth())) {
288+
return false;
289+
}
276290

277-
// 4. the upper right corner of the second rectangle is below the lower left corner of the first.
278-
|| (this.getY() - (rect.getY() + rect.getHeight()) > EPS)
279-
);
291+
// The first rectangle lies to the bottom of the second rectangle or touches very slightly
292+
if ((this.getY() + this.getHeight()) < (rect.getY() + epsilon)) {
293+
return false;
294+
}
295+
// The first rectangle lies to the top of the second rectangle or touches very slightly
296+
if ((this.getY() + epsilon) > (rect.getY() + rect.getHeight())) {
297+
return false;
298+
}
280299

300+
return true;
281301
}
282302

283303
/**

kernel/src/test/java/com/itextpdf/kernel/geom/RectangleTest.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,68 @@ This file is part of the iText (R) project.
5151
import com.itextpdf.test.annotations.type.UnitTest;
5252

5353
import java.io.ByteArrayOutputStream;
54+
5455
import java.util.ArrayList;
5556
import java.util.Arrays;
5657
import java.util.List;
58+
5759
import org.junit.Assert;
5860
import org.junit.Test;
5961
import org.junit.experimental.categories.Category;
6062

6163
@Category(UnitTest.class)
6264
public class RectangleTest extends ExtendedITextTest {
65+
private static final float OVERLAP_EPSILON = 0.1f;
66+
67+
@Test
68+
public void overlapWithEpsilon() {
69+
Rectangle first = new Rectangle(0, 0, 10, 10);
70+
Rectangle second = new Rectangle(-10, 0, 10.09f, 5);
71+
72+
Assert.assertFalse(first.overlaps(second, OVERLAP_EPSILON));
73+
second.setWidth(10.11f);
74+
Assert.assertTrue(first.overlaps(second, OVERLAP_EPSILON));
75+
76+
second = new Rectangle(5, 9.91f, 5, 5);
77+
Assert.assertFalse(first.overlaps(second, OVERLAP_EPSILON));
78+
second.setY(9.89f);
79+
Assert.assertTrue(first.overlaps(second, OVERLAP_EPSILON));
80+
81+
second = new Rectangle(9.91f, 0, 5, 5);
82+
Assert.assertFalse(first.overlaps(second, OVERLAP_EPSILON));
83+
second.setX(9.89f);
84+
Assert.assertTrue(first.overlaps(second, OVERLAP_EPSILON));
85+
86+
second = new Rectangle(5, -10, 5, 10.09f);
87+
Assert.assertFalse(first.overlaps(second, OVERLAP_EPSILON));
88+
second.setHeight(10.11f);
89+
Assert.assertTrue(first.overlaps(second, OVERLAP_EPSILON));
90+
}
91+
92+
@Test
93+
public void overlapWithNegativeEpsilon() {
94+
Rectangle first = new Rectangle(0, 0, 10, 10);
95+
Rectangle second = new Rectangle(-10, 0, 9.89f, 5);
96+
97+
Assert.assertFalse(first.overlaps(second, -OVERLAP_EPSILON));
98+
second.setWidth(9.91f);
99+
Assert.assertTrue(first.overlaps(second, -OVERLAP_EPSILON));
100+
101+
second = new Rectangle(5, 10.11f, 5, 5);
102+
Assert.assertFalse(first.overlaps(second, -OVERLAP_EPSILON));
103+
second.setY(10.09f);
104+
Assert.assertTrue(first.overlaps(second, -OVERLAP_EPSILON));
105+
106+
second = new Rectangle(10.11f, 0, 5, 5);
107+
Assert.assertFalse(first.overlaps(second, -OVERLAP_EPSILON));
108+
second.setX(10.09f);
109+
Assert.assertTrue(first.overlaps(second, -OVERLAP_EPSILON));
110+
111+
second = new Rectangle(5, -10, 5, 9.89f);
112+
Assert.assertFalse(first.overlaps(second, -OVERLAP_EPSILON));
113+
second.setHeight(9.91f);
114+
Assert.assertTrue(first.overlaps(second, -OVERLAP_EPSILON));
115+
}
63116

64117
@Test
65118
public void rectangleOverlapTest01() {

layout/src/main/java/com/itextpdf/layout/property/BackgroundImage.java

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ This file is part of the iText (R) project.
4646
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
4747
import com.itextpdf.kernel.pdf.xobject.PdfImageXObject;
4848
import com.itextpdf.kernel.pdf.xobject.PdfXObject;
49+
import com.itextpdf.layout.property.BackgroundRepeat.BackgroundRepeatValue;
4950

5051
public class BackgroundImage {
5152

@@ -54,26 +55,30 @@ public class BackgroundImage {
5455
protected PdfXObject image;
5556

5657
/**
57-
* Whether the background repeats in the x dimension.
58+
* Whether the background-repeat value is not {@link BackgroundRepeatValue#NO_REPEAT} for X axis.
5859
*
59-
* @deprecated Replace this field with {@link BackgroundRepeat} instance.
60+
* @deprecated replace this field with {@link BackgroundRepeat} instance
6061
*/
6162
@Deprecated
6263
protected boolean repeatX;
6364

6465
/**
65-
* Whether the background repeats in the y dimension.
66+
* Whether the background-repeat value is not {@link BackgroundRepeatValue#NO_REPEAT} for Y axis.
6667
*
67-
* @deprecated Replace this field with {@link BackgroundRepeat} instance.
68+
* @deprecated replace this field with {@link BackgroundRepeat} instance
6869
*/
6970
@Deprecated
7071
protected boolean repeatY;
72+
7173
protected AbstractLinearGradientBuilder linearGradientBuilder;
7274

7375
private BlendMode blendMode = DEFAULT_BLEND_MODE;
7476

75-
private BackgroundPosition position;
76-
private BackgroundSize backgroundSize;
77+
private BackgroundRepeat repeat;
78+
79+
private final BackgroundPosition position;
80+
81+
private final BackgroundSize backgroundSize;
7782

7883
/**
7984
* Creates a new {@link BackgroundImage} instance.
@@ -89,8 +94,9 @@ protected BackgroundImage(PdfXObject image, BackgroundRepeat repeat, BackgroundP
8994
BackgroundSize backgroundSize, AbstractLinearGradientBuilder linearGradientBuilder,
9095
BlendMode blendMode) {
9196
this.image = image;
92-
this.repeatX = repeat.isRepeatX();
93-
this.repeatY = repeat.isRepeatY();
97+
this.repeatX = !repeat.isNoRepeatOnXAxis();
98+
this.repeatY = !repeat.isNoRepeatOnYAxis();
99+
this.repeat = repeat;
94100
this.position = position;
95101
this.backgroundSize = backgroundSize;
96102
this.linearGradientBuilder = linearGradientBuilder;
@@ -181,8 +187,9 @@ public BackgroundImage(final PdfFormXObject image) {
181187
*/
182188
@Deprecated
183189
public BackgroundImage(final PdfImageXObject image, final boolean repeatX, final boolean repeatY) {
184-
this(image, new BackgroundRepeat(repeatX, repeatY), new BackgroundPosition(), new BackgroundSize(),
185-
null, DEFAULT_BLEND_MODE);
190+
this(image, new BackgroundRepeat(repeatX ? BackgroundRepeatValue.REPEAT : BackgroundRepeatValue.NO_REPEAT,
191+
repeatY ? BackgroundRepeatValue.REPEAT : BackgroundRepeatValue.NO_REPEAT), new BackgroundPosition(),
192+
new BackgroundSize(), null, DEFAULT_BLEND_MODE);
186193
}
187194

188195
/**
@@ -195,8 +202,9 @@ public BackgroundImage(final PdfImageXObject image, final boolean repeatX, final
195202
*/
196203
@Deprecated
197204
public BackgroundImage(final PdfFormXObject image, final boolean repeatX, final boolean repeatY) {
198-
this(image, new BackgroundRepeat(repeatX, repeatY), new BackgroundPosition(), new BackgroundSize(),
199-
null, DEFAULT_BLEND_MODE);
205+
this(image, new BackgroundRepeat(repeatX ? BackgroundRepeatValue.REPEAT : BackgroundRepeatValue.NO_REPEAT,
206+
repeatY ? BackgroundRepeatValue.REPEAT : BackgroundRepeatValue.NO_REPEAT), new BackgroundPosition(),
207+
new BackgroundSize(), null, DEFAULT_BLEND_MODE);
200208
}
201209

202210
/**
@@ -221,8 +229,8 @@ public BackgroundImage(final AbstractLinearGradientBuilder linearGradientBuilder
221229
*/
222230
@Deprecated
223231
public BackgroundImage(final AbstractLinearGradientBuilder linearGradientBuilder, final BlendMode blendMode) {
224-
this(null, new BackgroundRepeat(false, false), new BackgroundPosition(), new BackgroundSize()
225-
, linearGradientBuilder, blendMode);
232+
this(null, new BackgroundRepeat(BackgroundRepeatValue.NO_REPEAT), new BackgroundPosition(),
233+
new BackgroundSize(), linearGradientBuilder, blendMode);
226234
}
227235

228236
public PdfImageXObject getImage() {
@@ -250,10 +258,12 @@ public boolean isBackgroundSpecified() {
250258
return image instanceof PdfFormXObject || image instanceof PdfImageXObject || linearGradientBuilder != null;
251259
}
252260

261+
@Deprecated
253262
public boolean isRepeatX() {
254263
return repeatX;
255264
}
256265

266+
@Deprecated
257267
public boolean isRepeatY() {
258268
return repeatY;
259269
}
@@ -301,6 +311,23 @@ public float getHeight() {
301311
return (float) image.getHeight();
302312
}
303313

314+
/**
315+
* Gets image {@link BackgroundRepeat} instance.
316+
*
317+
* @return the image background repeat
318+
*/
319+
public BackgroundRepeat getRepeat() {
320+
// Remove this if-blocks after removing repeatX and repeatY
321+
if (repeatX == repeat.isNoRepeatOnXAxis()) {
322+
repeat = new BackgroundRepeat(repeatX ? BackgroundRepeatValue.REPEAT : BackgroundRepeatValue.NO_REPEAT, repeat.getYAxisRepeat());
323+
}
324+
if (repeatY == repeat.isNoRepeatOnYAxis()) {
325+
repeat = new BackgroundRepeat(repeat.getXAxisRepeat(), repeatY ? BackgroundRepeatValue.REPEAT : BackgroundRepeatValue.NO_REPEAT);
326+
}
327+
328+
return repeat;
329+
}
330+
304331
/**
305332
* Get the image's blend mode.
306333
*
@@ -349,7 +376,7 @@ public Builder setImage(PdfXObject image) {
349376
*/
350377
public Builder setLinearGradientBuilder(AbstractLinearGradientBuilder linearGradientBuilder) {
351378
this.linearGradientBuilder = linearGradientBuilder;
352-
this.repeat = new BackgroundRepeat(false, false);
379+
this.repeat = new BackgroundRepeat(BackgroundRepeatValue.NO_REPEAT);
353380
this.image = null;
354381
return this;
355382
}

0 commit comments

Comments
 (0)