@@ -48,16 +48,16 @@ This file is part of the iText (R) project.
48
48
import com .itextpdf .io .util .MessageFormatUtil ;
49
49
import com .itextpdf .kernel .colors .Color ;
50
50
import com .itextpdf .kernel .colors .DeviceRgb ;
51
+ import com .itextpdf .kernel .colors .gradients .StrategyBasedLinearGradientBuilder ;
51
52
import com .itextpdf .kernel .pdf .xobject .PdfFormXObject ;
52
53
import com .itextpdf .kernel .pdf .xobject .PdfImageXObject ;
53
54
import com .itextpdf .kernel .pdf .xobject .PdfXObject ;
54
55
import com .itextpdf .layout .IPropertyContainer ;
55
- import com .itextpdf .kernel .colors .gradients .StrategyBasedLinearGradientBuilder ;
56
56
import com .itextpdf .layout .property .Background ;
57
57
import com .itextpdf .layout .property .BackgroundImage ;
58
58
import com .itextpdf .layout .property .BackgroundPosition ;
59
+ import com .itextpdf .layout .property .BackgroundBox ;
59
60
import com .itextpdf .layout .property .BackgroundRepeat ;
60
- import com .itextpdf .layout .property .BackgroundSize ;
61
61
import com .itextpdf .layout .property .BlendMode ;
62
62
import com .itextpdf .layout .property .BackgroundRepeat .BackgroundRepeatValue ;
63
63
import com .itextpdf .layout .property .Property ;
@@ -98,16 +98,15 @@ private BackgroundApplierUtil() {
98
98
public static void applyBackground (Map <String , String > cssProps , ProcessorContext context ,
99
99
IPropertyContainer element ) {
100
100
final String backgroundColorStr = cssProps .get (CssConstants .BACKGROUND_COLOR );
101
- applyBackgroundColor (backgroundColorStr , element );
102
-
103
101
final String backgroundImagesStr = cssProps .get (CssConstants .BACKGROUND_IMAGE );
104
102
final String backgroundRepeatStr = cssProps .get (CssConstants .BACKGROUND_REPEAT );
105
103
final String backgroundSizeStr = cssProps .get (CssConstants .BACKGROUND_SIZE );
106
104
final String backgroundPositionXStr = cssProps .get (CssConstants .BACKGROUND_POSITION_X );
107
105
final String backgroundPositionYStr = cssProps .get (CssConstants .BACKGROUND_POSITION_Y );
108
106
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 );
109
109
110
- final List <BackgroundImage > backgroundImagesList = new ArrayList <>();
111
110
final List <String > backgroundImagesArray = CssUtils .splitStringWithComma (backgroundImagesStr );
112
111
final List <String > backgroundRepeatArray = CssUtils .splitStringWithComma (backgroundRepeatStr );
113
112
final List <List <String >> backgroundSizeArray = backgroundSizeStr == null ? null
@@ -120,29 +119,16 @@ public static void applyBackground(Map<String, String> cssProps, ProcessorContex
120
119
final float em = fontSize == null ? 0 : CssUtils .parseAbsoluteLength (fontSize );
121
120
final float rem = context .getCssContext ().getRootFontSize ();
122
121
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 );
133
124
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 );
146
132
if (!backgroundImagesList .isEmpty ()) {
147
133
element .setProperty (Property .BACKGROUND_IMAGE , backgroundImagesList );
148
134
}
@@ -183,6 +169,67 @@ static String[] splitStringWithComma(final String value) {
183
169
return resultList .toArray (new String [0 ]);
184
170
}
185
171
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
+
186
233
private static BlendMode applyBackgroundBlendMode (final List <String > backgroundBlendModeArray ,
187
234
final int iteration ) {
188
235
String cssValue = null ;
@@ -277,46 +324,51 @@ private static BackgroundRepeat applyBackgroundRepeat(List<String> backgroundRep
277
324
private static int getBackgroundSidePropertyIndex (final int propertiesNumber , final int iteration ) {
278
325
if (propertiesNumber > 0 ) {
279
326
return iteration % propertiesNumber ;
327
+ } else {
328
+ return -1 ;
280
329
}
281
- return -1 ;
282
330
}
283
331
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 ) {
285
334
if (backgroundColorStr != null && !CssConstants .TRANSPARENT .equals (backgroundColorStr )) {
286
335
float [] rgbaColor = CssUtils .parseRgbaColor (backgroundColorStr );
287
336
Color color = new DeviceRgb (rgbaColor [0 ], rgbaColor [1 ], rgbaColor [2 ]);
288
337
float opacity = rgbaColor [3 ];
289
- Background backgroundColor = new Background (color , opacity );
338
+ final Background backgroundColor = new Background (color , opacity , clip );
290
339
element .setProperty (Property .BACKGROUND , backgroundColor );
291
340
}
292
341
}
293
342
294
343
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 ) {
296
346
if (image == null ) {
297
347
return false ;
298
348
}
299
349
if (image instanceof PdfImageXObject ) {
300
350
backgroundImagesList .add (new HtmlBackgroundImage ((PdfImageXObject ) image , repeat , position ,
301
- backgroundBlendMode ));
351
+ backgroundBlendMode , clip , origin ));
302
352
return true ;
303
353
} else if (image instanceof PdfFormXObject ) {
304
354
backgroundImagesList .add (new HtmlBackgroundImage ((PdfFormXObject ) image , repeat , position ,
305
- backgroundBlendMode ));
355
+ backgroundBlendMode , clip , origin ));
306
356
return true ;
307
357
} else {
308
358
throw new IllegalStateException ();
309
359
}
310
360
}
311
361
312
362
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 ) {
314
365
try {
315
366
StrategyBasedLinearGradientBuilder gradientBuilder =
316
367
CssGradientUtil .parseCssLinearGradient (image , em , rem );
317
368
if (gradientBuilder != null ) {
318
369
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 ());
320
372
return true ;
321
373
}
322
374
} catch (StyledXMLParserException e ) {
@@ -399,10 +451,15 @@ private static class HtmlBackgroundImage extends BackgroundImage {
399
451
* @param repeat background-repeat property. {@link BackgroundRepeat} instance.
400
452
* @param position background-position property. {@link BackgroundPosition} instance.
401
453
* @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.
402
456
*/
403
457
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 ());
406
463
dimensionMultiplier = PX_TO_PT_MULTIPLIER ;
407
464
}
408
465
@@ -413,10 +470,15 @@ public HtmlBackgroundImage(PdfImageXObject xObject,
413
470
* @param repeat background-repeat property. {@link BackgroundRepeat} instance.
414
471
* @param position background-position property. {@link BackgroundPosition} instance.
415
472
* @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.
416
475
*/
417
476
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 ());
420
482
}
421
483
422
484
@ Override
0 commit comments