@@ -57,6 +57,7 @@ This file is part of the iText (R) project.
57
57
import com .itextpdf .layout .property .BackgroundImage ;
58
58
import com .itextpdf .layout .property .BackgroundPosition ;
59
59
import com .itextpdf .layout .property .BackgroundRepeat ;
60
+ import com .itextpdf .layout .property .BackgroundSize ;
60
61
import com .itextpdf .layout .property .BlendMode ;
61
62
import com .itextpdf .layout .property .Property ;
62
63
import com .itextpdf .layout .property .UnitValue ;
@@ -99,34 +100,44 @@ public static void applyBackground(Map<String, String> cssProps, ProcessorContex
99
100
100
101
final String backgroundImagesStr = cssProps .get (CssConstants .BACKGROUND_IMAGE );
101
102
final String backgroundRepeatStr = cssProps .get (CssConstants .BACKGROUND_REPEAT );
103
+ final String backgroundSizeStr = cssProps .get (CssConstants .BACKGROUND_SIZE );
102
104
final String backgroundPositionXStr = cssProps .get (CssConstants .BACKGROUND_POSITION_X );
103
105
final String backgroundPositionYStr = cssProps .get (CssConstants .BACKGROUND_POSITION_Y );
104
106
final String backgroundBlendModeStr = cssProps .get (CssConstants .BACKGROUND_BLEND_MODE );
105
107
106
108
final List <BackgroundImage > backgroundImagesList = new ArrayList <>();
107
109
final List <String > backgroundImagesArray = CssUtils .splitStringWithComma (backgroundImagesStr );
108
110
final List <String > backgroundRepeatArray = CssUtils .splitStringWithComma (backgroundRepeatStr );
111
+ final List <List <String >> backgroundSizeArray = backgroundSizeStr == null ? null
112
+ : CssUtils .extractShorthandProperties (backgroundSizeStr );
109
113
final List <String > backgroundPositionXArray = CssUtils .splitStringWithComma (backgroundPositionXStr );
110
114
final List <String > backgroundPositionYArray = CssUtils .splitStringWithComma (backgroundPositionYStr );
111
115
final List <String > backgroundBlendModeArray = CssUtils .splitStringWithComma (backgroundBlendModeStr );
116
+
117
+ final String fontSize = cssProps .get (CssConstants .FONT_SIZE );
118
+ final float em = fontSize == null ? 0 : CssUtils .parseAbsoluteLength (fontSize );
119
+ final float rem = context .getCssContext ().getRootFontSize ();
120
+
112
121
for (int i = 0 ; i < backgroundImagesArray .size (); ++i ) {
113
122
final String backgroundImage = backgroundImagesArray .get (i );
114
123
if (backgroundImage == null || CssConstants .NONE .equals (backgroundImage )) {
115
124
continue ;
116
125
}
117
-
118
- final String fontSize = cssProps .get (CssConstants .FONT_SIZE );
119
- final float em = fontSize == null ? 0 : CssUtils .parseAbsoluteLength (fontSize );
120
- final float rem = context .getCssContext ().getRootFontSize ();
121
126
final BackgroundPosition position =
122
127
applyBackgroundPosition (backgroundPositionXArray , backgroundPositionYArray , i , em , rem );
123
128
final BlendMode blendMode = applyBackgroundBlendMode (backgroundBlendModeArray , i );
124
-
129
+ boolean imageApplied = false ;
125
130
if (CssGradientUtil .isCssLinearGradientValue (backgroundImage )) {
126
- applyLinearGradient (backgroundImage , backgroundImagesList , blendMode , position , em , rem );
131
+ imageApplied = applyLinearGradient (backgroundImage , backgroundImagesList , blendMode , position , em , rem );
127
132
} else {
128
133
final BackgroundRepeat repeat = applyBackgroundRepeat (backgroundRepeatArray , i );
129
- applyBackgroundImage (context , backgroundImage , backgroundImagesList , repeat , blendMode , position );
134
+ final PdfXObject image = context .getResourceResolver ().retrieveImageExtended (
135
+ CssUtils .extractUrl (backgroundImage ));
136
+ imageApplied = applyBackgroundImage (image , backgroundImagesList , repeat , blendMode , position );
137
+ }
138
+ if (imageApplied ) {
139
+ applyBackgroundSize (backgroundSizeArray , em , rem , i ,
140
+ backgroundImagesList .get (backgroundImagesList .size () - 1 ));
130
141
}
131
142
}
132
143
if (!backgroundImagesList .isEmpty ()) {
@@ -184,11 +195,11 @@ private static BackgroundPosition applyBackgroundPosition(List<String> backgroun
184
195
List <String > backgroundPositionYArray ,
185
196
int i , float em , float rem ) {
186
197
final BackgroundPosition position = new BackgroundPosition ();
187
- final int indexX = getBackgroundSidePropertyIndex (backgroundPositionXArray , i );
198
+ final int indexX = getBackgroundSidePropertyIndex (backgroundPositionXArray . size () , i );
188
199
if (indexX != -1 ) {
189
200
applyBackgroundPositionX (position , backgroundPositionXArray .get (indexX ), em , rem );
190
201
}
191
- final int indexY = getBackgroundSidePropertyIndex (backgroundPositionYArray , i );
202
+ final int indexY = getBackgroundSidePropertyIndex (backgroundPositionYArray . size () , i );
192
203
if (indexY != -1 ) {
193
204
applyBackgroundPositionY (position , backgroundPositionYArray .get (indexY ), em , rem );
194
205
}
@@ -238,7 +249,7 @@ private static void applyBackgroundPositionY(BackgroundPosition position, String
238
249
}
239
250
240
251
private static BackgroundRepeat applyBackgroundRepeat (List <String > backgroundRepeatArray , int iteration ) {
241
- final int index = getBackgroundSidePropertyIndex (backgroundRepeatArray , iteration );
252
+ final int index = getBackgroundSidePropertyIndex (backgroundRepeatArray . size () , iteration );
242
253
if (index != -1 ) {
243
254
final boolean repeatX = CssConstants .REPEAT .equals (backgroundRepeatArray .get (index )) ||
244
255
CssConstants .REPEAT_X .equals (backgroundRepeatArray .get (index ));
@@ -249,13 +260,9 @@ private static BackgroundRepeat applyBackgroundRepeat(List<String> backgroundRep
249
260
return new BackgroundRepeat ();
250
261
}
251
262
252
- private static int getBackgroundSidePropertyIndex (final List <String > backgroundPropertyArray , final int iteration ) {
253
- if (!backgroundPropertyArray .isEmpty ()) {
254
- if (backgroundPropertyArray .size () > iteration ) {
255
- return iteration ;
256
- } else {
257
- return 0 ;
258
- }
263
+ private static int getBackgroundSidePropertyIndex (final int propertiesNumber , final int iteration ) {
264
+ if (propertiesNumber > 0 ) {
265
+ return iteration % propertiesNumber ;
259
266
}
260
267
return -1 ;
261
268
}
@@ -270,39 +277,93 @@ private static void applyBackgroundColor(final String backgroundColorStr, final
270
277
}
271
278
}
272
279
273
- private static void applyBackgroundImage (ProcessorContext context , String backgroundImage ,
274
- List < BackgroundImage > backgroundImagesList , BackgroundRepeat repeat ,
275
- BlendMode backgroundBlendMode , BackgroundPosition position ) {
276
- final PdfXObject image = context . getResourceResolver (). retrieveImageExtended (
277
- CssUtils . extractUrl ( backgroundImage ));
278
- if (image != null ) {
279
- if ( image instanceof PdfImageXObject ) {
280
- backgroundImagesList
281
- . add ( new HtmlBackgroundImage (( PdfImageXObject ) image , repeat , position , backgroundBlendMode )) ;
282
- } else if (image instanceof PdfFormXObject ) {
283
- backgroundImagesList
284
- . add ( new HtmlBackgroundImage (( PdfFormXObject ) image , repeat , position , backgroundBlendMode ));
285
- } else {
286
- throw new IllegalStateException ();
287
- }
280
+ private static boolean applyBackgroundImage (PdfXObject image , List < BackgroundImage > backgroundImagesList ,
281
+ BackgroundRepeat repeat , BlendMode backgroundBlendMode , BackgroundPosition position ) {
282
+ if ( image == null ) {
283
+ return false ;
284
+ }
285
+ if (image instanceof PdfImageXObject ) {
286
+ backgroundImagesList . add ( new HtmlBackgroundImage (( PdfImageXObject ) image , repeat , position ,
287
+ backgroundBlendMode ));
288
+ return true ;
289
+ } else if (image instanceof PdfFormXObject ) {
290
+ backgroundImagesList . add ( new HtmlBackgroundImage (( PdfFormXObject ) image , repeat , position ,
291
+ backgroundBlendMode ));
292
+ return true ;
293
+ } else {
294
+ throw new IllegalStateException ();
288
295
}
289
296
}
290
297
291
- private static void applyLinearGradient (String backgroundImage , List <BackgroundImage > backgroundImagesList ,
292
- BlendMode blendMode , BackgroundPosition position , float em , float rem ) {
298
+ private static boolean applyLinearGradient (String image , List <BackgroundImage > backgroundImagesList ,
299
+ BlendMode blendMode , BackgroundPosition position , float em , float rem ) {
293
300
try {
294
301
StrategyBasedLinearGradientBuilder gradientBuilder =
295
- CssGradientUtil .parseCssLinearGradient (backgroundImage , em , rem );
302
+ CssGradientUtil .parseCssLinearGradient (image , em , rem );
296
303
if (gradientBuilder != null ) {
297
304
backgroundImagesList .add (new BackgroundImage .Builder ().setLinearGradientBuilder (gradientBuilder )
298
305
.setBackgroundBlendMode (blendMode ).setBackgroundPosition (position ).build ());
306
+ return true ;
299
307
}
300
308
} catch (StyledXMLParserException e ) {
301
- LOGGER .warn (MessageFormatUtil .format (
302
- LogMessageConstant .INVALID_GRADIENT_DECLARATION , backgroundImage ));
309
+ LOGGER .warn (MessageFormatUtil .format (LogMessageConstant .INVALID_GRADIENT_DECLARATION , image ));
310
+ }
311
+ return false ;
312
+ }
313
+
314
+ private static void applyBackgroundSize (List <List <String >> backgroundProperties , float em , float rem ,
315
+ int imageIndex , BackgroundImage image ) {
316
+ if (backgroundProperties == null || backgroundProperties .isEmpty ()) {
317
+ return ;
318
+ }
319
+ if (image .getForm () != null && (image .getImageHeight () == 0f || image .getImageWidth () == 0f )) {
320
+ return ;
321
+ }
322
+ List <String > backgroundSizeValues = backgroundProperties
323
+ .get (getBackgroundSidePropertyIndex (backgroundProperties .size (), imageIndex ));
324
+ if (backgroundSizeValues .size () == 2 && CommonCssConstants .AUTO .equals (backgroundSizeValues .get (1 ))) {
325
+ backgroundSizeValues .remove (1 );
326
+ }
327
+ if (backgroundSizeValues .size () == 1 ) {
328
+ String widthValue = backgroundSizeValues .get (0 );
329
+ applyBackgroundWidth (widthValue , image , em , rem );
330
+ }
331
+ if (backgroundSizeValues .size () == 2 ) {
332
+ applyBackgroundWidthHeight (backgroundSizeValues , image , em , rem );
303
333
}
304
334
}
305
335
336
+ private static void applyBackgroundWidth (final String widthValue , final BackgroundImage image ,
337
+ final float em , final float rem ) {
338
+ if (CommonCssConstants .BACKGROUND_SIZE_VALUES .contains (widthValue )) {
339
+ if (widthValue .equals (CommonCssConstants .CONTAIN )) {
340
+ image .getBackgroundSize ().setBackgroundSizeToContain ();
341
+ }
342
+ if (widthValue .equals (CommonCssConstants .COVER )) {
343
+ image .getBackgroundSize ().setBackgroundSizeToCover ();
344
+ }
345
+ return ;
346
+ }
347
+ image .getBackgroundSize ().setBackgroundSizeToValues (CssUtils .parseLengthValueToPt (widthValue , em , rem ), null );
348
+ }
349
+
350
+ private static void applyBackgroundWidthHeight (final List <String > backgroundSizeValues ,
351
+ final BackgroundImage image , final float em , final float rem ) {
352
+ String widthValue = backgroundSizeValues .get (0 );
353
+ if (CommonCssConstants .BACKGROUND_SIZE_VALUES .contains (widthValue )) {
354
+ if (widthValue .equals (CommonCssConstants .AUTO )) {
355
+ UnitValue height = CssUtils .parseLengthValueToPt (backgroundSizeValues .get (1 ), em , rem );
356
+ if (height != null ) {
357
+ image .getBackgroundSize ().setBackgroundSizeToValues (null , height );
358
+ }
359
+ }
360
+ return ;
361
+ }
362
+ image .getBackgroundSize ().setBackgroundSizeToValues (
363
+ CssUtils .parseLengthValueToPt (backgroundSizeValues .get (0 ), em , rem ),
364
+ CssUtils .parseLengthValueToPt (backgroundSizeValues .get (1 ), em , rem ));
365
+ }
366
+
306
367
/**
307
368
* Implementation of the Image class when used in the context of HTML to PDF conversion.
308
369
*/
@@ -327,7 +388,7 @@ private static class HtmlBackgroundImage extends BackgroundImage {
327
388
*/
328
389
public HtmlBackgroundImage (PdfImageXObject xObject ,
329
390
BackgroundRepeat repeat , BackgroundPosition position , BlendMode blendMode ) {
330
- super (xObject , repeat , position , null , blendMode );
391
+ super (xObject , repeat , position , new BackgroundSize (), null , blendMode );
331
392
dimensionMultiplier = PX_TO_PT_MULTIPLIER ;
332
393
}
333
394
@@ -341,7 +402,17 @@ public HtmlBackgroundImage(PdfImageXObject xObject,
341
402
*/
342
403
public HtmlBackgroundImage (PdfFormXObject xObject ,
343
404
BackgroundRepeat repeat , BackgroundPosition position , BlendMode blendMode ) {
344
- super (xObject , repeat , position , null , blendMode );
405
+ super (xObject , repeat , position , new BackgroundSize (), null , blendMode );
406
+ }
407
+
408
+ @ Override
409
+ public float getImageWidth () {
410
+ return (float ) (image .getWidth () * dimensionMultiplier );
411
+ }
412
+
413
+ @ Override
414
+ public float getImageHeight () {
415
+ return (float ) (image .getHeight () * dimensionMultiplier );
345
416
}
346
417
347
418
@ Override
0 commit comments