@@ -22,6 +22,7 @@ This file is part of the iText (R) project.
22
22
*/
23
23
package com .itextpdf .svg .renderers .impl ;
24
24
25
+ import com .itextpdf .commons .utils .MessageFormatUtil ;
25
26
import com .itextpdf .kernel .font .PdfFont ;
26
27
import com .itextpdf .kernel .geom .AffineTransform ;
27
28
import com .itextpdf .kernel .geom .Point ;
@@ -43,6 +44,7 @@ This file is part of the iText (R) project.
43
44
import com .itextpdf .layout .renderer .ParagraphRenderer ;
44
45
import com .itextpdf .styledxmlparser .css .util .CssDimensionParsingUtils ;
45
46
import com .itextpdf .styledxmlparser .css .util .CssUtils ;
47
+ import com .itextpdf .styledxmlparser .exceptions .StyledXMLParserException ;
46
48
import com .itextpdf .svg .SvgConstants ;
47
49
import com .itextpdf .svg .css .SvgStrokeParameterConverter .PdfLineDashParameters ;
48
50
import com .itextpdf .svg .renderers .ISvgNodeRenderer ;
@@ -127,7 +129,7 @@ public float[] getRelativeTranslation() {
127
129
128
130
public float [] getRelativeTranslation (SvgDrawContext context ) {
129
131
if (!moveResolved ) {
130
- resolveTextMove (context );
132
+ resolveRelativeTextMove (context );
131
133
}
132
134
return new float []{xMove , yMove };
133
135
}
@@ -140,21 +142,33 @@ public boolean containsRelativeMove() {
140
142
141
143
public boolean containsRelativeMove (SvgDrawContext context ) {
142
144
if (!moveResolved ) {
143
- resolveTextMove (context );
145
+ resolveRelativeTextMove (context );
144
146
}
145
147
boolean isNullMove = CssUtils .compareFloats (0f , xMove ) && CssUtils .compareFloats (0f , yMove ); // comparison to 0
146
148
return !isNullMove ;
147
149
}
148
150
149
151
@ Override
150
152
public boolean containsAbsolutePositionChange () {
151
- if (!posResolved ) resolveTextPosition ();
153
+ return containsAbsolutePositionChange (new SvgDrawContext (null , null ));
154
+ }
155
+
156
+ public boolean containsAbsolutePositionChange (SvgDrawContext context ) {
157
+ if (!posResolved ) {
158
+ resolveAbsoluteTextPosition (context );
159
+ }
152
160
return (xPos != null && xPos .length > 0 ) || (yPos != null && yPos .length > 0 );
153
161
}
154
162
155
163
@ Override
156
164
public float [][] getAbsolutePositionChanges () {
157
- if (!posResolved ) resolveTextPosition ();
165
+ return getAbsolutePositionChanges (new SvgDrawContext (null , null ));
166
+ }
167
+
168
+ public float [][] getAbsolutePositionChanges (SvgDrawContext context ) {
169
+ if (!posResolved ) {
170
+ resolveAbsoluteTextPosition (context );
171
+ }
158
172
return new float [][]{xPos , yPos };
159
173
}
160
174
@@ -178,12 +192,13 @@ public TextRectangle getTextRectangle(SvgDrawContext context, Point startPoint)
178
192
// building of properly positioned rectangles without any drawing or visual properties applying.
179
193
for (ISvgTextNodeRenderer child : children ) {
180
194
if (child instanceof TextSvgBranchRenderer ) {
181
- startPoint = ((TextSvgBranchRenderer ) child ).getStartPoint (context , startPoint );
182
- if (child .containsAbsolutePositionChange () && textChunkRect != null ) {
195
+ TextSvgBranchRenderer childText = (TextSvgBranchRenderer ) child ;
196
+ startPoint = childText .getStartPoint (context , startPoint );
197
+ if (childText .containsAbsolutePositionChange (context ) && textChunkRect != null ) {
183
198
commonRect = getCommonRectangleWithAnchor (commonRect , textChunkRect , rootX , textAnchorValue );
184
199
// Start new text chunk.
185
200
textChunkRect = null ;
186
- textAnchorValue = child .getAttribute (SvgConstants .Attributes .TEXT_ANCHOR );
201
+ textAnchorValue = childText .getAttribute (SvgConstants .Attributes .TEXT_ANCHOR );
187
202
rootX = (float ) startPoint .getX ();
188
203
}
189
204
} else {
@@ -208,7 +223,7 @@ public Rectangle getObjectBoundingBox(SvgDrawContext context) {
208
223
if (objectBoundingBox == null ) {
209
224
// Handle white-spaces
210
225
if (!whiteSpaceProcessed ) {
211
- SvgTextUtil .processWhiteSpace (this , true );
226
+ SvgTextUtil .processWhiteSpace (this , true , context );
212
227
}
213
228
objectBoundingBox = getTextRectangle (context , null );
214
229
}
@@ -235,7 +250,7 @@ protected void doDraw(SvgDrawContext context) {
235
250
}
236
251
// Handle white-spaces
237
252
if (!whiteSpaceProcessed ) {
238
- SvgTextUtil .processWhiteSpace (this , true );
253
+ SvgTextUtil .processWhiteSpace (this , true , context );
239
254
}
240
255
241
256
this .paragraph = new Paragraph ();
@@ -311,10 +326,10 @@ void addTextChild(Text text, SvgDrawContext drawContext) {
311
326
}
312
327
313
328
void performDrawing (SvgDrawContext context ) {
314
- if (this .containsAbsolutePositionChange ()) {
329
+ if (this .containsAbsolutePositionChange (context )) {
315
330
drawLastTextChunk (context );
316
331
// TODO: DEVSIX-2507 support rotate and other attributes
317
- float [][] absolutePositions = this .getAbsolutePositionChanges ();
332
+ float [][] absolutePositions = this .getAbsolutePositionChanges (context );
318
333
AffineTransform newTransform = getTextTransform (absolutePositions , context );
319
334
startNewTextChunk (context , newTransform );
320
335
}
@@ -383,7 +398,7 @@ void applyFillAndStrokeProperties(FillProperties fillProperties, StrokePropertie
383
398
}
384
399
}
385
400
386
- private void resolveTextMove (SvgDrawContext context ) {
401
+ private void resolveRelativeTextMove (SvgDrawContext context ) {
387
402
if (this .attributesAndStyles != null ) {
388
403
String xRawValue = this .attributesAndStyles .get (SvgConstants .Attributes .DX );
389
404
String yRawValue = this .attributesAndStyles .get (SvgConstants .Attributes .DY );
@@ -405,18 +420,39 @@ private void resolveTextMove(SvgDrawContext context) {
405
420
}
406
421
}
407
422
408
- private void resolveTextPosition ( ) {
423
+ private void resolveAbsoluteTextPosition ( SvgDrawContext context ) {
409
424
if (this .attributesAndStyles != null ) {
410
425
String xRawValue = this .attributesAndStyles .get (SvgConstants .Attributes .X );
411
426
String yRawValue = this .attributesAndStyles .get (SvgConstants .Attributes .Y );
412
427
413
- xPos = getPositionsFromString (xRawValue );
414
- yPos = getPositionsFromString (yRawValue );
428
+ xPos = getPositionsFromString (xRawValue , context , true );
429
+ yPos = getPositionsFromString (yRawValue , context , false );
415
430
416
431
posResolved = true ;
417
432
}
418
433
}
419
434
435
+ private float [] getPositionsFromString (String rawValuesString , SvgDrawContext context , boolean isHorizontal ) {
436
+ float [] result = null ;
437
+ List <String > valuesList = SvgCssUtils .splitValueList (rawValuesString );
438
+ if (!valuesList .isEmpty ()) {
439
+ result = new float [valuesList .size ()];
440
+ for (int i = 0 ; i < valuesList .size (); i ++) {
441
+ String value = valuesList .get (i );
442
+ if (CssDimensionParsingUtils .determinePositionBetweenValueAndUnit (value ) == 0 ) {
443
+ throw new StyledXMLParserException (MessageFormatUtil .format (StyledXMLParserException .NAN , value ));
444
+ }
445
+ if (isHorizontal ) {
446
+ result [i ] = parseHorizontalLength (value , context );
447
+ } else {
448
+ result [i ] = parseVerticalLength (value , context );
449
+ }
450
+ }
451
+ }
452
+
453
+ return result ;
454
+ }
455
+
420
456
private static AffineTransform getTextTransform (float [][] absolutePositions , SvgDrawContext context ) {
421
457
AffineTransform tf = new AffineTransform ();
422
458
// If x is not specified, but y is, we need to correct for preceding text.
@@ -435,19 +471,6 @@ private static AffineTransform getTextTransform(float[][] absolutePositions, Svg
435
471
return tf ;
436
472
}
437
473
438
- private static float [] getPositionsFromString (String rawValuesString ) {
439
- float [] result = null ;
440
- List <String > valuesList = SvgCssUtils .splitValueList (rawValuesString );
441
- if (!valuesList .isEmpty ()) {
442
- result = new float [valuesList .size ()];
443
- for (int i = 0 ; i < valuesList .size (); i ++) {
444
- result [i ] = CssDimensionParsingUtils .parseAbsoluteLength (valuesList .get (i ));
445
- }
446
- }
447
-
448
- return result ;
449
- }
450
-
451
474
/**
452
475
* Adjust absolutely positioned text chunk (shift it to the start of view port, apply text anchor) and
453
476
* merge it with the common text rectangle.
@@ -509,14 +532,16 @@ private void applyTextAnchor(String textAnchorValue, boolean isRtl) {
509
532
}
510
533
511
534
private Point getStartPoint (SvgDrawContext context , Point basePoint ) {
512
- double x = 0 , y = 0 ;
513
- if (getAbsolutePositionChanges ()[0 ] != null ) {
514
- x = getAbsolutePositionChanges ()[0 ][0 ];
535
+ double x = 0 ;
536
+ double y = 0 ;
537
+ float [][] absolutePosition = getAbsolutePositionChanges (context );
538
+ if (absolutePosition [0 ] != null ) {
539
+ x = absolutePosition [0 ][0 ];
515
540
} else if (basePoint != null ) {
516
541
x = basePoint .getX ();
517
542
}
518
- if (getAbsolutePositionChanges () [1 ] != null ) {
519
- y = getAbsolutePositionChanges () [1 ][0 ];
543
+ if (absolutePosition [1 ] != null ) {
544
+ y = absolutePosition [1 ][0 ];
520
545
} else if (basePoint != null ) {
521
546
y = basePoint .getY ();
522
547
}
0 commit comments