diff --git a/src/core/font_renderer.js b/src/core/font_renderer.js index f03a274c8..3634d1cdb 100644 --- a/src/core/font_renderer.js +++ b/src/core/font_renderer.js @@ -170,6 +170,11 @@ function lookupCmap(ranges, unicode) { function compileGlyf(code, cmds, font) { function moveTo(x, y) { + if (firstPoint) { + // Close the current subpath in adding a straight line to the first point. + cmds.add("L", firstPoint); + } + firstPoint = [x, y]; cmds.add("M", [x, y]); } function lineTo(x, y) { @@ -182,6 +187,7 @@ function compileGlyf(code, cmds, font) { let i = 0; const numberOfContours = getInt16(code, i); let flags; + let firstPoint = null; let x = 0, y = 0; i += 10; @@ -350,6 +356,11 @@ function compileGlyf(code, cmds, font) { function compileCharString(charStringCode, cmds, font, glyphId) { function moveTo(x, y) { + if (firstPoint) { + // Close the current subpath in adding a straight line to the first point. + cmds.add("L", firstPoint); + } + firstPoint = [x, y]; cmds.add("M", [x, y]); } function lineTo(x, y) { @@ -363,6 +374,7 @@ function compileCharString(charStringCode, cmds, font, glyphId) { let x = 0, y = 0; let stems = 0; + let firstPoint = null; function parse(code) { let i = 0; diff --git a/src/display/canvas.js b/src/display/canvas.js index ee9c4f053..3b56fb0d8 100644 --- a/src/display/canvas.js +++ b/src/display/canvas.js @@ -2043,12 +2043,13 @@ class CanvasGraphics { ctx.save(); ctx.translate(x, y); ctx.scale(fontSize, -fontSize); + let currentTransform; if ( fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE ) { if (patternFillTransform) { - const currentTransform = ctx.getTransform(); + currentTransform = ctx.getTransform(); ctx.setTransform(...patternFillTransform); ctx.fill( this.#getScaledPath(path, currentTransform, patternFillTransform) @@ -2062,8 +2063,22 @@ class CanvasGraphics { fillStrokeMode === TextRenderingMode.FILL_STROKE ) { if (patternStrokeTransform) { - const currentTransform = ctx.getTransform(); + currentTransform ||= ctx.getTransform(); ctx.setTransform(...patternStrokeTransform); + const { a, b, c, d } = currentTransform; + const invPatternTransform = Util.inverseTransform( + patternStrokeTransform + ); + const transf = Util.transform( + [a, b, c, d, 0, 0], + invPatternTransform + ); + const [sx, sy] = Util.singularValueDecompose2dScale(transf); + + // Cancel the pattern scaling of the line width. + // If sx and sy are different, unfortunately we can't do anything and + // we'll have a rendering bug. + ctx.lineWidth *= Math.max(sx, sy) / fontSize; ctx.stroke( this.#getScaledPath(path, currentTransform, patternStrokeTransform) ); diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 9105960cb..f9e0cd705 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -696,3 +696,4 @@ !issue18911.pdf !issue19207.pdf !issue19239.pdf +!issue19360.pdf diff --git a/test/pdfs/issue19360.pdf b/test/pdfs/issue19360.pdf new file mode 100755 index 000000000..558b3c59d Binary files /dev/null and b/test/pdfs/issue19360.pdf differ diff --git a/test/test_manifest.json b/test/test_manifest.json index 03c40750c..759b73237 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -11286,5 +11286,12 @@ "firstPage": 2, "lastPage": 2, "type": "eq" + }, + { + "id": "issue19360", + "file": "pdfs/issue19360.pdf", + "md5": "b2de376f7e96fa2b6afc00dac016c40a", + "rounds": 1, + "type": "eq" } ]