Skip to content

Commit 0b9c186

Browse files
committed
Update the path-processing algo.
Optimize the algo: use a StringBuilder instance instead of a string. Process minuses correctly. DEVSIX-2043, DEVSIX-2044
1 parent 022fa28 commit 0b9c186

File tree

1 file changed

+21
-27
lines changed

1 file changed

+21
-27
lines changed

svg/src/main/java/com/itextpdf/svg/renderers/impl/PathSvgNodeRenderer.java

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ This file is part of the iText (R) project.
4242
*/
4343
package com.itextpdf.svg.renderers.impl;
4444

45-
4645
import com.itextpdf.io.util.MessageFormatUtil;
4746
import com.itextpdf.kernel.geom.Point;
4847
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
@@ -89,15 +88,15 @@ public class PathSvgNodeRenderer extends AbstractSvgNodeRenderer {
8988
* Find any occurence of a letter that is not an operator
9089
*/
9190
private static final String INVALID_OPERATOR_REGEX = "(?:(?![mzlhvcsqtae])\\p{L})";
92-
private static Pattern invalidRegexPattern = Pattern.compile(INVALID_OPERATOR_REGEX, Pattern.CASE_INSENSITIVE);;
91+
private static Pattern invalidRegexPattern = Pattern.compile(INVALID_OPERATOR_REGEX, Pattern.CASE_INSENSITIVE);
9392

9493
/**
9594
* The regular expression to split the <a href="https://www.w3.org/TR/SVG/paths.html#PathData">PathData attribute of the &ltpath&gt element</a>
9695
* <p>
9796
* Since {@link PathSvgNodeRenderer#containsInvalidAttributes(String)} is called before the use of this expression in {@link PathSvgNodeRenderer#parsePropertiesAndStyles()} the attribute to be split is valid.
9897
* The regex splits at each letter.
9998
*/
100-
private final String SPLIT_REGEX = "(?=[\\p{L}])";
99+
private static final String SPLIT_REGEX = "(?=[\\p{L}])";
101100

102101

103102
/**
@@ -116,7 +115,7 @@ public class PathSvgNodeRenderer extends AbstractSvgNodeRenderer {
116115
public void doDraw(SvgDrawContext context) {
117116
PdfCanvas canvas = context.getCurrentCanvas();
118117
canvas.writeLiteral("% path\n");
119-
currentPoint = new Point(0,0);
118+
currentPoint = new Point(0, 0);
120119
for (IPathShape item : getShapes()) {
121120
item.draw(canvas);
122121
}
@@ -168,7 +167,7 @@ private String[] getShapeCoordinates(IPathShape shape, IPathShape previousShape,
168167
} else if (shape instanceof VerticalLineTo) {
169168
String currentX = String.valueOf(currentPoint.x);
170169
String currentY = String.valueOf(currentPoint.y);
171-
String[] yValues = concatenate(new String[] { currentY }, shape.isRelative() ? makeRelativeOperatorsAbsolute(operatorArgs, currentPoint.y) : operatorArgs);
170+
String[] yValues = concatenate(new String[]{currentY}, shape.isRelative() ? makeRelativeOperatorsAbsolute(operatorArgs, currentPoint.y) : operatorArgs);
172171
shapeCoordinates = concatenate(new String[]{currentX}, yValues);
173172

174173
} else if (shape instanceof HorizontalLineTo) {
@@ -237,7 +236,7 @@ private List<IPathShape> processPathOperator(String[] pathProperties, IPathShape
237236
}
238237

239238
/**
240-
* Processes the {@link SvgConstants.Attributes.D} {@link PathSvgNodeRenderer#attributesAndStyles} and converts them
239+
* Processes the {@link SvgConstants.Attributes#D} {@link PathSvgNodeRenderer#attributesAndStyles} and converts them
241240
* into one or more {@link IPathShape} objects to be drawn on the canvas.
242241
* <p>
243242
* Each individual operator is passed to {@link PathSvgNodeRenderer#processPathOperator(String[], IPathShape)} to be processed individually.
@@ -264,6 +263,7 @@ private static String[] concatenate(String[] first, String[] second) {
264263
return arr;
265264
}
266265

266+
267267
boolean containsInvalidAttributes(String attributes) {
268268
return SvgRegexUtils.containsAtLeastOneMatch(invalidRegexPattern,attributes);
269269
}
@@ -289,43 +289,37 @@ private Collection<String> parsePropertiesAndStyles() {
289289
}
290290

291291
String[] resultArray = result.toString().split(SPLIT_REGEX);
292-
List<String> resultList = new ArrayList<>(Arrays.asList(resultArray));
293-
294-
return resultList;
292+
return new ArrayList<>(Arrays.asList(resultArray));
295293
}
296294

297295
/**
298296
* Iterate over the input string and to seperate
299-
* @param input
300-
* @return
301297
*/
302-
String separateDecimalPoints(String input){
298+
String separateDecimalPoints(String input) {
303299
//If a space or minus sign is found reset
304300
//If a another point is found, add an extra space on before the point
305-
String res="";
301+
StringBuilder res = new StringBuilder();
306302
//Iterate over string
307303
boolean decimalPointEncountered = false;
308304
for (int i = 0; i < input.length(); i++) {
309305
char c = input.charAt(i);
310-
//If it's a whitespace or minus sign and a point was previously found, reset
311-
if(decimalPointEncountered && (c=='-' || Character.isWhitespace(c))){
306+
//If it's a whitespace or a minus sign and a point was previously found, reset the decimal point flag
307+
if (decimalPointEncountered && (c == '-' || Character.isWhitespace(c))) {
312308
decimalPointEncountered = false;
313309
}
314310
//If a point is found, mark and continue
315-
if(c =='.'){
316-
//If it's the second point, add extra space
317-
if(decimalPointEncountered){
318-
res+=" ";
319-
}else{
320-
decimalPointEncountered=true;
311+
if (c == '.') {
312+
//If it's the second point, add an extra space
313+
if (decimalPointEncountered) {
314+
res.append(" ");
315+
} else {
316+
decimalPointEncountered = true;
321317
}
318+
} else if (c == '-') {// If a minus is found, add an extra space
319+
res.append(" ");
322320
}
323-
res+=c;
321+
res.append(c);
324322
}
325-
326-
327-
return res;
323+
return res.toString();
328324
}
329-
330-
331325
}

0 commit comments

Comments
 (0)