diff --git a/itext.tests/itext.layout.tests/itext/layout/properties/BackgroundImageTest.cs b/itext.tests/itext.layout.tests/itext/layout/properties/BackgroundImageTest.cs
index e0a1a44816..213a55e157 100644
--- a/itext.tests/itext.layout.tests/itext/layout/properties/BackgroundImageTest.cs
+++ b/itext.tests/itext.layout.tests/itext/layout/properties/BackgroundImageTest.cs
@@ -41,10 +41,12 @@ You should have received a copy of the GNU Affero General Public License
namespace iText.Layout.Properties {
[NUnit.Framework.Category("IntegrationTest")]
public class BackgroundImageTest : ExtendedITextTest {
- public static readonly String SOURCE_FOLDER = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext
+ private const float DELTA = 0.0001f;
+
+ private static readonly String SOURCE_FOLDER = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext
.CurrentContext.TestDirectory) + "/resources/itext/layout/BackgroundImageTest/";
- public static readonly String DESTINATION_FOLDER = NUnit.Framework.TestContext.CurrentContext.TestDirectory
+ private static readonly String DESTINATION_FOLDER = NUnit.Framework.TestContext.CurrentContext.TestDirectory
+ "/test/itext/layout/BackgroundImageTest/";
[NUnit.Framework.OneTimeSetUp]
@@ -623,6 +625,58 @@ public virtual void BackgroundImageWithLinearGradientAndLuminosityBlendModeTest(
BlendModeTest(BlendMode.LUMINOSITY);
}
+ [NUnit.Framework.Test]
+ public virtual void CalculateImageSizeTest() {
+ PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.Create(SOURCE_FOLDER + "pattern-grg-rrg-rgg.png"
+ ));
+ iText.Layout.Properties.BackgroundImage backgroundImage = new BackgroundImage.Builder().SetImage(xObject).
+ Build();
+ float[] widthAndHeight = backgroundImage.CalculateBackgroundImageSize(200f, 300f);
+ iText.Test.TestUtil.AreEqual(new float[] { 45f, 45f }, widthAndHeight, DELTA);
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void CalculateImageSizeWithCoverPropertyTest() {
+ PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.Create(SOURCE_FOLDER + "pattern-grg-rrg-rgg.png"
+ ));
+ iText.Layout.Properties.BackgroundImage backgroundImage = new BackgroundImage.Builder().SetImage(xObject).
+ Build();
+ backgroundImage.GetBackgroundSize().SetBackgroundSizeToCover();
+ float[] widthAndHeight = backgroundImage.CalculateBackgroundImageSize(200f, 300f);
+ iText.Test.TestUtil.AreEqual(new float[] { 300f, 300f }, widthAndHeight, DELTA);
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void CalculateSizeWithContainPropertyTest() {
+ PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.Create(SOURCE_FOLDER + "pattern-grg-rrg-rgg.png"
+ ));
+ iText.Layout.Properties.BackgroundImage backgroundImage = new BackgroundImage.Builder().SetImage(xObject).
+ Build();
+ backgroundImage.GetBackgroundSize().SetBackgroundSizeToContain();
+ float[] widthAndHeight = backgroundImage.CalculateBackgroundImageSize(200f, 300f);
+ iText.Test.TestUtil.AreEqual(new float[] { 200f, 200.000015f }, widthAndHeight, DELTA);
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void CalculateSizeWithContainAndImageWeightMoreThatHeightTest() {
+ PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.Create(SOURCE_FOLDER + "itis.jpg"));
+ iText.Layout.Properties.BackgroundImage backgroundImage = new BackgroundImage.Builder().SetImage(xObject).
+ Build();
+ backgroundImage.GetBackgroundSize().SetBackgroundSizeToContain();
+ float[] widthAndHeight = backgroundImage.CalculateBackgroundImageSize(200f, 300f);
+ iText.Test.TestUtil.AreEqual(new float[] { 200f, 112.5f }, widthAndHeight, DELTA);
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void CalculateSizeWithCoverAndImageWeightMoreThatHeightTest() {
+ PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.Create(SOURCE_FOLDER + "itis.jpg"));
+ iText.Layout.Properties.BackgroundImage backgroundImage = new BackgroundImage.Builder().SetImage(xObject).
+ Build();
+ backgroundImage.GetBackgroundSize().SetBackgroundSizeToCover();
+ float[] widthAndHeight = backgroundImage.CalculateBackgroundImageSize(200f, 300f);
+ iText.Test.TestUtil.AreEqual(new float[] { 533.3333f, 300f }, widthAndHeight, DELTA);
+ }
+
private void BlendModeTest(BlendMode blendMode) {
AbstractLinearGradientBuilder gradientBuilder = new StrategyBasedLinearGradientBuilder().AddColorStop(new
GradientColorStop(ColorConstants.BLACK.GetColorValue())).AddColorStop(new GradientColorStop(ColorConstants
diff --git a/itext.tests/itext.layout.tests/itext/layout/renderer/BackgroundSizeCalculationUtilUnitTest.cs b/itext.tests/itext.layout.tests/itext/layout/renderer/BackgroundSizeCalculationUtilUnitTest.cs
deleted file mode 100644
index b12400d284..0000000000
--- a/itext.tests/itext.layout.tests/itext/layout/renderer/BackgroundSizeCalculationUtilUnitTest.cs
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-This file is part of the iText (R) project.
-Copyright (c) 1998-2024 Apryse Group NV
-Authors: Apryse Software.
-
-This program is offered under a commercial and under the AGPL license.
-For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
-
-AGPL licensing:
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-*/
-using System;
-using iText.IO.Image;
-using iText.Kernel.Pdf.Xobject;
-using iText.Layout.Properties;
-using iText.Test;
-
-namespace iText.Layout.Renderer {
- [NUnit.Framework.Category("UnitTest")]
- public class BackgroundSizeCalculationUtilUnitTest : ExtendedITextTest {
- private static readonly String SOURCE_FOLDER = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext
- .CurrentContext.TestDirectory) + "/resources/itext/layout/BackgroundImageTest/";
-
- private const float delta = 0.0001f;
-
- [NUnit.Framework.Test]
- public virtual void CalculateImageSizeTest() {
- PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.Create(SOURCE_FOLDER + "pattern-grg-rrg-rgg.png"
- ));
- BackgroundImage backgroundImage = new BackgroundImage.Builder().SetImage(xObject).Build();
- float[] widthAndHeight = BackgroundSizeCalculationUtil.CalculateBackgroundImageSize(backgroundImage, 200f,
- 300f);
- iText.Test.TestUtil.AreEqual(new float[] { 45f, 45f }, widthAndHeight, delta);
- }
-
- [NUnit.Framework.Test]
- public virtual void CalculateImageSizeWithCoverPropertyTest() {
- PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.Create(SOURCE_FOLDER + "pattern-grg-rrg-rgg.png"
- ));
- BackgroundImage backgroundImage = new BackgroundImage.Builder().SetImage(xObject).Build();
- backgroundImage.GetBackgroundSize().SetBackgroundSizeToCover();
- float[] widthAndHeight = BackgroundSizeCalculationUtil.CalculateBackgroundImageSize(backgroundImage, 200f,
- 300f);
- iText.Test.TestUtil.AreEqual(new float[] { 300f, 300f }, widthAndHeight, delta);
- }
-
- [NUnit.Framework.Test]
- public virtual void CalculateSizeWithContainPropertyTest() {
- PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.Create(SOURCE_FOLDER + "pattern-grg-rrg-rgg.png"
- ));
- BackgroundImage backgroundImage = new BackgroundImage.Builder().SetImage(xObject).Build();
- backgroundImage.GetBackgroundSize().SetBackgroundSizeToContain();
- float[] widthAndHeight = BackgroundSizeCalculationUtil.CalculateBackgroundImageSize(backgroundImage, 200f,
- 300f);
- iText.Test.TestUtil.AreEqual(new float[] { 200f, 200.000015f }, widthAndHeight, delta);
- }
-
- [NUnit.Framework.Test]
- public virtual void CalculateSizeWithContainAndImageWeightMoreThatHeightTest() {
- PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.Create(SOURCE_FOLDER + "itis.jpg"));
- BackgroundImage backgroundImage = new BackgroundImage.Builder().SetImage(xObject).Build();
- backgroundImage.GetBackgroundSize().SetBackgroundSizeToContain();
- float[] widthAndHeight = BackgroundSizeCalculationUtil.CalculateBackgroundImageSize(backgroundImage, 200f,
- 300f);
- iText.Test.TestUtil.AreEqual(new float[] { 200f, 112.5f }, widthAndHeight, delta);
- }
-
- [NUnit.Framework.Test]
- public virtual void CalculateSizeWithCoverAndImageWeightMoreThatHeightTest() {
- PdfImageXObject xObject = new PdfImageXObject(ImageDataFactory.Create(SOURCE_FOLDER + "itis.jpg"));
- BackgroundImage backgroundImage = new BackgroundImage.Builder().SetImage(xObject).Build();
- backgroundImage.GetBackgroundSize().SetBackgroundSizeToCover();
- float[] widthAndHeight = BackgroundSizeCalculationUtil.CalculateBackgroundImageSize(backgroundImage, 200f,
- 300f);
- iText.Test.TestUtil.AreEqual(new float[] { 533.3333f, 300f }, widthAndHeight, delta);
- }
- }
-}
diff --git a/itext.tests/itext.svg.tests/itext/svg/css/AttributesRelativeUnitTest.cs b/itext.tests/itext.svg.tests/itext/svg/css/AttributesRelativeUnitTest.cs
index 0b8e35711d..07042e1418 100644
--- a/itext.tests/itext.svg.tests/itext/svg/css/AttributesRelativeUnitTest.cs
+++ b/itext.tests/itext.svg.tests/itext/svg/css/AttributesRelativeUnitTest.cs
@@ -121,6 +121,11 @@ public virtual void SvgWidthAndHeightEmAndRemTest() {
ConvertAndCompare(SOURCE_FOLDER, DESTINATION_FOLDER, "svgWidthAndHeightEmAndRemTest");
}
+ [NUnit.Framework.Test]
+ public virtual void SvgRelativeSizeWithViewBox1() {
+ ConvertAndCompare(SOURCE_FOLDER, DESTINATION_FOLDER, "svgRelativeSizeWithViewBox1");
+ }
+
//-------------- use
[NUnit.Framework.Test]
public virtual void UseXPercentTest() {
@@ -169,6 +174,32 @@ public virtual void SymbolWidthAndHeightEmAndRemTest() {
ConvertAndCompare(SOURCE_FOLDER, DESTINATION_FOLDER, "symbolWidthAndHeightEmAndRemTest");
}
+ //-------------- SVGs with absolute or missing size, but with viewBox and or preserveAspectRatio="none"
+ [NUnit.Framework.Test]
+ public virtual void AbsoluteWidthHeightViewBoxTest() {
+ ConvertAndCompare(SOURCE_FOLDER, DESTINATION_FOLDER, "absoluteWidthHeightViewBoxTest");
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void AbsoluteHeightViewBoxMissWidthTest() {
+ ConvertAndCompare(SOURCE_FOLDER, DESTINATION_FOLDER, "absoluteHeightViewBoxMissWidthTest");
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void AbsoluteWidthNoHeightNoViewBoxTest() {
+ ConvertAndCompare(SOURCE_FOLDER, DESTINATION_FOLDER, "absoluteWidthNoHeightNoViewBoxTest");
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void AbsoluteWidthViewBoxNoHeightTest() {
+ ConvertAndCompare(SOURCE_FOLDER, DESTINATION_FOLDER, "absoluteWidthViewBoxNoHeightTest");
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void AbsWidthViewBoxNoneRatioTest() {
+ ConvertAndCompare(SOURCE_FOLDER, DESTINATION_FOLDER, "absWidthViewBoxNoneRatioTest");
+ }
+
//-------------- misc
[NUnit.Framework.Test]
public virtual void LinePercentTest() {
@@ -203,5 +234,15 @@ public virtual void ViewportFromConverterPropertiesTest() {
// browsers the result should be bigger but with the same proportions
ConvertAndCompare(SOURCE_FOLDER, DESTINATION_FOLDER, "viewportFromConverterPropertiesTest", properties);
}
+
+ [NUnit.Framework.Test]
+ public virtual void ViewBoxMissWidthHeightTest() {
+ ConvertAndCompare(SOURCE_FOLDER, DESTINATION_FOLDER, "viewBoxMissWidthHeightTest");
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void PercentHeightMissWidthViewBoxTest() {
+ ConvertAndCompare(SOURCE_FOLDER, DESTINATION_FOLDER, "percentHeightMissWidthViewBoxTest");
+ }
}
}
diff --git a/itext.tests/itext.svg.tests/itext/svg/renderers/SvgImageRendererTest.cs b/itext.tests/itext.svg.tests/itext/svg/renderers/SvgImageRendererTest.cs
index 357417f446..dfb1b09b66 100644
--- a/itext.tests/itext.svg.tests/itext/svg/renderers/SvgImageRendererTest.cs
+++ b/itext.tests/itext.svg.tests/itext/svg/renderers/SvgImageRendererTest.cs
@@ -26,6 +26,9 @@ You should have received a copy of the GNU Affero General Public License
using iText.Kernel.Pdf;
using iText.Kernel.Utils;
using iText.Layout;
+using iText.Layout.Element;
+using iText.Layout.Logs;
+using iText.Layout.Properties;
using iText.StyledXmlParser.Node;
using iText.StyledXmlParser.Resolver.Resource;
using iText.Svg.Converter;
@@ -34,6 +37,7 @@ You should have received a copy of the GNU Affero General Public License
using iText.Svg.Processors.Impl;
using iText.Svg.Utils;
using iText.Svg.Xobject;
+using iText.Test.Attributes;
namespace iText.Svg.Renderers {
[NUnit.Framework.Category("IntegrationTest")]
@@ -107,5 +111,100 @@ public virtual void NoSpecifiedWidthHeightImageTest() {
NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, DESTINATION_FOLDER
, "diff"));
}
+
+ [NUnit.Framework.Test]
+ public virtual void RelativeSizedSvg1Test() {
+ String svgName = "fixed_height_percent_width";
+ String svgFileName = SOURCE_FOLDER + svgName + ".svg";
+ String cmpFileName = SOURCE_FOLDER + "cmp_" + svgName + ".pdf";
+ String outFileName = DESTINATION_FOLDER + svgName + ".pdf";
+ using (Document document = new Document(new PdfDocument(new PdfWriter(outFileName, new WriterProperties().
+ SetCompressionLevel(0))))) {
+ INode parsedSvg = SvgConverter.Parse(FileUtil.GetInputStreamForFile(svgFileName));
+ ISvgProcessorResult result = new DefaultSvgProcessor().Process(parsedSvg, new SvgConverterProperties().SetBaseUri
+ (svgFileName));
+ SvgDrawContext svgDrawContext = new SvgDrawContext(new ResourceResolver(SOURCE_FOLDER), null);
+ SvgImageXObject svgImageXObject = new SvgImageXObject(result, svgDrawContext, 12, document.GetPdfDocument(
+ ));
+ SvgImage svgImage = new SvgImage(svgImageXObject);
+ svgImage.SetWidth(100);
+ svgImage.SetHeight(300);
+ document.Add(svgImage);
+ }
+ NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, DESTINATION_FOLDER
+ , "diff"));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void RelativeSizedSvg3Test() {
+ String svgName = "viewbox_fixed_height_percent_width";
+ String svgFileName = SOURCE_FOLDER + svgName + ".svg";
+ String cmpFileName = SOURCE_FOLDER + "cmp_" + svgName + ".pdf";
+ String outFileName = DESTINATION_FOLDER + svgName + ".pdf";
+ using (Document document = new Document(new PdfDocument(new PdfWriter(outFileName, new WriterProperties().
+ SetCompressionLevel(0))))) {
+ INode parsedSvg = SvgConverter.Parse(FileUtil.GetInputStreamForFile(svgFileName));
+ ISvgProcessorResult result = new DefaultSvgProcessor().Process(parsedSvg, new SvgConverterProperties().SetBaseUri
+ (svgFileName));
+ SvgDrawContext svgDrawContext = new SvgDrawContext(new ResourceResolver(SOURCE_FOLDER), null);
+ SvgImageXObject svgImageXObject = new SvgImageXObject(result, svgDrawContext, 12, document.GetPdfDocument(
+ ));
+ SvgImage svgImage = new SvgImage(svgImageXObject);
+ svgImage.SetWidth(100);
+ svgImage.SetHeight(300);
+ document.Add(svgImage);
+ }
+ NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, DESTINATION_FOLDER
+ , "diff"));
+ }
+
+ [NUnit.Framework.Test]
+ [LogMessage(LayoutLogMessageConstant.ELEMENT_DOES_NOT_FIT_AREA)]
+ public virtual void RelativeSizedSvg4Test() {
+ String svgName = "viewbox_percent_height_percent_width";
+ String svgFileName = SOURCE_FOLDER + svgName + ".svg";
+ String cmpFileName = SOURCE_FOLDER + "cmp_" + svgName + ".pdf";
+ String outFileName = DESTINATION_FOLDER + svgName + ".pdf";
+ using (Document document = new Document(new PdfDocument(new PdfWriter(outFileName, new WriterProperties().
+ SetCompressionLevel(0))))) {
+ INode parsedSvg = SvgConverter.Parse(FileUtil.GetInputStreamForFile(svgFileName));
+ ISvgProcessorResult result = new DefaultSvgProcessor().Process(parsedSvg, new SvgConverterProperties().SetBaseUri
+ (svgFileName));
+ SvgDrawContext svgDrawContext = new SvgDrawContext(new ResourceResolver(SOURCE_FOLDER), null);
+ SvgImageXObject svgImageXObject = new SvgImageXObject(result, svgDrawContext, 12, document.GetPdfDocument(
+ ));
+ SvgImage svgImage = new SvgImage(svgImageXObject);
+ document.Add(svgImage);
+ }
+ NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, DESTINATION_FOLDER
+ , "diff"));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void RelativeSizedSvg5Test() {
+ String svgName = "viewbox_percent_height_percent_width_prRatio_none";
+ String svgFileName = SOURCE_FOLDER + svgName + ".svg";
+ String cmpFileName = SOURCE_FOLDER + "cmp_" + svgName + ".pdf";
+ String outFileName = DESTINATION_FOLDER + svgName + ".pdf";
+ using (Document document = new Document(new PdfDocument(new PdfWriter(outFileName, new WriterProperties().
+ SetCompressionLevel(0))))) {
+ INode parsedSvg = SvgConverter.Parse(FileUtil.GetInputStreamForFile(svgFileName));
+ ISvgProcessorResult result = new DefaultSvgProcessor().Process(parsedSvg, new SvgConverterProperties().SetBaseUri
+ (svgFileName));
+ SvgDrawContext svgDrawContext = new SvgDrawContext(new ResourceResolver(SOURCE_FOLDER), null);
+ SvgImageXObject svgImageXObject = new SvgImageXObject(result, svgDrawContext, 12, document.GetPdfDocument(
+ ));
+ Div div = new Div();
+ div.SetWidth(100);
+ div.SetHeight(300);
+ SvgImage svgImage = new SvgImage(svgImageXObject);
+ svgImage.SetWidth(UnitValue.CreatePercentValue(100));
+ svgImage.SetHeight(UnitValue.CreatePercentValue(100));
+ div.Add(svgImage);
+ document.Add(div);
+ }
+ NUnit.Framework.Assert.IsNull(new CompareTool().CompareByContent(outFileName, cmpFileName, DESTINATION_FOLDER
+ , "diff"));
+ }
}
}
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/absWidthViewBoxNoneRatioTest.svg b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/absWidthViewBoxNoneRatioTest.svg
new file mode 100644
index 0000000000..218b0dd7b6
--- /dev/null
+++ b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/absWidthViewBoxNoneRatioTest.svg
@@ -0,0 +1,5 @@
+
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/absoluteHeightViewBoxMissWidthTest.svg b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/absoluteHeightViewBoxMissWidthTest.svg
new file mode 100644
index 0000000000..68d7c43432
--- /dev/null
+++ b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/absoluteHeightViewBoxMissWidthTest.svg
@@ -0,0 +1,12 @@
+
+
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/absoluteWidthHeightViewBoxTest.svg b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/absoluteWidthHeightViewBoxTest.svg
new file mode 100644
index 0000000000..39468156bf
--- /dev/null
+++ b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/absoluteWidthHeightViewBoxTest.svg
@@ -0,0 +1,12 @@
+
+
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/absoluteWidthNoHeightNoViewBoxTest.svg b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/absoluteWidthNoHeightNoViewBoxTest.svg
new file mode 100644
index 0000000000..9f3a5bfa0b
--- /dev/null
+++ b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/absoluteWidthNoHeightNoViewBoxTest.svg
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/absoluteWidthViewBoxNoHeightTest.svg b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/absoluteWidthViewBoxNoHeightTest.svg
new file mode 100644
index 0000000000..3736203aa1
--- /dev/null
+++ b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/absoluteWidthViewBoxNoHeightTest.svg
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_absWidthViewBoxNoneRatioTest.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_absWidthViewBoxNoneRatioTest.pdf
new file mode 100644
index 0000000000..5be5733210
Binary files /dev/null and b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_absWidthViewBoxNoneRatioTest.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_absoluteHeightViewBoxMissWidthTest.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_absoluteHeightViewBoxMissWidthTest.pdf
new file mode 100644
index 0000000000..7988c7b2dd
Binary files /dev/null and b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_absoluteHeightViewBoxMissWidthTest.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_absoluteWidthHeightViewBoxTest.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_absoluteWidthHeightViewBoxTest.pdf
new file mode 100644
index 0000000000..88cb03005c
Binary files /dev/null and b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_absoluteWidthHeightViewBoxTest.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_absoluteWidthNoHeightNoViewBoxTest.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_absoluteWidthNoHeightNoViewBoxTest.pdf
new file mode 100644
index 0000000000..337d66f436
Binary files /dev/null and b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_absoluteWidthNoHeightNoViewBoxTest.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_absoluteWidthViewBoxNoHeightTest.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_absoluteWidthViewBoxNoHeightTest.pdf
new file mode 100644
index 0000000000..c45bfa13aa
Binary files /dev/null and b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_absoluteWidthViewBoxNoHeightTest.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_percentHeightMissWidthViewBoxTest.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_percentHeightMissWidthViewBoxTest.pdf
new file mode 100644
index 0000000000..181881f1ab
Binary files /dev/null and b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_percentHeightMissWidthViewBoxTest.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_svgHeightPercentTest.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_svgHeightPercentTest.pdf
index f2a94a4907..a3e8e56677 100644
Binary files a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_svgHeightPercentTest.pdf and b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_svgHeightPercentTest.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_svgRelativeSizeWithViewBox1.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_svgRelativeSizeWithViewBox1.pdf
new file mode 100644
index 0000000000..31f7cb4a83
Binary files /dev/null and b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_svgRelativeSizeWithViewBox1.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_svgViewboxWidthPercentTest.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_svgViewboxWidthPercentTest.pdf
index 081a52bfd8..da76fa8100 100644
Binary files a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_svgViewboxWidthPercentTest.pdf and b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_svgViewboxWidthPercentTest.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_svgWidthPercentTest.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_svgWidthPercentTest.pdf
index 95176cc9f5..ef74fed25b 100644
Binary files a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_svgWidthPercentTest.pdf and b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_svgWidthPercentTest.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_viewBoxMissWidthHeightTest.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_viewBoxMissWidthHeightTest.pdf
new file mode 100644
index 0000000000..73374e5586
Binary files /dev/null and b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_viewBoxMissWidthHeightTest.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_viewportFromConverterPropertiesTest.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_viewportFromConverterPropertiesTest.pdf
index c255769b3a..16f21a4464 100644
Binary files a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_viewportFromConverterPropertiesTest.pdf and b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/cmp_viewportFromConverterPropertiesTest.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/percentHeightMissWidthViewBoxTest.svg b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/percentHeightMissWidthViewBoxTest.svg
new file mode 100644
index 0000000000..7837d06cc0
--- /dev/null
+++ b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/percentHeightMissWidthViewBoxTest.svg
@@ -0,0 +1,12 @@
+
+
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/svgRelativeSizeWithViewBox1.svg b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/svgRelativeSizeWithViewBox1.svg
new file mode 100644
index 0000000000..a105d0c2c1
--- /dev/null
+++ b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/svgRelativeSizeWithViewBox1.svg
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/viewBoxMissWidthHeightTest.svg b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/viewBoxMissWidthHeightTest.svg
new file mode 100644
index 0000000000..f656df1ec8
--- /dev/null
+++ b/itext.tests/itext.svg.tests/resources/itext/svg/css/AttributesRelativeUnitTest/viewBoxMissWidthHeightTest.svg
@@ -0,0 +1,12 @@
+
+
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_fixed_height_percent_width.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_fixed_height_percent_width.pdf
new file mode 100644
index 0000000000..7cf415ef87
Binary files /dev/null and b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_fixed_height_percent_width.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_percent_height_fixed_width.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_percent_height_fixed_width.pdf
new file mode 100644
index 0000000000..9656091c82
Binary files /dev/null and b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_percent_height_fixed_width.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_percent_height_fixed_width_prRatio_none.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_percent_height_fixed_width_prRatio_none.pdf
new file mode 100644
index 0000000000..03bbdde00a
Binary files /dev/null and b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_percent_height_fixed_width_prRatio_none.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_viewbox_fixed_height_percent_width.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_viewbox_fixed_height_percent_width.pdf
new file mode 100644
index 0000000000..ac73e52171
Binary files /dev/null and b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_viewbox_fixed_height_percent_width.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_viewbox_fixed_height_prRatio_none.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_viewbox_fixed_height_prRatio_none.pdf
new file mode 100644
index 0000000000..5feb433496
Binary files /dev/null and b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_viewbox_fixed_height_prRatio_none.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_viewbox_percent_height_percent_width.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_viewbox_percent_height_percent_width.pdf
new file mode 100644
index 0000000000..b7c63d4c55
Binary files /dev/null and b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_viewbox_percent_height_percent_width.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_viewbox_percent_height_percent_width_prRatio_none.pdf b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_viewbox_percent_height_percent_width_prRatio_none.pdf
new file mode 100644
index 0000000000..0fc50ee8ed
Binary files /dev/null and b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/cmp_viewbox_percent_height_percent_width_prRatio_none.pdf differ
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/fixed_height_percent_width.svg b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/fixed_height_percent_width.svg
new file mode 100644
index 0000000000..f7d6e75912
--- /dev/null
+++ b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/fixed_height_percent_width.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/percent_height_fixed_width.svg b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/percent_height_fixed_width.svg
new file mode 100644
index 0000000000..68cae23f3b
--- /dev/null
+++ b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/percent_height_fixed_width.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/viewbox_fixed_height_percent_width.svg b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/viewbox_fixed_height_percent_width.svg
new file mode 100644
index 0000000000..b1115708aa
--- /dev/null
+++ b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/viewbox_fixed_height_percent_width.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/viewbox_percent_height_percent_width.svg b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/viewbox_percent_height_percent_width.svg
new file mode 100644
index 0000000000..1d1c9682a3
--- /dev/null
+++ b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/viewbox_percent_height_percent_width.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/viewbox_percent_height_percent_width_prRatio_none.svg b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/viewbox_percent_height_percent_width_prRatio_none.svg
new file mode 100644
index 0000000000..78c6b131a1
--- /dev/null
+++ b/itext.tests/itext.svg.tests/resources/itext/svg/renderers/SvgImageRendererTest/viewbox_percent_height_percent_width_prRatio_none.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/itext/itext.layout/itext/layout/properties/BackgroundImage.cs b/itext/itext.layout/itext/layout/properties/BackgroundImage.cs
index 01d005e1cb..ef45b4f21b 100644
--- a/itext/itext.layout/itext/layout/properties/BackgroundImage.cs
+++ b/itext/itext.layout/itext/layout/properties/BackgroundImage.cs
@@ -26,6 +26,10 @@ You should have received a copy of the GNU Affero General Public License
namespace iText.Layout.Properties {
/// Class to hold background-image property.
public class BackgroundImage {
+ private static readonly UnitValue PERCENT_VALUE_100 = UnitValue.CreatePercentValue(100F);
+
+ private const float EPS = 1e-4F;
+
private static readonly BlendMode DEFAULT_BLEND_MODE = BlendMode.NORMAL;
protected internal PdfXObject image;
@@ -147,6 +151,31 @@ private BackgroundImage(PdfXObject image, BackgroundRepeat repeat, BackgroundPos
this.backgroundOrigin = origin;
}
+ /// Calculates width and height values for background image with a given area params.
+ /// width of the area of this images
+ /// height of the area of this images
+ /// array of two float values. NOTE that first value defines width, second defines height
+ public virtual float[] CalculateBackgroundImageSize(float areaWidth, float areaHeight) {
+ BackgroundSize size;
+ if (GetLinearGradientBuilder() == null && GetBackgroundSize().IsSpecificSize()) {
+ size = CalculateBackgroundSizeForArea(this, areaWidth, areaHeight);
+ }
+ else {
+ size = GetBackgroundSize();
+ }
+ UnitValue widthUV = size.GetBackgroundWidthSize();
+ UnitValue heightUV = size.GetBackgroundHeightSize();
+ if (widthUV != null && widthUV.IsPercentValue()) {
+ widthUV = UnitValue.CreatePointValue(areaWidth * widthUV.GetValue() / PERCENT_VALUE_100.GetValue());
+ }
+ if (heightUV != null && heightUV.IsPercentValue()) {
+ heightUV = UnitValue.CreatePointValue(areaHeight * heightUV.GetValue() / PERCENT_VALUE_100.GetValue());
+ }
+ float? width = widthUV != null && widthUV.GetValue() >= 0 ? (float?)widthUV.GetValue() : null;
+ float? height = heightUV != null && heightUV.GetValue() >= 0 ? (float?)heightUV.GetValue() : null;
+ return ResolveWidthAndHeight(width, height, areaWidth, areaHeight);
+ }
+
/// Gets background-position.
///
///
@@ -235,6 +264,67 @@ public virtual BackgroundBox GetBackgroundOrigin() {
return backgroundOrigin;
}
+ /// Resolves the final size of the background image in specified area.
+ /// the intrinsic background image width
+ /// the intrinsic background image height
+ /// the area width in which background will be placed
+ /// the area height in which background will be placed
+ /// the final size of the background image
+ protected internal virtual float[] ResolveWidthAndHeight(float? width, float? height, float areaWidth, float
+ areaHeight) {
+ bool isGradient = GetLinearGradientBuilder() != null;
+ float?[] widthAndHeight = new float?[2];
+ if (width != null) {
+ widthAndHeight[0] = width;
+ if (!isGradient && height == null) {
+ float difference = GetImageWidth() < EPS ? 1F : (float)width / GetImageWidth();
+ widthAndHeight[1] = GetImageHeight() * difference;
+ }
+ }
+ if (height != null) {
+ widthAndHeight[1] = height;
+ if (!isGradient && width == null) {
+ float difference = GetImageHeight() < EPS ? 1F : (float)height / GetImageHeight();
+ widthAndHeight[0] = GetImageWidth() * difference;
+ }
+ }
+ if (widthAndHeight[0] == null) {
+ widthAndHeight[0] = isGradient ? areaWidth : GetImageWidth();
+ }
+ if (widthAndHeight[1] == null) {
+ widthAndHeight[1] = isGradient ? areaHeight : GetImageHeight();
+ }
+ return new float[] { (float)widthAndHeight[0], (float)widthAndHeight[1] };
+ }
+
+ private static BackgroundSize CalculateBackgroundSizeForArea(iText.Layout.Properties.BackgroundImage image
+ , float areaWidth, float areaHeight) {
+ double widthDifference = areaWidth / image.GetImageWidth();
+ double heightDifference = areaHeight / image.GetImageHeight();
+ if (image.GetBackgroundSize().IsCover()) {
+ return CreateBackgroundSizeWithMaxValueSide(widthDifference > heightDifference);
+ }
+ else {
+ if (image.GetBackgroundSize().IsContain()) {
+ return CreateBackgroundSizeWithMaxValueSide(widthDifference < heightDifference);
+ }
+ else {
+ return new BackgroundSize();
+ }
+ }
+ }
+
+ private static BackgroundSize CreateBackgroundSizeWithMaxValueSide(bool maxWidth) {
+ BackgroundSize size = new BackgroundSize();
+ if (maxWidth) {
+ size.SetBackgroundSizeToValues(PERCENT_VALUE_100, null);
+ }
+ else {
+ size.SetBackgroundSizeToValues(null, PERCENT_VALUE_100);
+ }
+ return size;
+ }
+
///
///
/// builder class.
diff --git a/itext/itext.layout/itext/layout/renderer/AbstractRenderer.cs b/itext/itext.layout/itext/layout/renderer/AbstractRenderer.cs
index a4ca490d57..f55c5f8ccc 100644
--- a/itext/itext.layout/itext/layout/renderer/AbstractRenderer.cs
+++ b/itext/itext.layout/itext/layout/renderer/AbstractRenderer.cs
@@ -592,8 +592,8 @@ private void DrawBackgroundImage(BackgroundImage backgroundImage, DrawContext dr
) {
Rectangle originBackgroundArea = ApplyBackgroundBoxProperty(backgroundArea.Clone(), backgroundImage.GetBackgroundOrigin
());
- float[] imageWidthAndHeight = BackgroundSizeCalculationUtil.CalculateBackgroundImageSize(backgroundImage,
- originBackgroundArea.GetWidth(), originBackgroundArea.GetHeight());
+ float[] imageWidthAndHeight = backgroundImage.CalculateBackgroundImageSize(originBackgroundArea.GetWidth()
+ , originBackgroundArea.GetHeight());
PdfXObject backgroundXObject = backgroundImage.GetImage();
if (backgroundXObject == null) {
backgroundXObject = backgroundImage.GetForm();
diff --git a/itext/itext.layout/itext/layout/renderer/BackgroundSizeCalculationUtil.cs b/itext/itext.layout/itext/layout/renderer/BackgroundSizeCalculationUtil.cs
deleted file mode 100644
index 2c1cb8d419..0000000000
--- a/itext/itext.layout/itext/layout/renderer/BackgroundSizeCalculationUtil.cs
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
-This file is part of the iText (R) project.
-Copyright (c) 1998-2024 Apryse Group NV
-Authors: Apryse Software.
-
-This program is offered under a commercial and under the AGPL license.
-For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
-
-AGPL licensing:
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see .
-*/
-using iText.Layout.Properties;
-
-namespace iText.Layout.Renderer {
-//\cond DO_NOT_DOCUMENT
- /// Utility class for calculate background image width and height.
- internal sealed class BackgroundSizeCalculationUtil {
- private const int PERCENT_100 = 100;
-
- private static readonly UnitValue PERCENT_VALUE_100 = UnitValue.CreatePercentValue(100);
-
- private BackgroundSizeCalculationUtil() {
- }
-
- //no instance required
- /// Calculates width and height values for image with a given area params.
- ///
- /// the
- ///
- /// width and height of which you want to calculate
- ///
- /// width of the area of this images
- /// height of the area of this images
- /// array of two Float values. NOTE that first value defines width, second defines height.
- ///
- public static float[] CalculateBackgroundImageSize(BackgroundImage image, float areaWidth, float areaHeight
- ) {
- bool isGradient = image.GetLinearGradientBuilder() != null;
- BackgroundSize size;
- if (!isGradient && image.GetBackgroundSize().IsSpecificSize()) {
- size = CalculateBackgroundSizeForArea(image, areaWidth, areaHeight);
- }
- else {
- size = image.GetBackgroundSize();
- }
- UnitValue width = size.GetBackgroundWidthSize();
- UnitValue height = size.GetBackgroundHeightSize();
- float?[] widthAndHeight = new float?[2];
- if (width != null && width.GetValue() >= 0) {
- bool needScale = !isGradient && height == null;
- CalculateBackgroundWidth(width, areaWidth, needScale, image, widthAndHeight);
- }
- if (height != null && height.GetValue() >= 0) {
- bool needScale = !isGradient && width == null;
- CalculateBackgroundHeight(height, areaHeight, needScale, image, widthAndHeight);
- }
- SetDefaultSizeIfNull(widthAndHeight, areaWidth, areaHeight, image, isGradient);
- return new float[] { (float)widthAndHeight[0], (float)widthAndHeight[1] };
- }
-
- private static BackgroundSize CalculateBackgroundSizeForArea(BackgroundImage image, float areaWidth, float
- areaHeight) {
- double widthDifference = areaWidth / image.GetImageWidth();
- double heightDifference = areaHeight / image.GetImageHeight();
- if (image.GetBackgroundSize().IsCover()) {
- return CreateSizeWithMaxValueSide(widthDifference > heightDifference);
- }
- else {
- if (image.GetBackgroundSize().IsContain()) {
- return CreateSizeWithMaxValueSide(widthDifference < heightDifference);
- }
- else {
- return new BackgroundSize();
- }
- }
- }
-
- private static BackgroundSize CreateSizeWithMaxValueSide(bool maxWidth) {
- BackgroundSize size = new BackgroundSize();
- if (maxWidth) {
- size.SetBackgroundSizeToValues(PERCENT_VALUE_100, null);
- }
- else {
- size.SetBackgroundSizeToValues(null, PERCENT_VALUE_100);
- }
- return size;
- }
-
- private static void CalculateBackgroundWidth(UnitValue width, float areaWidth, bool scale, BackgroundImage
- image, float?[] widthAndHeight) {
- if (scale) {
- if (width.IsPercentValue()) {
- ScaleWidth(areaWidth * width.GetValue() / PERCENT_100, image, widthAndHeight);
- }
- else {
- ScaleWidth(width.GetValue(), image, widthAndHeight);
- }
- }
- else {
- if (width.IsPercentValue()) {
- widthAndHeight[0] = areaWidth * width.GetValue() / PERCENT_100;
- }
- else {
- widthAndHeight[0] = width.GetValue();
- }
- }
- }
-
- private static void CalculateBackgroundHeight(UnitValue height, float areaHeight, bool scale, BackgroundImage
- image, float?[] widthAndHeight) {
- if (scale) {
- if (height.IsPercentValue()) {
- ScaleHeight(areaHeight * height.GetValue() / PERCENT_100, image, widthAndHeight);
- }
- else {
- ScaleHeight(height.GetValue(), image, widthAndHeight);
- }
- }
- else {
- if (height.IsPercentValue()) {
- widthAndHeight[1] = areaHeight * height.GetValue() / PERCENT_100;
- }
- else {
- widthAndHeight[1] = height.GetValue();
- }
- }
- }
-
- private static void ScaleWidth(float newWidth, BackgroundImage image, float?[] imageWidthAndHeight) {
- float difference = image.GetImageWidth() == 0f ? 1f : newWidth / image.GetImageWidth();
- imageWidthAndHeight[0] = newWidth;
- imageWidthAndHeight[1] = image.GetImageHeight() * difference;
- }
-
- private static void ScaleHeight(float newHeight, BackgroundImage image, float?[] imageWidthAndHeight) {
- float difference = image.GetImageHeight() == 0f ? 1f : newHeight / image.GetImageHeight();
- imageWidthAndHeight[0] = image.GetImageWidth() * difference;
- imageWidthAndHeight[1] = newHeight;
- }
-
- private static void SetDefaultSizeIfNull(float?[] widthAndHeight, float areaWidth, float areaHeight, BackgroundImage
- image, bool isGradient) {
- if (isGradient) {
- widthAndHeight[0] = widthAndHeight[0] == null ? areaWidth : widthAndHeight[0];
- widthAndHeight[1] = widthAndHeight[1] == null ? areaHeight : widthAndHeight[1];
- }
- else {
- widthAndHeight[0] = widthAndHeight[0] == null ? image.GetImageWidth() : widthAndHeight[0];
- widthAndHeight[1] = widthAndHeight[1] == null ? image.GetImageHeight() : widthAndHeight[1];
- }
- }
- }
-//\endcond
-}
diff --git a/itext/itext.svg/itext/svg/SvgConstants.cs b/itext/itext.svg/itext/svg/SvgConstants.cs
index 455f75b9e1..29826cdee9 100644
--- a/itext/itext.svg/itext/svg/SvgConstants.cs
+++ b/itext/itext.svg/itext/svg/SvgConstants.cs
@@ -615,19 +615,19 @@ public sealed class Values {
/// Value representing the default aspect ratio: xmidymid.
public const String DEFAULT_ASPECT_RATIO = SvgConstants.Values.XMID_YMID;
- /// Default svg view port width value.
+ /// Default svg view port width value (300px * 0.75 = 225).
///
- /// Default svg view port width value.
+ /// Default svg view port width value (300px * 0.75 = 225).
/// See SVG specification.
///
- public const String DEFAULT_VIEWPORT_WIDTH = "300px";
+ public const float DEFAULT_VIEWPORT_WIDTH = 225F;
- /// Default svg view port height value.
+ /// Default svg view port height value (150px * 0.75 = 112.5).
///
- /// Default svg view port height value.
+ /// Default svg view port height value (150px * 0.75 = 112.5).
/// See SVG specification.
///
- public const String DEFAULT_VIEWPORT_HEIGHT = "150px";
+ public const float DEFAULT_VIEWPORT_HEIGHT = 112.5F;
/// Default width and height value.
///
diff --git a/itext/itext.svg/itext/svg/css/SvgCssContext.cs b/itext/itext.svg/itext/svg/css/SvgCssContext.cs
index 30f6f0cb03..8f0dac44b4 100644
--- a/itext/itext.svg/itext/svg/css/SvgCssContext.cs
+++ b/itext/itext.svg/itext/svg/css/SvgCssContext.cs
@@ -45,5 +45,11 @@ public virtual float GetRootFontSize() {
public virtual void SetRootFontSize(String fontSizeStr) {
this.rootFontSize = CssDimensionParsingUtils.ParseAbsoluteFontSize(fontSizeStr);
}
+
+ /// Sets the root font size.
+ /// the new root font size
+ public virtual void SetRootFontSize(float rootFontSize) {
+ this.rootFontSize = rootFontSize;
+ }
}
}
diff --git a/itext/itext.svg/itext/svg/element/SvgImage.cs b/itext/itext.svg/itext/svg/element/SvgImage.cs
index 9583446d3b..0b89824ac2 100644
--- a/itext/itext.svg/itext/svg/element/SvgImage.cs
+++ b/itext/itext.svg/itext/svg/element/SvgImage.cs
@@ -20,6 +20,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
+using System;
using iText.Kernel.Pdf;
using iText.Layout.Element;
using iText.Layout.Renderer;
@@ -45,11 +46,25 @@ public SvgImage(SvgImageXObject xObject)
: base(xObject) {
}
+ ///
+ /// Gets the
+ ///
+ /// contained in this image object.
+ ///
+ ///
+ /// a
+ ///
+ ///
+ public virtual SvgImageXObject GetSvgImageXObject() {
+ return (SvgImageXObject)GetXObject();
+ }
+
///
/// Draws SVG image to a canvas-like object maintained in the
/// .
///
/// pdf that shall contain the SVG image.
+ [System.ObsoleteAttribute(@"was replaced by getSvgImageXObject().generate(PdfDocument)")]
public virtual void Generate(PdfDocument document) {
((SvgImageXObject)xObject).Generate(document);
}
diff --git a/itext/itext.svg/itext/svg/renderers/SvgImageRenderer.cs b/itext/itext.svg/itext/svg/renderers/SvgImageRenderer.cs
index 8e0b0c2e2b..bc6003e7e4 100644
--- a/itext/itext.svg/itext/svg/renderers/SvgImageRenderer.cs
+++ b/itext/itext.svg/itext/svg/renderers/SvgImageRenderer.cs
@@ -20,8 +20,13 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
+using iText.Kernel.Geom;
+using iText.Layout.Layout;
using iText.Layout.Renderer;
+using iText.Svg;
using iText.Svg.Element;
+using iText.Svg.Utils;
+using iText.Svg.Xobject;
namespace iText.Svg.Renderers {
///
@@ -40,10 +45,56 @@ public SvgImageRenderer(SvgImage image)
: base(image) {
}
+ public override LayoutResult Layout(LayoutContext layoutContext) {
+ SvgImage svgImage = (SvgImage)modelElement;
+ if (svgImage.GetSvgImageXObject().IsRelativeSized()) {
+ CalculateRelativeSizedSvgSize(svgImage, layoutContext.GetArea().GetBBox());
+ }
+ return base.Layout(layoutContext);
+ }
+
///
public override void Draw(DrawContext drawContext) {
- ((SvgImage)modelElement).Generate(drawContext.GetDocument());
+ ((SvgImage)modelElement).GetSvgImageXObject().Generate(drawContext.GetDocument());
base.Draw(drawContext);
}
+
+ private void CalculateRelativeSizedSvgSize(SvgImage svgImage, Rectangle layoutBox) {
+ SvgImageXObject svgImageXObject = svgImage.GetSvgImageXObject();
+ ISvgNodeRenderer svgRootRenderer = svgImageXObject.GetResult().GetRootRenderer();
+ float? aspectRatio = null;
+ float[] viewBoxValues = SvgCssUtils.ParseViewBox(svgRootRenderer);
+ if (viewBoxValues != null && viewBoxValues.Length == SvgConstants.Values.VIEWBOX_VALUES_NUMBER) {
+ // aspectRatio can also be specified by absolute height and width,
+ // but in that case SVG isn't relative and processed as usual image
+ aspectRatio = viewBoxValues[2] / viewBoxValues[3];
+ }
+ float? retrievedAreaWidth = RetrieveWidth(layoutBox.GetWidth());
+ float? retrievedAreaHeight = RetrieveHeight();
+ float areaWidth = retrievedAreaWidth == null ? (aspectRatio == null ? SvgConstants.Values.DEFAULT_VIEWPORT_WIDTH
+ : layoutBox.GetWidth()) : (float)retrievedAreaWidth;
+ float areaHeight = retrievedAreaHeight == null ? SvgConstants.Values.DEFAULT_VIEWPORT_HEIGHT : (float)retrievedAreaHeight;
+ float finalWidth;
+ float finalHeight;
+ if (aspectRatio != null && (retrievedAreaHeight == null || retrievedAreaWidth == null)) {
+ if (retrievedAreaWidth == null && retrievedAreaHeight != null) {
+ finalHeight = areaHeight;
+ finalWidth = (float)(finalHeight * aspectRatio);
+ }
+ else {
+ finalWidth = areaWidth;
+ finalHeight = (float)(finalWidth / aspectRatio);
+ }
+ }
+ else {
+ finalWidth = areaWidth;
+ finalHeight = areaHeight;
+ }
+ svgRootRenderer.SetAttribute(SvgConstants.Attributes.WIDTH, null);
+ svgRootRenderer.SetAttribute(SvgConstants.Attributes.HEIGHT, null);
+ svgImageXObject.UpdateBBox(finalWidth, finalHeight);
+ imageWidth = svgImage.GetImageWidth();
+ imageHeight = svgImage.GetImageHeight();
+ }
}
}
diff --git a/itext/itext.svg/itext/svg/renderers/impl/AbstractContainerSvgNodeRenderer.cs b/itext/itext.svg/itext/svg/renderers/impl/AbstractContainerSvgNodeRenderer.cs
index 2deb87ed58..3db6e43c8c 100644
--- a/itext/itext.svg/itext/svg/renderers/impl/AbstractContainerSvgNodeRenderer.cs
+++ b/itext/itext.svg/itext/svg/renderers/impl/AbstractContainerSvgNodeRenderer.cs
@@ -48,8 +48,10 @@ protected internal override void DoDraw(SvgDrawContext context) {
internal virtual Rectangle CalculateViewPort(SvgDrawContext context) {
Rectangle percentBaseBox;
if (GetParent() is PdfRootSvgNodeRenderer || !(GetParent() is AbstractSvgNodeRenderer)) {
- // If the current container is a top level SVG, take a current view port as a percent base
- percentBaseBox = context.GetCurrentViewPort();
+ // If the current container is a top level SVG, make a copy of the current viewport.
+ // It is needed to avoid double percent resolving. For absolute sized viewport we
+ // will get the same viewport, so save resources and just make a copy.
+ return context.GetCurrentViewPort().Clone();
}
else {
// If the current container is nested container, take a view box as a percent base
diff --git a/itext/itext.svg/itext/svg/utils/SvgCssUtils.cs b/itext/itext.svg/itext/svg/utils/SvgCssUtils.cs
index dcc0b62e3b..615709176f 100644
--- a/itext/itext.svg/itext/svg/utils/SvgCssUtils.cs
+++ b/itext/itext.svg/itext/svg/utils/SvgCssUtils.cs
@@ -213,10 +213,8 @@ public static Rectangle ExtractWidthAndHeight(ISvgNodeRenderer svgRenderer, floa
if (context.GetCustomViewport() == null) {
float[] viewBox = iText.Svg.Utils.SvgCssUtils.ParseViewBox(svgRenderer);
if (viewBox == null) {
- percentHorizontalBase = CssDimensionParsingUtils.ParseAbsoluteLength(SvgConstants.Values.DEFAULT_VIEWPORT_WIDTH
- );
- percentVerticalBase = CssDimensionParsingUtils.ParseAbsoluteLength(SvgConstants.Values.DEFAULT_VIEWPORT_HEIGHT
- );
+ percentHorizontalBase = SvgConstants.Values.DEFAULT_VIEWPORT_WIDTH;
+ percentVerticalBase = SvgConstants.Values.DEFAULT_VIEWPORT_HEIGHT;
}
else {
percentHorizontalBase = viewBox[2];
diff --git a/itext/itext.svg/itext/svg/xobject/SvgImageXObject.cs b/itext/itext.svg/itext/svg/xobject/SvgImageXObject.cs
index 392835999e..b12245c905 100644
--- a/itext/itext.svg/itext/svg/xobject/SvgImageXObject.cs
+++ b/itext/itext.svg/itext/svg/xobject/SvgImageXObject.cs
@@ -20,15 +20,20 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
+using System;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Canvas;
using iText.Kernel.Pdf.Xobject;
+using iText.Layout.Properties;
+using iText.StyledXmlParser.Css.Util;
using iText.StyledXmlParser.Resolver.Resource;
+using iText.Svg;
using iText.Svg.Processors;
using iText.Svg.Processors.Impl;
using iText.Svg.Renderers;
using iText.Svg.Renderers.Impl;
+using iText.Svg.Utils;
namespace iText.Svg.Xobject {
/// A wrapper for Form XObject for SVG images.
@@ -39,6 +44,12 @@ public class SvgImageXObject : PdfFormXObject {
private bool isGenerated = false;
+ private float em;
+
+ private SvgDrawContext svgDrawContext;
+
+ private bool isRelativeSized = false;
+
/// Creates a new instance of Form XObject for the SVG image.
/// the form XObject’s bounding box.
/// processor result containing the SVG information.
@@ -51,6 +62,62 @@ public SvgImageXObject(Rectangle bBox, ISvgProcessorResult result, ResourceResol
: base(bBox) {
this.result = result;
this.resourceResolver = resourceResolver;
+ this.svgDrawContext = new SvgDrawContext(resourceResolver, result.GetFontProvider());
+ }
+
+ /// Creates a new instance of Form XObject for the relative sized SVG image.
+ /// processor result containing the SVG information
+ /// the svg draw context
+ /// em value in pt
+ /// pdf that shall contain the SVG image, can be null
+ public SvgImageXObject(ISvgProcessorResult result, SvgDrawContext svgContext, float em, PdfDocument pdfDocument
+ )
+ : this(null, result, svgContext.GetResourceResolver()) {
+ if (pdfDocument != null) {
+ svgContext.PushCanvas(new PdfCanvas(this, pdfDocument));
+ }
+ this.em = em;
+ this.isRelativeSized = true;
+ this.svgDrawContext = svgContext;
+ }
+
+ /// If the SVG image is relative sized.
+ ///
+ /// If the SVG image is relative sized. This information
+ /// is used during image layouting to resolve it's relative size.
+ ///
+ ///
+ ///
+ ///
+ /// if the SVG image is relative sized,
+ ///
+ /// otherwise
+ ///
+ ///
+ ///
+ public virtual bool IsRelativeSized() {
+ return isRelativeSized;
+ }
+
+ /// Sets if the SVG image is relative sized.
+ ///
+ /// Sets if the SVG image is relative sized. This information
+ /// is used during image layouting to resolve it's relative size.
+ ///
+ ///
+ ///
+ ///
+ /// if the SVG image is relative sized,
+ ///
+ /// otherwise
+ ///
+ ///
+ ///
+ public virtual void SetRelativeSized(bool relativeSized) {
+ // TODO DEVSIX-8829 remove/deprecate this method after ticket will be done
+ isRelativeSized = relativeSized;
}
/// Returns processor result containing the SVG information.
@@ -65,6 +132,7 @@ public virtual ISvgProcessorResult GetResult() {
///
/// instance
///
+ [System.ObsoleteAttribute(@"not used anymore")]
public virtual ResourceResolver GetResourceResolver() {
return resourceResolver;
}
@@ -74,21 +142,54 @@ public virtual ResourceResolver GetResourceResolver() {
/// Processes xObject before first image generation to avoid drawing it twice or more. It allows to reuse the same
/// Form XObject multiple times.
///
- /// pdf that shall contain the SVG image.
+ ///
+ /// pdf that shall contain the SVG image, can be null if constructor
+ ///
+ /// was used
+ ///
public virtual void Generate(PdfDocument document) {
if (!isGenerated) {
- PdfCanvas canvas = new PdfCanvas(this, document);
- SvgDrawContext context = new SvgDrawContext(resourceResolver, result.GetFontProvider());
if (result is SvgProcessorResult) {
- context.SetCssContext(((SvgProcessorResult)result).GetContext().GetCssContext());
+ svgDrawContext.SetCssContext(((SvgProcessorResult)result).GetContext().GetCssContext());
+ }
+ svgDrawContext.SetTempFonts(result.GetTempFonts());
+ svgDrawContext.AddNamedObjects(result.GetNamedObjects());
+ if (svgDrawContext.Size() == 0) {
+ svgDrawContext.PushCanvas(new PdfCanvas(this, document));
}
- context.SetTempFonts(result.GetTempFonts());
- context.AddNamedObjects(result.GetNamedObjects());
- context.PushCanvas(canvas);
ISvgNodeRenderer root = new PdfRootSvgNodeRenderer(result.GetRootRenderer());
- root.Draw(context);
+ root.Draw(svgDrawContext);
isGenerated = true;
}
}
+
+ /// Updated XObject BBox for relative sized SVG image.
+ /// the area width where SVG image will be drawn
+ /// the area height where SVG image will be drawn
+ public virtual void UpdateBBox(float? areaWidth, float? areaHeight) {
+ // TODO DEVSIX-8829 change parameters to float, not Float
+ if (areaWidth != null && areaHeight != null) {
+ svgDrawContext.SetCustomViewport(new Rectangle((float)areaWidth, (float)areaHeight));
+ }
+ Rectangle bbox = SvgCssUtils.ExtractWidthAndHeight(result.GetRootRenderer(), em, svgDrawContext);
+ SetBBox(new PdfArray(bbox));
+ }
+
+ /// Gets the SVG element width.
+ /// the SVG element width
+ public virtual UnitValue GetElementWidth() {
+ String widthStr = result.GetRootRenderer().GetAttribute(SvgConstants.Attributes.WIDTH);
+ return CssDimensionParsingUtils.ParseLengthValueToPt(widthStr, em, svgDrawContext.GetCssContext().GetRootFontSize
+ ());
+ }
+
+ /// Gets the SVG element height.
+ /// the SVG element height
+ public virtual UnitValue GetElementHeight() {
+ String heightStr = result.GetRootRenderer().GetAttribute(SvgConstants.Attributes.HEIGHT);
+ return CssDimensionParsingUtils.ParseLengthValueToPt(heightStr, em, svgDrawContext.GetCssContext().GetRootFontSize
+ ());
+ }
}
}
diff --git a/port-hash b/port-hash
index 9fa91479eb..d06f69a49e 100644
--- a/port-hash
+++ b/port-hash
@@ -1 +1 @@
-8bb3a645256a2b07cf12bb1b8d159ccb397b64e6
+fad2fb2571e1aed7f01fc39fdf33081cdd6a3893