Skip to content

Commit 7b2a1a8

Browse files
author
Dmitry Radchuk
committed
Add repeat, fit-content support
DEVSIX-8383
1 parent b178090 commit 7b2a1a8

File tree

106 files changed

+1609
-48
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+1609
-48
lines changed

src/main/java/com/itextpdf/html2pdf/css/CssConstants.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ This file is part of the iText (R) project.
3131

3232
public class CssConstants extends CommonCssConstants {
3333

34+
/** The Constant AUTO_FIT. */
35+
public static final String AUTO_FIT = "auto-fit";
36+
37+
/** The Constant AUTO_FILL. */
38+
public static final String AUTO_FILL = "auto-fill";
39+
3440
/** The Constant BLEED. */
3541
public static final String BLEED = "bleed";
3642

@@ -71,6 +77,9 @@ public class CssConstants extends CommonCssConstants {
7177
/** The Constant MIN_WIDTH. */
7278
public static final String MIN_WIDTH = "min-width";
7379

80+
/** The Constant MIN_MAX. */
81+
public static final String MINMAX = "minmax";
82+
7483
/**
7584
* The Constant OBJECT_FIT.
7685
*/

src/main/java/com/itextpdf/html2pdf/css/apply/util/GridApplierUtil.java

Lines changed: 105 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,22 @@ This file is part of the iText (R) project.
2626
import com.itextpdf.html2pdf.css.CssConstants;
2727
import com.itextpdf.html2pdf.logs.Html2PdfLogMessageConstant;
2828
import com.itextpdf.layout.IPropertyContainer;
29-
import com.itextpdf.layout.properties.GridFlow;
30-
import com.itextpdf.layout.properties.GridValue;
29+
import com.itextpdf.layout.properties.grid.AutoRepeatValue;
30+
import com.itextpdf.layout.properties.grid.BreadthValue;
31+
import com.itextpdf.layout.properties.grid.FixedRepeatValue;
32+
import com.itextpdf.layout.properties.grid.GridFlow;
3133
import com.itextpdf.layout.properties.Property;
3234
import com.itextpdf.layout.properties.UnitValue;
35+
import com.itextpdf.layout.properties.grid.AutoValue;
36+
import com.itextpdf.layout.properties.grid.FitContentValue;
37+
import com.itextpdf.layout.properties.grid.FlexValue;
38+
import com.itextpdf.layout.properties.grid.GridValue;
39+
import com.itextpdf.layout.properties.grid.MaxContentValue;
40+
import com.itextpdf.layout.properties.grid.MinContentValue;
41+
import com.itextpdf.layout.properties.grid.MinMaxValue;
42+
import com.itextpdf.layout.properties.grid.PercentValue;
43+
import com.itextpdf.layout.properties.grid.PointValue;
44+
import com.itextpdf.layout.properties.grid.TemplateValue;
3345
import com.itextpdf.styledxmlparser.css.CommonCssConstants;
3446
import com.itextpdf.styledxmlparser.css.util.CssDimensionParsingUtils;
3547
import com.itextpdf.styledxmlparser.css.util.CssUtils;
@@ -81,7 +93,7 @@ private GridApplierUtil() {
8193
* @param element the element
8294
*/
8395
public static void applyGridItemProperties(Map<String, String> cssProps, IStylesContainer stylesContainer,
84-
IPropertyContainer element) {
96+
IPropertyContainer element) {
8597
if (!(stylesContainer instanceof JsoupElementNode)
8698
|| !(((JsoupElementNode) stylesContainer).parentNode() instanceof JsoupElementNode)) {
8799
return;
@@ -127,7 +139,7 @@ public static void applyGridItemProperties(Map<String, String> cssProps, IStyles
127139
applyGridItemPlacement(cssProps.get(CssConstants.GRID_ROW_END), element, Property.GRID_ROW_END, Property.GRID_ROW_SPAN);
128140
applyGridItemPlacement(cssProps.get(CssConstants.GRID_ROW_START), element, Property.GRID_ROW_START, Property.GRID_ROW_SPAN);
129141
}
130-
142+
131143
private static void applyGridItemPlacement(String value, IPropertyContainer element, int property, int spanProperty) {
132144
if (value == null) {
133145
return;
@@ -154,7 +166,7 @@ private static void applyGridItemPlacement(String value, IPropertyContainer elem
154166
* @param context the context
155167
*/
156168
public static void applyGridContainerProperties(Map<String, String> cssProps, IPropertyContainer container,
157-
ProcessorContext context) {
169+
ProcessorContext context) {
158170

159171
final float emValue = CssDimensionParsingUtils.parseAbsoluteFontSize(cssProps.get(CssConstants.FONT_SIZE));
160172
final float remValue = context.getCssContext().getRootFontSize();
@@ -182,7 +194,7 @@ public static void applyGridContainerProperties(Map<String, String> cssProps, IP
182194

183195
private static void applyAuto(String autoStr, IPropertyContainer container, int property, float emValue, float remValue) {
184196
if (autoStr != null) {
185-
GridValue value = getGridValue(autoStr, emValue, remValue);
197+
TemplateValue value = parseTemplateValue(autoStr, emValue, remValue);
186198
if (value != null) {
187199
container.setProperty(property, value);
188200
}
@@ -208,9 +220,9 @@ private static void applyFlow(String flow, IPropertyContainer container) {
208220
private static void applyTemplate(String templateStr, IPropertyContainer container, int property, float emValue, float remValue) {
209221
if (templateStr != null) {
210222
final List<String> templateStrArray = CssUtils.extractShorthandProperties(templateStr).get(0);
211-
final List<GridValue> templateResult = new ArrayList<>();
223+
final List<TemplateValue> templateResult = new ArrayList<>();
212224
for (String str : templateStrArray) {
213-
GridValue value = getGridValue(str, emValue, remValue);
225+
TemplateValue value = parseTemplateValue(str, emValue, remValue);
214226
if (value != null) {
215227
templateResult.add(value);
216228
}
@@ -221,26 +233,101 @@ private static void applyTemplate(String templateStr, IPropertyContainer contain
221233
}
222234
}
223235

224-
private static GridValue getGridValue(String str, float emValue, float remValue) {
236+
private static TemplateValue parseTemplateValue(String str, float emValue, float remValue) {
237+
if (str == null) {
238+
return null;
239+
}
225240
final UnitValue unit = CssDimensionParsingUtils.parseLengthValueToPt(str, emValue, remValue);
226241
if (unit != null) {
227242
if (unit.isPointValue()) {
228-
return GridValue.createPointValue(unit.getValue());
243+
return new PointValue(unit.getValue());
229244
} else {
230-
return GridValue.createPercentValue(unit.getValue());
245+
return new PercentValue(unit.getValue());
231246
}
232-
} else if (CommonCssConstants.MIN_CONTENT.equals(str)) {
233-
return GridValue.createMinContentValue();
234-
} else if (CommonCssConstants.MAX_CONTENT.equals(str)) {
235-
return GridValue.createMaxContentValue();
236-
} else if (CommonCssConstants.AUTO.equals(str)) {
237-
return GridValue.createAutoValue();
247+
}
248+
if (CommonCssConstants.MIN_CONTENT.equals(str)) {
249+
return MinContentValue.VALUE;
250+
}
251+
if (CommonCssConstants.MAX_CONTENT.equals(str)) {
252+
return MaxContentValue.VALUE;
253+
}
254+
if (CommonCssConstants.AUTO.equals(str)) {
255+
return AutoValue.VALUE;
238256
}
239257
final Float fr = CssDimensionParsingUtils.parseFlex(str);
240258
if (fr != null) {
241-
return GridValue.createFlexValue((float) fr);
259+
return new FlexValue((float) fr);
260+
}
261+
if (determineFunction(str, CommonCssConstants.FIT_CONTENT)) {
262+
return parseFitContent(str, emValue, remValue);
263+
}
264+
if (determineFunction(str, CommonCssConstants.REPEAT)) {
265+
return parseRepeat(str, emValue, remValue);
266+
}
267+
if (determineFunction(str, CssConstants.MINMAX)) {
268+
return parseMinMax(str, emValue, remValue);
269+
}
270+
return null;
271+
}
272+
273+
private static FitContentValue parseFitContent(String str, float emValue, float remValue) {
274+
UnitValue length = CssDimensionParsingUtils.parseLengthValueToPt(
275+
str.substring(CommonCssConstants.FIT_CONTENT.length() + 1, str.length() - 1), emValue, remValue);
276+
if (length == null) {
277+
return null;
278+
}
279+
return new FitContentValue(length);
280+
}
281+
282+
private static boolean determineFunction(String str, String function) {
283+
return str.startsWith(function)
284+
&& str.length() > function.length() + 2;
285+
}
286+
287+
private static TemplateValue parseMinMax(String str, float emValue, float remValue) {
288+
int parameterSeparator = str.indexOf(',');
289+
if (parameterSeparator < 0) {
290+
return null;
242291
}
292+
TemplateValue min = parseTemplateValue(str.substring(CssConstants.MINMAX.length() + 1, parameterSeparator).trim(), emValue, remValue);
293+
TemplateValue max = parseTemplateValue(str.substring(parameterSeparator + 1, str.length() - 1).trim(), emValue, remValue);
294+
if (!(min instanceof BreadthValue) || !(max instanceof BreadthValue)) {
295+
return null;
296+
}
297+
return new MinMaxValue((BreadthValue)min, (BreadthValue)max);
298+
}
243299

300+
private static TemplateValue parseRepeat(String str, float emValue, float remValue) {
301+
List<GridValue> repeatList = new ArrayList<>();
302+
int repeatCount = -1;
303+
int repeatTypeEndIndex = str.indexOf(',');
304+
if (repeatTypeEndIndex < 0) {
305+
return null;
306+
}
307+
String repeatType = str.substring(CommonCssConstants.REPEAT.length() + 1, repeatTypeEndIndex).trim();
308+
try {
309+
repeatCount = Integer.parseInt(repeatType);
310+
} catch (NumberFormatException ex) {
311+
//do nothing
312+
}
313+
314+
List<String> repeatStr = CssUtils.extractShorthandProperties(
315+
str.substring(repeatTypeEndIndex + 1, str.length() - 1)).get(0);
316+
for (String strValue : repeatStr) {
317+
TemplateValue value = parseTemplateValue(strValue, emValue, remValue);
318+
if (value instanceof GridValue) {
319+
repeatList.add((GridValue) value);
320+
} else {
321+
return null;
322+
}
323+
}
324+
if (repeatCount > 0) {
325+
return new FixedRepeatValue(repeatCount, repeatList);
326+
} else if (CssConstants.AUTO_FILL.equals(repeatType)) {
327+
return new AutoRepeatValue(false, repeatList);
328+
} else if (CssConstants.AUTO_FIT.equals(repeatType)) {
329+
return new AutoRepeatValue(true, repeatList);
330+
}
244331
return null;
245332
}
246333

src/test/java/com/itextpdf/html2pdf/css/apply/util/GridApplierUtilTest.java

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,17 @@ This file is part of the iText (R) project.
2828
import com.itextpdf.html2pdf.logs.Html2PdfLogMessageConstant;
2929
import com.itextpdf.layout.element.Div;
3030
import com.itextpdf.layout.element.IElement;
31-
import com.itextpdf.layout.properties.GridFlow;
32-
import com.itextpdf.layout.properties.GridValue;
31+
import com.itextpdf.layout.properties.grid.AutoRepeatValue;
32+
import com.itextpdf.layout.properties.grid.FitContentValue;
33+
import com.itextpdf.layout.properties.grid.FixedRepeatValue;
34+
import com.itextpdf.layout.properties.grid.GridFlow;
35+
import com.itextpdf.layout.properties.grid.GridValue;
3336
import com.itextpdf.layout.properties.Property;
37+
import com.itextpdf.layout.properties.grid.LengthValue;
38+
import com.itextpdf.layout.properties.grid.MinMaxValue;
39+
import com.itextpdf.layout.properties.grid.PercentValue;
40+
import com.itextpdf.layout.properties.grid.PointValue;
41+
import com.itextpdf.layout.properties.grid.TemplateValue;
3442
import com.itextpdf.styledxmlparser.css.CommonCssConstants;
3543
import com.itextpdf.styledxmlparser.jsoup.nodes.Element;
3644
import com.itextpdf.styledxmlparser.node.IElementNode;
@@ -323,8 +331,8 @@ public void containerAutoValuesTest() {
323331
cssProps.put(CssConstants.GRID_AUTO_ROWS, "30%");
324332
IElement element = new Div();
325333
GridApplierUtil.applyGridContainerProperties(cssProps, element, new ProcessorContext(new ConverterProperties()));
326-
Assertions.assertEquals(8.25, element.<GridValue>getProperty(Property.GRID_AUTO_COLUMNS).getValue(), 0.00001);
327-
Assertions.assertEquals(30, element.<GridValue>getProperty(Property.GRID_AUTO_ROWS).getValue());
334+
Assertions.assertEquals(8.25f, element.<LengthValue>getProperty(Property.GRID_AUTO_COLUMNS).getValue());
335+
Assertions.assertEquals(30.0f, element.<LengthValue>getProperty(Property.GRID_AUTO_ROWS).getValue());
328336
}
329337

330338
@Test
@@ -334,20 +342,51 @@ public void containerTemplateValuesTest() {
334342
cssProps.put(CssConstants.GRID_TEMPLATE_ROWS, "10px 20pt 3em 5rem");
335343
IElement element = new Div();
336344
GridApplierUtil.applyGridContainerProperties(cssProps, element, new ProcessorContext(new ConverterProperties()));
337-
List<GridValue> actualColValues = element.<List<GridValue>>getProperty(Property.GRID_TEMPLATE_COLUMNS);
345+
List<TemplateValue> actualColValues = element.<List<TemplateValue>>getProperty(Property.GRID_TEMPLATE_COLUMNS);
338346
Assertions.assertEquals(6, actualColValues.size());
339-
Assertions.assertTrue(actualColValues.get(0).isMinContentValue());
340-
Assertions.assertTrue(actualColValues.get(1).isFlexibleValue());
341-
Assertions.assertTrue(actualColValues.get(2).isAutoValue());
342-
Assertions.assertTrue(actualColValues.get(3).isFlexibleValue());
343-
Assertions.assertEquals(75, actualColValues.get(4).getValue());
344-
Assertions.assertEquals(20, actualColValues.get(5).getValue());
345-
List<GridValue> actualRowValues = element.<List<GridValue>>getProperty(Property.GRID_TEMPLATE_ROWS);
347+
Assertions.assertEquals(actualColValues.get(0).getType(), GridValue.ValueType.MIN_CONTENT);
348+
Assertions.assertEquals(actualColValues.get(1).getType(), GridValue.ValueType.FLEX);
349+
Assertions.assertEquals(actualColValues.get(2).getType(), GridValue.ValueType.AUTO);
350+
Assertions.assertEquals(actualColValues.get(3).getType(), GridValue.ValueType.FLEX);
351+
Assertions.assertEquals(75.0f, ((PointValue)actualColValues.get(4)).getValue());
352+
Assertions.assertEquals(20.0f, ((PercentValue)actualColValues.get(5)).getValue());
353+
List<TemplateValue> actualRowValues = element.<List<TemplateValue>>getProperty(Property.GRID_TEMPLATE_ROWS);
346354
Assertions.assertEquals(4, actualRowValues.size());
347-
Assertions.assertEquals(7.5f, actualRowValues.get(0).getValue());
348-
Assertions.assertEquals(20, actualRowValues.get(1).getValue());
349-
Assertions.assertEquals(0, actualRowValues.get(2).getValue());
350-
Assertions.assertEquals(60, actualRowValues.get(3).getValue());
355+
Assertions.assertEquals(7.5f, ((PointValue)actualRowValues.get(0)).getValue());
356+
Assertions.assertEquals(20.0f, ((PointValue)actualRowValues.get(1)).getValue());
357+
Assertions.assertEquals(0.0f, ((PointValue)actualRowValues.get(2)).getValue());
358+
Assertions.assertEquals(60.0f, ((PointValue)actualRowValues.get(3)).getValue());
359+
}
360+
361+
@Test
362+
public void containerComplexTemplateValuesTest() {
363+
Map<String, String> cssProps = new HashMap<>();
364+
cssProps.put(CssConstants.GRID_TEMPLATE_COLUMNS,
365+
"minmax(min-content, 1fr) fit-content(40%) fit-content(20px) repeat(2, fit-content(200px))");
366+
cssProps.put(CssConstants.GRID_TEMPLATE_ROWS, "repeat(3, 100px) repeat(auto-fit, minmax(100px, auto))");
367+
IElement element = new Div();
368+
GridApplierUtil.applyGridContainerProperties(cssProps, element, new ProcessorContext(new ConverterProperties()));
369+
370+
List<TemplateValue> actualColValues = element.<List<TemplateValue>>getProperty(Property.GRID_TEMPLATE_COLUMNS);
371+
Assertions.assertEquals(4, actualColValues.size());
372+
373+
Assertions.assertEquals(GridValue.ValueType.MINMAX, actualColValues.get(0).getType());
374+
Assertions.assertEquals(GridValue.ValueType.MIN_CONTENT, ((MinMaxValue)actualColValues.get(0)).getMin().getType());
375+
Assertions.assertEquals(GridValue.ValueType.FLEX, ((MinMaxValue)actualColValues.get(0)).getMax().getType());
376+
Assertions.assertEquals(GridValue.ValueType.FIT_CONTENT, actualColValues.get(1).getType());
377+
Assertions.assertEquals(GridValue.ValueType.PERCENT, ((FitContentValue)actualColValues.get(1)).getLength().getType());
378+
Assertions.assertEquals(GridValue.ValueType.FIT_CONTENT, actualColValues.get(2).getType());
379+
Assertions.assertEquals(GridValue.ValueType.POINT, ((FitContentValue)actualColValues.get(2)).getLength().getType());
380+
Assertions.assertEquals(GridValue.ValueType.FIXED_REPEAT, actualColValues.get(3).getType());
381+
Assertions.assertEquals(GridValue.ValueType.FIT_CONTENT, ((FixedRepeatValue)actualColValues.get(3)).getValues().get(0).getType());
382+
383+
List<TemplateValue> actualRowValues = element.<List<TemplateValue>>getProperty(Property.GRID_TEMPLATE_ROWS);
384+
Assertions.assertEquals(2, actualRowValues.size());
385+
386+
Assertions.assertEquals(GridValue.ValueType.FIXED_REPEAT, actualRowValues.get(0).getType());
387+
Assertions.assertEquals(GridValue.ValueType.POINT, ((FixedRepeatValue)actualRowValues.get(0)).getValues().get(0).getType());
388+
Assertions.assertEquals(GridValue.ValueType.AUTO_REPEAT, actualRowValues.get(1).getType());
389+
Assertions.assertEquals(GridValue.ValueType.MINMAX, ((AutoRepeatValue)actualRowValues.get(1)).getValues().get(0).getType());
351390
}
352391

353392
@Test

src/test/java/com/itextpdf/html2pdf/css/grid/GridTemplateColumnTest.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,11 @@ public void templateColumnWidthUnitsTest() throws IOException, InterruptedExcept
6262
}
6363

6464
@Test
65-
// TODO DEVSIX-8383 (assign to the ticket about minmax&repeat&fit-content support)
6665
public void templateColumnFitContentTest() throws IOException, InterruptedException {
6766
runTest("template-cols-fit-content");
6867
}
6968

7069
@Test
71-
// TODO DEVSIX-8383 (assign to the ticket about minmax&repeat&fit-content support)
7270
public void templateColumnFitContentAutoTest() throws IOException, InterruptedException {
7371
runTest("template-cols-fit-content-auto");
7472
}
@@ -94,7 +92,6 @@ public void templateColumnMarginTest() throws IOException, InterruptedException
9492
}
9593

9694
@Test
97-
// TODO DEVSIX-8383 (assign to the ticket about minmax&repeat&fit-content support)
9895
public void templateColumnMinMaxTest() throws IOException, InterruptedException {
9996
runTest("template-cols-minmax");
10097
}
@@ -120,13 +117,11 @@ public void templateColumnPaddingTest() throws IOException, InterruptedException
120117
}
121118

122119
@Test
123-
// TODO DEVSIX-8383 (assign to the ticket about minmax&repeat&fit-content support)
124120
public void templateColumnRepeatTest() throws IOException, InterruptedException {
125121
runTest("template-cols-repeat");
126122
}
127123

128124
@Test
129-
// TODO DEVSIX-8383 (assign to the ticket about minmax&repeat&fit-content support)
130125
public void templateColumnRepeatMinMaxTest() throws IOException, InterruptedException {
131126
runTest("template-cols-repeat-minmax");
132127
}

src/test/java/com/itextpdf/html2pdf/css/grid/GridTemplateCombinedTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ public void templateCoombinedMarginsPaddingsTest() throws IOException, Interrupt
6161
}
6262

6363
@Test
64-
// TODO DEVSIX-8383 (assign to the ticket about minmax&repeat support)
6564
public void templateCombinedMinMaxTest() throws IOException, InterruptedException {
6665
runTest("template-combined-minmax");
6766
}
@@ -83,7 +82,6 @@ public void templateCombinedNestedTest() throws IOException, InterruptedExceptio
8382
}
8483

8584
@Test
86-
// TODO DEVSIX-8383 (assign to the ticket about minmax&repeat support)
8785
public void templateCombinedRepeatMinMaxTest() throws IOException, InterruptedException {
8886
runTest("template-combined-repeat-minmax");
8987
}

0 commit comments

Comments
 (0)