Skip to content

Commit 9761a2e

Browse files
committed
Major fixes in rounded borders processing.
DEVSIX-1311
1 parent 8b1afc0 commit 9761a2e

File tree

13 files changed

+470
-91
lines changed

13 files changed

+470
-91
lines changed

layout/src/main/java/com/itextpdf/layout/border/Border.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ This file is part of the iText (R) project.
4444
package com.itextpdf.layout.border;
4545

4646
import com.itextpdf.kernel.color.Color;
47+
import com.itextpdf.kernel.geom.Point;
4748
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
4849
import com.itextpdf.layout.property.TransparentColor;
4950

@@ -446,4 +447,16 @@ protected Side getBorderSide(float x1, float y1, float x2, float y2) {
446447
public enum Side {
447448
NONE, TOP, RIGHT, BOTTOM, LEFT
448449
}
450+
451+
452+
protected Point getIntersectionPoint(Point lineBeg, Point lineEnd, Point clipLineBeg, Point clipLineEnd) {
453+
double A1 = lineBeg.getY() - lineEnd.getY(), A2 = clipLineBeg.getY() - clipLineEnd.getY();
454+
double B1 = lineEnd.getX() - lineBeg.getX(), B2 = clipLineEnd.getX() - clipLineBeg.getX();
455+
double C1 = lineBeg.getX() * lineEnd.getY() - lineBeg.getY() * lineEnd.getX();
456+
double C2 = clipLineBeg.getX() * clipLineEnd.getY() - clipLineBeg.getY() * clipLineEnd.getX();
457+
458+
double M = B1 * A2 - B2 * A1;
459+
460+
return new Point((B2 * C1 - B1 * C2) / M, (C2 * A1 - C1 * A2) / M);
461+
}
449462
}

layout/src/main/java/com/itextpdf/layout/border/DashedBorder.java

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ This file is part of the iText (R) project.
4444
package com.itextpdf.layout.border;
4545

4646
import com.itextpdf.kernel.color.Color;
47+
import com.itextpdf.kernel.geom.Point;
4748
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
4849

4950
/**
@@ -190,6 +191,7 @@ public void draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float
190191
adjustedGap -= dash;
191192
}
192193

194+
// Points (x0, y0) and (x3, y3) are used to produce Bezier curve
193195
float x0 = x1, y0 = y1,
194196
x3 = x2, y3 = y2;
195197

@@ -206,7 +208,7 @@ public void draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float
206208
transparentColor.applyStrokeTransparency(canvas);
207209
canvas.setLineDash(dash, adjustedGap, dash + adjustedGap / 2);
208210

209-
211+
Point clipPoint1, clipPoint2, clipPoint;
210212
Border.Side borderSide = getBorderSide(x1, y1, x2, y2);
211213
switch (borderSide) {
212214
case TOP:
@@ -216,6 +218,16 @@ public void draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float
216218
x3 += borderWidthAfter / 2;
217219
y3 -= innerRadius;
218220

221+
clipPoint1 = getIntersectionPoint(new Point(x1 - borderWidthBefore, y1 + width), new Point(x1, y1), new Point(x0, y0), new Point(x0 + 10, y0));
222+
clipPoint2 = getIntersectionPoint(new Point(x2 + borderWidthAfter, y2 + width), new Point(x2, y2), new Point(x3, y3), new Point(x3 - 10, y3));
223+
if (clipPoint1.x > clipPoint2.x) {
224+
clipPoint = getIntersectionPoint(new Point(x1 - borderWidthBefore, y1 + width), clipPoint1, clipPoint2, new Point(x2 + borderWidthAfter, y2 + width));
225+
canvas.moveTo(x1 - borderWidthBefore, y1 + width).lineTo(clipPoint.x, clipPoint.y).lineTo(x2 + borderWidthAfter, y2 + width).lineTo(x1 - borderWidthBefore, y1 + width);
226+
} else {
227+
canvas.moveTo(x1 - borderWidthBefore, y1 + width).lineTo(clipPoint1.x, clipPoint1.y).lineTo(clipPoint2.x, clipPoint2.y).lineTo(x2 + borderWidthAfter, y2 + width).lineTo(x1 - borderWidthBefore, y1 + width);
228+
}
229+
canvas.clip().newPath();
230+
219231
x1 += innerRadiusBefore;
220232
y1 += widthHalf;
221233

@@ -226,16 +238,24 @@ public void draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float
226238
.moveTo(x0, y0).curveTo(x0, y0 + innerRadius * curv, x1 - innerRadiusBefore * curv, y1, x1, y1)
227239
.lineTo(x2, y2)
228240
.curveTo(x2 + innerRadiusAfter * curv, y2, x3, y3 + innerRadius * curv, x3, y3);
229-
230241
break;
231242
case RIGHT:
232-
233243
x0 -= innerRadius;
234244
y0 += borderWidthBefore / 2;
235245

236246
x3 -= innerRadius;
237247
y3 -= borderWidthAfter;
238248

249+
clipPoint1 = getIntersectionPoint(new Point(x1 + width, y1 + borderWidthBefore), new Point(x1, y1), new Point(x0, y0), new Point(x0, y0 - 10));
250+
clipPoint2 = getIntersectionPoint(new Point(x2 + width, y2 -borderWidthAfter), new Point(x2, y2), new Point(x3, y3), new Point(x3, y3 - 10));
251+
if (clipPoint1.y < clipPoint2.y) {
252+
clipPoint = getIntersectionPoint(new Point(x1 + width, y1 + borderWidthBefore), clipPoint1, clipPoint2, new Point(x2 + width, y2 -borderWidthAfter));
253+
canvas.moveTo(x1 + width, y1 + borderWidthBefore).lineTo(clipPoint.x, clipPoint.y).lineTo(x2 + width, y2 -borderWidthAfter).lineTo(x1 + width, y1 + borderWidthBefore).clip().newPath();
254+
} else {
255+
canvas.moveTo(x1 + width, y1 + borderWidthBefore).lineTo(clipPoint1.x, clipPoint1.y).lineTo(clipPoint2.x, clipPoint2.y).lineTo(x2 + width, y2 -borderWidthAfter).lineTo(x1 + width, y1 + borderWidthBefore).clip().newPath();
256+
}
257+
canvas.clip().newPath();
258+
239259
x1 += widthHalf;
240260
y1 -= innerRadiusBefore;
241261

@@ -255,6 +275,16 @@ public void draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float
255275
x3 -= borderWidthAfter / 2;
256276
y3 += innerRadius;
257277

278+
clipPoint1 = getIntersectionPoint(new Point(x1 + borderWidthBefore, y1 - width), new Point(x1, y1), new Point(x0, y0), new Point(x0 - 10, y0));
279+
clipPoint2 = getIntersectionPoint(new Point(x2 - borderWidthAfter, y2 - width), new Point(x2, y2), new Point(x3, y3), new Point(x3 + 10, y3));
280+
if (clipPoint1.x < clipPoint2.x) {
281+
clipPoint = getIntersectionPoint(new Point(x1 + borderWidthBefore, y1 - width), clipPoint1, clipPoint2, new Point(x2 - borderWidthAfter, y2 - width));
282+
canvas.moveTo(x1 + borderWidthBefore, y1 - width).lineTo(clipPoint.x, clipPoint.y).lineTo(x2 - borderWidthAfter, y2 - width).lineTo(x1 + borderWidthBefore, y1 - width);
283+
} else {
284+
canvas.moveTo(x1 + borderWidthBefore, y1 - width).lineTo(clipPoint1.x, clipPoint1.y).lineTo(clipPoint2.x, clipPoint2.y).lineTo(x2 - borderWidthAfter, y2 - width).lineTo(x1 + borderWidthBefore, y1 - width);
285+
}
286+
canvas.clip().newPath();
287+
258288
x1 -= innerRadiusBefore;
259289
y1 -= widthHalf;
260290

@@ -272,7 +302,17 @@ public void draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float
272302
y0 -= borderWidthBefore / 2;
273303

274304
x3 += innerRadius;
275-
y3 -= borderWidthAfter;
305+
y3 += borderWidthAfter;
306+
307+
clipPoint1 = getIntersectionPoint(new Point(x1 - width, y1 - borderWidthBefore), new Point(x1, y1), new Point(x0, y0), new Point(x0, y0 + 10));
308+
clipPoint2 = getIntersectionPoint(new Point(x2 - width, y2 + borderWidthAfter), new Point(x2, y2), new Point(x3, y3), new Point(x3, y3 + 10));
309+
if (clipPoint1.y > clipPoint2.y) {
310+
clipPoint = getIntersectionPoint(new Point(x1 - width, y1 - borderWidthBefore), clipPoint1, clipPoint2, new Point(x2 - width, y2 + borderWidthAfter));
311+
canvas.moveTo(x1 - width, y1 - borderWidthBefore).lineTo(clipPoint.x, clipPoint.y).lineTo(x2 - width, y2 + borderWidthAfter).lineTo(x1 - width, y1 - borderWidthBefore);
312+
} else {
313+
canvas.moveTo(x1 - width, y1 - borderWidthBefore).lineTo(clipPoint1.x, clipPoint1.y).lineTo(clipPoint2.x, clipPoint2.y).lineTo(x2 - width, y2 + borderWidthAfter).lineTo(x1 - width, y1 - borderWidthBefore);
314+
}
315+
canvas.clip().newPath();
276316

277317
x1 -= widthHalf;
278318
y1 += innerRadiusBefore;
@@ -286,7 +326,8 @@ public void draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float
286326
.curveTo(x2, y2 + innerRadiusAfter * curv, x3 - innerRadius * curv, y3, x3, y3);
287327
break;
288328
}
289-
canvas.stroke()
329+
canvas
330+
.stroke()
290331
.restoreState();
291332
}
292333

layout/src/main/java/com/itextpdf/layout/border/DottedBorder.java

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ This file is part of the iText (R) project.
4444
package com.itextpdf.layout.border;
4545

4646
import com.itextpdf.kernel.color.Color;
47+
import com.itextpdf.kernel.geom.Point;
4748
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
4849

4950
/**
@@ -157,6 +158,7 @@ public void draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float
157158
adjustedGap -= width;
158159
}
159160

161+
// Points (x0, y0) and (x3, y3) are used to produce Bezier curve
160162
float x0 = x1, y0 = y1,
161163
x3 = x2, y3 = y2;
162164

@@ -173,7 +175,7 @@ public void draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float
173175
transparentColor.applyStrokeTransparency(canvas);
174176
canvas.setLineDash(width, adjustedGap, width + adjustedGap / 2);
175177

176-
178+
Point clipPoint1, clipPoint2, clipPoint;
177179
Border.Side borderSide = getBorderSide(x1, y1, x2, y2);
178180
switch (borderSide) {
179181
case TOP:
@@ -183,6 +185,16 @@ public void draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float
183185
x3 += borderWidthAfter / 2;
184186
y3 -= innerRadius;
185187

188+
clipPoint1 = getIntersectionPoint(new Point(x1 - borderWidthBefore, y1 + width), new Point(x1, y1), new Point(x0, y0), new Point(x0 + 10, y0));
189+
clipPoint2 = getIntersectionPoint(new Point(x2 + borderWidthAfter, y2 + width), new Point(x2, y2), new Point(x3, y3), new Point(x3 - 10, y3));
190+
if (clipPoint1.x > clipPoint2.x) {
191+
clipPoint = getIntersectionPoint(new Point(x1 - borderWidthBefore, y1 + width), clipPoint1, clipPoint2, new Point(x2 + borderWidthAfter, y2 + width));
192+
canvas.moveTo(x1 - borderWidthBefore, y1 + width).lineTo(clipPoint.x, clipPoint.y).lineTo(x2 + borderWidthAfter, y2 + width).lineTo(x1 - borderWidthBefore, y1 + width);
193+
} else {
194+
canvas.moveTo(x1 - borderWidthBefore, y1 + width).lineTo(clipPoint1.x, clipPoint1.y).lineTo(clipPoint2.x, clipPoint2.y).lineTo(x2 + borderWidthAfter, y2 + width).lineTo(x1 - borderWidthBefore, y1 + width);
195+
}
196+
canvas.clip().newPath();
197+
186198
x1 += innerRadiusBefore;
187199
y1 += widthHalf;
188200

@@ -193,16 +205,24 @@ public void draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float
193205
.moveTo(x0, y0).curveTo(x0, y0 + innerRadius * curv, x1 - innerRadiusBefore * curv, y1, x1, y1)
194206
.lineTo(x2, y2)
195207
.curveTo(x2 + innerRadiusAfter * curv, y2, x3, y3 + innerRadius * curv, x3, y3);
196-
197208
break;
198209
case RIGHT:
199-
200210
x0 -= innerRadius;
201211
y0 += borderWidthBefore / 2;
202212

203213
x3 -= innerRadius;
204214
y3 -= borderWidthAfter;
205215

216+
clipPoint1 = getIntersectionPoint(new Point(x1 + width, y1 + borderWidthBefore), new Point(x1, y1), new Point(x0, y0), new Point(x0, y0 - 10));
217+
clipPoint2 = getIntersectionPoint(new Point(x2 + width, y2 - borderWidthAfter), new Point(x2, y2), new Point(x3, y3), new Point(x3, y3 - 10));
218+
if (clipPoint1.y < clipPoint2.y) {
219+
clipPoint = getIntersectionPoint(new Point(x1 + width, y1 + borderWidthBefore), clipPoint1, clipPoint2, new Point(x2 + width, y2 - borderWidthAfter));
220+
canvas.moveTo(x1 + width, y1 + borderWidthBefore).lineTo(clipPoint.x, clipPoint.y).lineTo(x2 + width, y2 - borderWidthAfter).lineTo(x1 + width, y1 + borderWidthBefore).clip().newPath();
221+
} else {
222+
canvas.moveTo(x1 + width, y1 + borderWidthBefore).lineTo(clipPoint1.x, clipPoint1.y).lineTo(clipPoint2.x, clipPoint2.y).lineTo(x2 + width, y2 - borderWidthAfter).lineTo(x1 + width, y1 + borderWidthBefore).clip().newPath();
223+
}
224+
canvas.clip().newPath();
225+
206226
x1 += widthHalf;
207227
y1 -= innerRadiusBefore;
208228

@@ -222,6 +242,16 @@ public void draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float
222242
x3 -= borderWidthAfter / 2;
223243
y3 += innerRadius;
224244

245+
clipPoint1 = getIntersectionPoint(new Point(x1 + borderWidthBefore, y1 - width), new Point(x1, y1), new Point(x0, y0), new Point(x0 - 10, y0));
246+
clipPoint2 = getIntersectionPoint(new Point(x2 - borderWidthAfter, y2 - width), new Point(x2, y2), new Point(x3, y3), new Point(x3 + 10, y3));
247+
if (clipPoint1.x < clipPoint2.x) {
248+
clipPoint = getIntersectionPoint(new Point(x1 + borderWidthBefore, y1 - width), clipPoint1, clipPoint2, new Point(x2 - borderWidthAfter, y2 - width));
249+
canvas.moveTo(x1 + borderWidthBefore, y1 - width).lineTo(clipPoint.x, clipPoint.y).lineTo(x2 - borderWidthAfter, y2 - width).lineTo(x1 + borderWidthBefore, y1 - width);
250+
} else {
251+
canvas.moveTo(x1 + borderWidthBefore, y1 - width).lineTo(clipPoint1.x, clipPoint1.y).lineTo(clipPoint2.x, clipPoint2.y).lineTo(x2 - borderWidthAfter, y2 - width).lineTo(x1 + borderWidthBefore, y1 - width);
252+
}
253+
canvas.clip().newPath();
254+
225255
x1 -= innerRadiusBefore;
226256
y1 -= widthHalf;
227257

@@ -239,7 +269,17 @@ public void draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float
239269
y0 -= borderWidthBefore / 2;
240270

241271
x3 += innerRadius;
242-
y3 -= borderWidthAfter;
272+
y3 += borderWidthAfter;
273+
274+
clipPoint1 = getIntersectionPoint(new Point(x1 - width, y1 - borderWidthBefore), new Point(x1, y1), new Point(x0, y0), new Point(x0, y0 + 10));
275+
clipPoint2 = getIntersectionPoint(new Point(x2 - width, y2 + borderWidthAfter), new Point(x2, y2), new Point(x3, y3), new Point(x3, y3 + 10));
276+
if (clipPoint1.y > clipPoint2.y) {
277+
clipPoint = getIntersectionPoint(new Point(x1 - width, y1 - borderWidthBefore), clipPoint1, clipPoint2, new Point(x2 - width, y2 + borderWidthAfter));
278+
canvas.moveTo(x1 - width, y1 - borderWidthBefore).lineTo(clipPoint.x, clipPoint.y).lineTo(x2 - width, y2 + borderWidthAfter).lineTo(x1 - width, y1 - borderWidthBefore);
279+
} else {
280+
canvas.moveTo(x1 - width, y1 - borderWidthBefore).lineTo(clipPoint1.x, clipPoint1.y).lineTo(clipPoint2.x, clipPoint2.y).lineTo(x2 - width, y2 + borderWidthAfter).lineTo(x1 - width, y1 - borderWidthBefore);
281+
}
282+
canvas.clip().newPath();
243283

244284
x1 -= widthHalf;
245285
y1 += innerRadiusBefore;
@@ -253,7 +293,8 @@ public void draw(PdfCanvas canvas, float x1, float y1, float x2, float y2, float
253293
.curveTo(x2, y2 + innerRadiusAfter * curv, x3 - innerRadius * curv, y3, x3, y3);
254294
break;
255295
}
256-
canvas.stroke()
296+
canvas
297+
.stroke()
257298
.restoreState();
258299
}
259300

0 commit comments

Comments
 (0)