@@ -57,6 +57,7 @@ This file is part of the iText (R) project.
5757import com .itextpdf .layout .property .BackgroundImage ;
5858import com .itextpdf .layout .property .BackgroundPosition ;
5959import com .itextpdf .layout .property .BackgroundRepeat ;
60+ import com .itextpdf .layout .property .BackgroundSize ;
6061import com .itextpdf .layout .property .BlendMode ;
6162import com .itextpdf .layout .property .Property ;
6263import com .itextpdf .layout .property .UnitValue ;
@@ -99,34 +100,44 @@ public static void applyBackground(Map<String, String> cssProps, ProcessorContex
99100
100101 final String backgroundImagesStr = cssProps .get (CssConstants .BACKGROUND_IMAGE );
101102 final String backgroundRepeatStr = cssProps .get (CssConstants .BACKGROUND_REPEAT );
103+ final String backgroundSizeStr = cssProps .get (CssConstants .BACKGROUND_SIZE );
102104 final String backgroundPositionXStr = cssProps .get (CssConstants .BACKGROUND_POSITION_X );
103105 final String backgroundPositionYStr = cssProps .get (CssConstants .BACKGROUND_POSITION_Y );
104106 final String backgroundBlendModeStr = cssProps .get (CssConstants .BACKGROUND_BLEND_MODE );
105107
106108 final List <BackgroundImage > backgroundImagesList = new ArrayList <>();
107109 final List <String > backgroundImagesArray = CssUtils .splitStringWithComma (backgroundImagesStr );
108110 final List <String > backgroundRepeatArray = CssUtils .splitStringWithComma (backgroundRepeatStr );
111+ final List <List <String >> backgroundSizeArray = backgroundSizeStr == null ? null
112+ : CssUtils .extractShorthandProperties (backgroundSizeStr );
109113 final List <String > backgroundPositionXArray = CssUtils .splitStringWithComma (backgroundPositionXStr );
110114 final List <String > backgroundPositionYArray = CssUtils .splitStringWithComma (backgroundPositionYStr );
111115 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+
112121 for (int i = 0 ; i < backgroundImagesArray .size (); ++i ) {
113122 final String backgroundImage = backgroundImagesArray .get (i );
114123 if (backgroundImage == null || CssConstants .NONE .equals (backgroundImage )) {
115124 continue ;
116125 }
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 ();
121126 final BackgroundPosition position =
122127 applyBackgroundPosition (backgroundPositionXArray , backgroundPositionYArray , i , em , rem );
123128 final BlendMode blendMode = applyBackgroundBlendMode (backgroundBlendModeArray , i );
124-
129+ boolean imageApplied = false ;
125130 if (CssGradientUtil .isCssLinearGradientValue (backgroundImage )) {
126- applyLinearGradient (backgroundImage , backgroundImagesList , blendMode , position , em , rem );
131+ imageApplied = applyLinearGradient (backgroundImage , backgroundImagesList , blendMode , position , em , rem );
127132 } else {
128133 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 ));
130141 }
131142 }
132143 if (!backgroundImagesList .isEmpty ()) {
@@ -184,11 +195,11 @@ private static BackgroundPosition applyBackgroundPosition(List<String> backgroun
184195 List <String > backgroundPositionYArray ,
185196 int i , float em , float rem ) {
186197 final BackgroundPosition position = new BackgroundPosition ();
187- final int indexX = getBackgroundSidePropertyIndex (backgroundPositionXArray , i );
198+ final int indexX = getBackgroundSidePropertyIndex (backgroundPositionXArray . size () , i );
188199 if (indexX != -1 ) {
189200 applyBackgroundPositionX (position , backgroundPositionXArray .get (indexX ), em , rem );
190201 }
191- final int indexY = getBackgroundSidePropertyIndex (backgroundPositionYArray , i );
202+ final int indexY = getBackgroundSidePropertyIndex (backgroundPositionYArray . size () , i );
192203 if (indexY != -1 ) {
193204 applyBackgroundPositionY (position , backgroundPositionYArray .get (indexY ), em , rem );
194205 }
@@ -238,7 +249,7 @@ private static void applyBackgroundPositionY(BackgroundPosition position, String
238249 }
239250
240251 private static BackgroundRepeat applyBackgroundRepeat (List <String > backgroundRepeatArray , int iteration ) {
241- final int index = getBackgroundSidePropertyIndex (backgroundRepeatArray , iteration );
252+ final int index = getBackgroundSidePropertyIndex (backgroundRepeatArray . size () , iteration );
242253 if (index != -1 ) {
243254 final boolean repeatX = CssConstants .REPEAT .equals (backgroundRepeatArray .get (index )) ||
244255 CssConstants .REPEAT_X .equals (backgroundRepeatArray .get (index ));
@@ -249,13 +260,9 @@ private static BackgroundRepeat applyBackgroundRepeat(List<String> backgroundRep
249260 return new BackgroundRepeat ();
250261 }
251262
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 ;
259266 }
260267 return -1 ;
261268 }
@@ -270,39 +277,93 @@ private static void applyBackgroundColor(final String backgroundColorStr, final
270277 }
271278 }
272279
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 ();
288295 }
289296 }
290297
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 ) {
293300 try {
294301 StrategyBasedLinearGradientBuilder gradientBuilder =
295- CssGradientUtil .parseCssLinearGradient (backgroundImage , em , rem );
302+ CssGradientUtil .parseCssLinearGradient (image , em , rem );
296303 if (gradientBuilder != null ) {
297304 backgroundImagesList .add (new BackgroundImage .Builder ().setLinearGradientBuilder (gradientBuilder )
298305 .setBackgroundBlendMode (blendMode ).setBackgroundPosition (position ).build ());
306+ return true ;
299307 }
300308 } 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 );
303333 }
304334 }
305335
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+
306367 /**
307368 * Implementation of the Image class when used in the context of HTML to PDF conversion.
308369 */
@@ -327,7 +388,7 @@ private static class HtmlBackgroundImage extends BackgroundImage {
327388 */
328389 public HtmlBackgroundImage (PdfImageXObject xObject ,
329390 BackgroundRepeat repeat , BackgroundPosition position , BlendMode blendMode ) {
330- super (xObject , repeat , position , null , blendMode );
391+ super (xObject , repeat , position , new BackgroundSize (), null , blendMode );
331392 dimensionMultiplier = PX_TO_PT_MULTIPLIER ;
332393 }
333394
@@ -341,7 +402,17 @@ public HtmlBackgroundImage(PdfImageXObject xObject,
341402 */
342403 public HtmlBackgroundImage (PdfFormXObject xObject ,
343404 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 );
345416 }
346417
347418 @ Override
0 commit comments