@@ -48,16 +48,16 @@ This file is part of the iText (R) project.
4848import com .itextpdf .io .util .MessageFormatUtil ;
4949import com .itextpdf .kernel .colors .Color ;
5050import com .itextpdf .kernel .colors .DeviceRgb ;
51+ import com .itextpdf .kernel .colors .gradients .StrategyBasedLinearGradientBuilder ;
5152import com .itextpdf .kernel .pdf .xobject .PdfFormXObject ;
5253import com .itextpdf .kernel .pdf .xobject .PdfImageXObject ;
5354import com .itextpdf .kernel .pdf .xobject .PdfXObject ;
5455import com .itextpdf .layout .IPropertyContainer ;
55- import com .itextpdf .kernel .colors .gradients .StrategyBasedLinearGradientBuilder ;
5656import com .itextpdf .layout .property .Background ;
5757import com .itextpdf .layout .property .BackgroundImage ;
5858import com .itextpdf .layout .property .BackgroundPosition ;
59+ import com .itextpdf .layout .property .BackgroundBox ;
5960import com .itextpdf .layout .property .BackgroundRepeat ;
60- import com .itextpdf .layout .property .BackgroundSize ;
6161import com .itextpdf .layout .property .BlendMode ;
6262import com .itextpdf .layout .property .BackgroundRepeat .BackgroundRepeatValue ;
6363import 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