Skip to content

Commit 308db0c

Browse files
ar3emiText-CI
authored andcommitted
Add support of background-clip and background-origin
DEVSIX-2105
1 parent 0490d6d commit 308db0c

File tree

256 files changed

+1920
-185
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

256 files changed

+1920
-185
lines changed

src/main/java/com/itextpdf/html2pdf/css/apply/util/BackgroundApplierUtil.java

Lines changed: 101 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,16 @@ This file is part of the iText (R) project.
4848
import com.itextpdf.io.util.MessageFormatUtil;
4949
import com.itextpdf.kernel.colors.Color;
5050
import com.itextpdf.kernel.colors.DeviceRgb;
51+
import com.itextpdf.kernel.colors.gradients.StrategyBasedLinearGradientBuilder;
5152
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
5253
import com.itextpdf.kernel.pdf.xobject.PdfImageXObject;
5354
import com.itextpdf.kernel.pdf.xobject.PdfXObject;
5455
import com.itextpdf.layout.IPropertyContainer;
55-
import com.itextpdf.kernel.colors.gradients.StrategyBasedLinearGradientBuilder;
5656
import com.itextpdf.layout.property.Background;
5757
import com.itextpdf.layout.property.BackgroundImage;
5858
import com.itextpdf.layout.property.BackgroundPosition;
59+
import com.itextpdf.layout.property.BackgroundBox;
5960
import com.itextpdf.layout.property.BackgroundRepeat;
60-
import com.itextpdf.layout.property.BackgroundSize;
6161
import com.itextpdf.layout.property.BlendMode;
6262
import com.itextpdf.layout.property.BackgroundRepeat.BackgroundRepeatValue;
6363
import com.itextpdf.layout.property.Property;
@@ -98,16 +98,15 @@ private BackgroundApplierUtil() {
9898
public static void applyBackground(Map<String, String> cssProps, ProcessorContext context,
9999
IPropertyContainer element) {
100100
final String backgroundColorStr = cssProps.get(CssConstants.BACKGROUND_COLOR);
101-
applyBackgroundColor(backgroundColorStr, element);
102-
103101
final String backgroundImagesStr = cssProps.get(CssConstants.BACKGROUND_IMAGE);
104102
final String backgroundRepeatStr = cssProps.get(CssConstants.BACKGROUND_REPEAT);
105103
final String backgroundSizeStr = cssProps.get(CssConstants.BACKGROUND_SIZE);
106104
final String backgroundPositionXStr = cssProps.get(CssConstants.BACKGROUND_POSITION_X);
107105
final String backgroundPositionYStr = cssProps.get(CssConstants.BACKGROUND_POSITION_Y);
108106
final String backgroundBlendModeStr = cssProps.get(CssConstants.BACKGROUND_BLEND_MODE);
107+
final String backgroundClipStr = cssProps.get(CssConstants.BACKGROUND_CLIP);
108+
final String backgroundOriginStr = cssProps.get(CssConstants.BACKGROUND_ORIGIN);
109109

110-
final List<BackgroundImage> backgroundImagesList = new ArrayList<>();
111110
final List<String> backgroundImagesArray = CssUtils.splitStringWithComma(backgroundImagesStr);
112111
final List<String> backgroundRepeatArray = CssUtils.splitStringWithComma(backgroundRepeatStr);
113112
final List<List<String>> backgroundSizeArray = backgroundSizeStr == null ? null
@@ -120,29 +119,16 @@ public static void applyBackground(Map<String, String> cssProps, ProcessorContex
120119
final float em = fontSize == null ? 0 : CssUtils.parseAbsoluteLength(fontSize);
121120
final float rem = context.getCssContext().getRootFontSize();
122121

123-
for (int i = 0; i < backgroundImagesArray.size(); ++i) {
124-
final String backgroundImage = backgroundImagesArray.get(i);
125-
if (backgroundImage == null || CssConstants.NONE.equals(backgroundImage)) {
126-
continue;
127-
}
128-
final BackgroundPosition position =
129-
applyBackgroundPosition(backgroundPositionXArray, backgroundPositionYArray, i, em, rem);
130-
final BlendMode blendMode = applyBackgroundBlendMode(backgroundBlendModeArray, i);
131-
boolean imageApplied = false;
132-
final BackgroundRepeat repeat = applyBackgroundRepeat(backgroundRepeatArray, i);
122+
final List<String> backgroundClipArray = CssUtils.splitStringWithComma(backgroundClipStr);
123+
final List<String> backgroundOriginArray = CssUtils.splitStringWithComma(backgroundOriginStr);
133124

134-
if (CssGradientUtil.isCssLinearGradientValue(backgroundImage)) {
135-
imageApplied = applyLinearGradient(backgroundImage, backgroundImagesList, blendMode, position, em, rem, repeat);
136-
} else {
137-
final PdfXObject image = context.getResourceResolver().retrieveImageExtended(
138-
CssUtils.extractUrl(backgroundImage));
139-
imageApplied = applyBackgroundImage(image, backgroundImagesList, repeat, blendMode, position);
140-
}
141-
if (imageApplied) {
142-
applyBackgroundSize(backgroundSizeArray, em, rem, i,
143-
backgroundImagesList.get(backgroundImagesList.size() - 1));
144-
}
145-
}
125+
final BackgroundBox clipForColor = getBackgroundBoxProperty(backgroundClipArray,
126+
backgroundImagesArray.isEmpty() ? 0 : (backgroundImagesArray.size() - 1), BackgroundBox.BORDER_BOX);
127+
applyBackgroundColor(backgroundColorStr, element, clipForColor);
128+
129+
final List<BackgroundImage> backgroundImagesList = getBackgroundImagesList(backgroundImagesArray, context, em,
130+
rem, backgroundPositionXArray, backgroundPositionYArray, backgroundSizeArray, backgroundBlendModeArray,
131+
backgroundRepeatArray, backgroundClipArray, backgroundOriginArray);
146132
if (!backgroundImagesList.isEmpty()) {
147133
element.setProperty(Property.BACKGROUND_IMAGE, backgroundImagesList);
148134
}
@@ -183,6 +169,67 @@ static String[] splitStringWithComma(final String value) {
183169
return resultList.toArray(new String[0]);
184170
}
185171

172+
private static List<BackgroundImage> getBackgroundImagesList(List<String> backgroundImagesArray,
173+
ProcessorContext context, float em, float rem,
174+
List<String> backgroundPositionXArray, List<String> backgroundPositionYArray,
175+
List<List<String>> backgroundSizeArray, List<String> backgroundBlendModeArray,
176+
List<String> backgroundRepeatArray, List<String> backgroundClipArray,
177+
List<String> backgroundOriginArray) {
178+
final List<BackgroundImage> backgroundImagesList = new ArrayList<>();
179+
180+
for (int i = 0; i < backgroundImagesArray.size(); ++i) {
181+
final String backgroundImage = backgroundImagesArray.get(i);
182+
if (backgroundImage == null || CssConstants.NONE.equals(backgroundImage)) {
183+
continue;
184+
}
185+
final BackgroundPosition position =
186+
applyBackgroundPosition(backgroundPositionXArray, backgroundPositionYArray, i, em, rem);
187+
final BlendMode blendMode = applyBackgroundBlendMode(backgroundBlendModeArray, i);
188+
boolean imageApplied = false;
189+
final BackgroundRepeat repeat = applyBackgroundRepeat(backgroundRepeatArray, i);
190+
191+
final BackgroundBox clip = getBackgroundBoxProperty(backgroundClipArray, i,
192+
BackgroundBox.BORDER_BOX);
193+
final BackgroundBox origin = getBackgroundBoxProperty(backgroundOriginArray, i,
194+
BackgroundBox.PADDING_BOX);
195+
196+
if (CssGradientUtil.isCssLinearGradientValue(backgroundImage)) {
197+
imageApplied = applyLinearGradient(backgroundImage, backgroundImagesList, blendMode, position, em, rem,
198+
repeat, clip, origin);
199+
} else {
200+
final PdfXObject image = context.getResourceResolver().retrieveImageExtended(
201+
CssUtils.extractUrl(backgroundImage));
202+
imageApplied = applyBackgroundImage(image, backgroundImagesList, repeat, blendMode, position, clip,
203+
origin);
204+
}
205+
if (imageApplied) {
206+
applyBackgroundSize(backgroundSizeArray, em, rem, i,
207+
backgroundImagesList.get(backgroundImagesList.size() - 1));
208+
}
209+
}
210+
return backgroundImagesList;
211+
}
212+
213+
private static BackgroundBox getBackgroundBoxProperty(final List<String> propertyArray,
214+
final int iteration, BackgroundBox defaultValue) {
215+
final int index = getBackgroundSidePropertyIndex(propertyArray.size(), iteration);
216+
if (index == -1) {
217+
return defaultValue;
218+
} else {
219+
return getBackgroundBoxPropertyByString(propertyArray.get(index));
220+
}
221+
}
222+
223+
private static BackgroundBox getBackgroundBoxPropertyByString(String box) {
224+
if (CommonCssConstants.PADDING_BOX.equals(box)) {
225+
return BackgroundBox.PADDING_BOX;
226+
} else if (CommonCssConstants.CONTENT_BOX.equals(box)) {
227+
return BackgroundBox.CONTENT_BOX;
228+
} else {
229+
return BackgroundBox.BORDER_BOX;
230+
}
231+
}
232+
186233
private static BlendMode applyBackgroundBlendMode(final List<String> backgroundBlendModeArray,
187234
final int iteration) {
188235
String cssValue = null;
@@ -277,46 +324,51 @@ private static BackgroundRepeat applyBackgroundRepeat(List<String> backgroundRep
277324
private static int getBackgroundSidePropertyIndex(final int propertiesNumber, final int iteration) {
278325
if (propertiesNumber > 0) {
279326
return iteration % propertiesNumber;
327+
} else {
328+
return -1;
280329
}
281-
return -1;
282330
}
283331

284-
private static void applyBackgroundColor(final String backgroundColorStr, final IPropertyContainer element) {
332+
private static void applyBackgroundColor(final String backgroundColorStr, final IPropertyContainer element,
333+
BackgroundBox clip) {
285334
if (backgroundColorStr != null && !CssConstants.TRANSPARENT.equals(backgroundColorStr)) {
286335
float[] rgbaColor = CssUtils.parseRgbaColor(backgroundColorStr);
287336
Color color = new DeviceRgb(rgbaColor[0], rgbaColor[1], rgbaColor[2]);
288337
float opacity = rgbaColor[3];
289-
Background backgroundColor = new Background(color, opacity);
338+
final Background backgroundColor = new Background(color, opacity, clip);
290339
element.setProperty(Property.BACKGROUND, backgroundColor);
291340
}
292341
}
293342

294343
private static boolean applyBackgroundImage(PdfXObject image, List<BackgroundImage> backgroundImagesList,
295-
BackgroundRepeat repeat, BlendMode backgroundBlendMode, BackgroundPosition position) {
344+
BackgroundRepeat repeat, BlendMode backgroundBlendMode, BackgroundPosition position, BackgroundBox clip,
345+
BackgroundBox origin) {
296346
if (image == null) {
297347
return false;
298348
}
299349
if (image instanceof PdfImageXObject) {
300350
backgroundImagesList.add(new HtmlBackgroundImage((PdfImageXObject) image, repeat, position,
301-
backgroundBlendMode));
351+
backgroundBlendMode, clip, origin));
302352
return true;
303353
} else if (image instanceof PdfFormXObject) {
304354
backgroundImagesList.add(new HtmlBackgroundImage((PdfFormXObject) image, repeat, position,
305-
backgroundBlendMode));
355+
backgroundBlendMode, clip, origin));
306356
return true;
307357
} else {
308358
throw new IllegalStateException();
309359
}
310360
}
311361

312362
private static boolean applyLinearGradient(String image, List<BackgroundImage> backgroundImagesList,
313-
BlendMode blendMode, BackgroundPosition position, float em, float rem, final BackgroundRepeat repeat) {
363+
BlendMode blendMode, BackgroundPosition position, float em, float rem, final BackgroundRepeat repeat,
364+
BackgroundBox clip, BackgroundBox origin) {
314365
try {
315366
StrategyBasedLinearGradientBuilder gradientBuilder =
316367
CssGradientUtil.parseCssLinearGradient(image, em, rem);
317368
if (gradientBuilder != null) {
318369
backgroundImagesList.add(new BackgroundImage.Builder().setLinearGradientBuilder(gradientBuilder)
319-
.setBackgroundBlendMode(blendMode).setBackgroundPosition(position).setBackgroundRepeat(repeat).build());
370+
.setBackgroundBlendMode(blendMode).setBackgroundPosition(position).setBackgroundRepeat(repeat)
371+
.setBackgroundClip(clip).setBackgroundOrigin(origin).build());
320372
return true;
321373
}
322374
} catch (StyledXMLParserException e) {
@@ -399,10 +451,15 @@ private static class HtmlBackgroundImage extends BackgroundImage {
399451
* @param repeat background-repeat property. {@link BackgroundRepeat} instance.
400452
* @param position background-position property. {@link BackgroundPosition} instance.
401453
* @param blendMode background-blend-mode property. {@link BlendMode} instance.
454+
* @param clip background-clip property. {@link BackgroundBox} instance.
455+
* @param origin background-origin property. {@link BackgroundBox} instance.
402456
*/
403457
public HtmlBackgroundImage(PdfImageXObject xObject,
404-
BackgroundRepeat repeat, BackgroundPosition position, BlendMode blendMode) {
405-
super(xObject, repeat, position, new BackgroundSize(), null, blendMode);
458+
BackgroundRepeat repeat, BackgroundPosition position, BlendMode blendMode,
459+
BackgroundBox clip, BackgroundBox origin) {
460+
super(new BackgroundImage.Builder().setImage(xObject).setBackgroundRepeat(repeat)
461+
.setBackgroundPosition(position).setBackgroundBlendMode(blendMode).setBackgroundClip(clip)
462+
.setBackgroundOrigin(origin).build());
406463
dimensionMultiplier = PX_TO_PT_MULTIPLIER;
407464
}
408465

@@ -413,10 +470,15 @@ public HtmlBackgroundImage(PdfImageXObject xObject,
413470
* @param repeat background-repeat property. {@link BackgroundRepeat} instance.
414471
* @param position background-position property. {@link BackgroundPosition} instance.
415472
* @param blendMode background-blend-mode property. {@link BlendMode} instance.
473+
* @param clip background-clip property. {@link BackgroundBox} instance.
474+
* @param origin background-origin property. {@link BackgroundBox} instance.
416475
*/
417476
public HtmlBackgroundImage(PdfFormXObject xObject,
418-
BackgroundRepeat repeat, BackgroundPosition position, BlendMode blendMode) {
419-
super(xObject, repeat, position, new BackgroundSize(), null, blendMode);
477+
BackgroundRepeat repeat, BackgroundPosition position, BlendMode blendMode,
478+
BackgroundBox clip, BackgroundBox origin) {
479+
super(new BackgroundImage.Builder().setImage(xObject).setBackgroundRepeat(repeat)
480+
.setBackgroundPosition(position).setBackgroundBlendMode(blendMode).setBackgroundClip(clip)
481+
.setBackgroundOrigin(origin).build());
420482
}
421483

422484
@Override

0 commit comments

Comments
 (0)