diff --git a/pdf/draw_absolute_test.go b/pdf/draw_absolute_test.go
index 15cf720..4735111 100644
--- a/pdf/draw_absolute_test.go
+++ b/pdf/draw_absolute_test.go
@@ -816,6 +816,6 @@ func TestAbsoluteImageBackground(t *testing.T) {
left: 1px;
}
-
+
`)
}
diff --git a/pdf/draw_background_test.go b/pdf/draw_background_test.go
index 1c22991..694a06b 100644
--- a/pdf/draw_background_test.go
+++ b/pdf/draw_background_test.go
@@ -11,8 +11,7 @@ import (
// Test how backgrounds are drawn.
func TestCanvasBackground(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
for _, data := range [][3]string{
{"all_blue", strings.Repeat(strings.Repeat("B", 10)+"\n", 10), `
`)
}
func TestPageBackgroundFixed(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
// Regression test for https://github.com/Kozea/WeasyPrint/issues/1993
assertPixelsEqual(t, `
RBBB
@@ -1072,15 +1055,14 @@ func TestPageBackgroundFixed(t *testing.T) {
`, `
`)
}
func TestPageBackgroundFixedBleed(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
// Regression test for https://github.com/Kozea/WeasyPrint/issues/1993
assertPixelsEqual(t, `
RRRRRR
@@ -1092,15 +1074,14 @@ func TestPageBackgroundFixedBleed(t *testing.T) {
`, `
`)
}
func TestBleedBackgroundSizeClip(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
// Regression test for https://github.com/Kozea/WeasyPrint/issues/1943
assertPixelsEqual(t, `
BBBBBB
@@ -1112,15 +1093,14 @@ func TestBleedBackgroundSizeClip(t *testing.T) {
`, `
`)
}
func TestMarksCrop(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
KK__KK
K____K
@@ -1136,8 +1116,7 @@ func TestMarksCrop(t *testing.T) {
}
func TestMarksCross(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
__KK__
______
@@ -1153,8 +1132,7 @@ func TestMarksCross(t *testing.T) {
}
func TestMarksCropCross(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
KKKKKK
K____K
diff --git a/pdf/draw_box_test.go b/pdf/draw_box_test.go
index 2a3b805..5847135 100644
--- a/pdf/draw_box_test.go
+++ b/pdf/draw_box_test.go
@@ -106,12 +106,11 @@ func TestBorders(t *testing.T) {
// Test the rendering of collapsing borders.
func TestBordersTableCollapse(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
source := `
abc | `
@@ -119,13 +118,17 @@ func TestBordersTableCollapse(t *testing.T) {
// Do not test the exact rendering of earch border style but at least
// check that they do not do the same.
var documents []string
- for _, borderStyle := range []string{
+ for _, borderStyle := range [...]string{
"none", "solid", "dashed", "dotted", "double",
- "inset", "outset", "groove", "ridge",
+ "outset", /* "groove", */
+ "inset", /* "ridge", */
} {
documents = append(documents, fmt.Sprintf(source, borderStyle))
}
assertDifferentRenderings(t, documents)
+
+ assertSameRendering(t, fmt.Sprintf(source, "outset"), fmt.Sprintf(source, "groove"), 0)
+ assertSameRendering(t, fmt.Sprintf(source, "inset"), fmt.Sprintf(source, "ridge"), 0)
}
func TestOutlines(t *testing.T) {
@@ -183,8 +186,7 @@ func TestEmBorders(t *testing.T) {
}
func TestBordersBoxSizing(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
________
_RRRRRR_
@@ -329,8 +331,7 @@ func TestRoundedRect(t *testing.T) {
}
func TestDrawBorderRadius(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
___zzzzz
__zzzzzz
@@ -357,8 +358,7 @@ func TestDrawBorderRadius(t *testing.T) {
}
func TestDrawSplitBorderRadius(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
___zzzzz
__zzzzzz
@@ -404,8 +404,7 @@ func TestDrawSplitBorderRadius(t *testing.T) {
}
func TestBorderImageStretch(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
__________
_RYYYMMMG_
@@ -422,7 +421,7 @@ func TestBorderImageStretch(t *testing.T) {
}
div {
border: 1px solid black;
- border-image-source: url(border.svg);
+ border-image-source: url(../resources_test/border.svg);
border-image-slice: 25%;
height: 4px;
margin: 1px;
@@ -434,8 +433,7 @@ func TestBorderImageStretch(t *testing.T) {
}
func TestBorderImageFill(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
__________
_RYYYMMMG_
@@ -452,7 +450,7 @@ func TestBorderImageFill(t *testing.T) {
}
div {
border: 1px solid black;
- border-image-source: url(border.svg);
+ border-image-source: url(../resources_test/border.svg);
border-image-slice: 25% fill;
height: 4px;
margin: 1px;
@@ -464,8 +462,7 @@ func TestBorderImageFill(t *testing.T) {
}
func TestBorderImageDefaultSlice(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_____________
_RYMG___RYMG_
@@ -486,7 +483,7 @@ func TestBorderImageDefaultSlice(t *testing.T) {
}
div {
border: 4px solid black;
- border-image-source: url(border.svg);
+ border-image-source: url(../resources_test/border.svg);
height: 2px;
margin: 1px;
width: 3px;
@@ -497,8 +494,7 @@ func TestBorderImageDefaultSlice(t *testing.T) {
}
func TestBorderImageUnevenWidth(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
____________
_RRRYYYMMMG_
@@ -516,7 +512,7 @@ func TestBorderImageUnevenWidth(t *testing.T) {
div {
border: 1px solid black;
border-left-width: 3px;
- border-image-source: url(border.svg);
+ border-image-source: url(../resources_test/border.svg);
border-image-slice: 25%;
height: 4px;
margin: 1px;
@@ -528,8 +524,7 @@ func TestBorderImageUnevenWidth(t *testing.T) {
}
func TestBorderImageNotPercent(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
__________
_RYYYMMMG_
@@ -546,7 +541,7 @@ func TestBorderImageNotPercent(t *testing.T) {
}
div {
border: 1px solid black;
- border-image-source: url(border.svg);
+ border-image-source: url(../resources_test/border.svg);
border-image-slice: 1;
height: 4px;
margin: 1px;
@@ -558,8 +553,7 @@ func TestBorderImageNotPercent(t *testing.T) {
}
func TestBorderImageRepeat(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
___________
_RYMYMYMYG_
@@ -576,7 +570,7 @@ func TestBorderImageRepeat(t *testing.T) {
}
div {
border: 1px solid black;
- border-image-source: url(border.svg);
+ border-image-source: url(../resources_test/border.svg);
border-image-slice: 25%;
border-image-repeat: repeat;
height: 4px;
@@ -589,8 +583,7 @@ func TestBorderImageRepeat(t *testing.T) {
}
func TestBorderImageSpace(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
_R_YMC_G_
@@ -608,7 +601,7 @@ func TestBorderImageSpace(t *testing.T) {
}
div {
border: 1px solid black;
- border-image-source: url(border2.svg);
+ border-image-source: url(../resources_test/border2.svg);
border-image-slice: 20%;
border-image-repeat: space;
height: 5px;
@@ -621,8 +614,7 @@ func TestBorderImageSpace(t *testing.T) {
}
func TestBorderImageOutset(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
____________
_RYYYYMMMMG_
@@ -641,7 +633,7 @@ func TestBorderImageOutset(t *testing.T) {
}
div {
border: 1px solid black;
- border-image-source: url(border.svg);
+ border-image-source: url(../resources_test/border.svg);
border-image-slice: 25%;
border-image-outset: 2px;
height: 2px;
@@ -655,8 +647,7 @@ func TestBorderImageOutset(t *testing.T) {
}
func TestBorderImageWidth(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
__________
_RRYYMMGG_
@@ -673,7 +664,7 @@ func TestBorderImageWidth(t *testing.T) {
}
div {
border: 1px solid black;
- border-image-source: url(border.svg);
+ border-image-source: url(../resources_test/border.svg);
border-image-slice: 25%;
border-image-width: 2;
height: 4px;
@@ -686,8 +677,7 @@ func TestBorderImageWidth(t *testing.T) {
}
func TestBorderImageGradient(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
__________
_RRRRRRRR_
diff --git a/pdf/draw_image_test.go b/pdf/draw_image_test.go
index 728fccd..4727e14 100644
--- a/pdf/draw_image_test.go
+++ b/pdf/draw_image_test.go
@@ -637,7 +637,7 @@ func TestImagesBorder(t *testing.T) {
body { margin: 0; font-size: 0 }
img { margin: 1px; border: 1px solid lime }
- `)
+ `)
}
func TestImagesBorderAbsolute(t *testing.T) {
@@ -649,7 +649,7 @@ func TestImagesBorderAbsolute(t *testing.T) {
body { margin: 0; font-size: 0 }
img { margin: 1px; border: 1px solid lime; position: absolute }
- `)
+ `)
}
func TestImageExif(t *testing.T) {
diff --git a/pdf/draw_svg_markers_test.go b/pdf/draw_svg_markers_test.go
index 162d707..73065d3 100644
--- a/pdf/draw_svg_markers_test.go
+++ b/pdf/draw_svg_markers_test.go
@@ -7,8 +7,7 @@ import (
)
func TestMarkers(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
___________
___________
@@ -44,8 +43,7 @@ func TestMarkers(t *testing.T) {
}
func TestMarkersViewbox(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
___________
____RRR____
@@ -81,8 +79,7 @@ func TestMarkersViewbox(t *testing.T) {
}
func TestMarkersSize(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
___________
____BBR____
@@ -120,8 +117,7 @@ func TestMarkersSize(t *testing.T) {
}
func TestMarkersViewboxSize(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
___________
____RRR____
@@ -195,8 +191,7 @@ func TestMarkersOverflow(t *testing.T) {
}
func TestMarkersUserspace(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
___________
___________
@@ -233,8 +228,7 @@ func TestMarkersUserspace(t *testing.T) {
}
func TestMarkersStrokeWidth(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
___________
___________
@@ -271,8 +265,7 @@ func TestMarkersStrokeWidth(t *testing.T) {
}
func TestMarkersViewboxStrokeWidth(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
___________
____BRR____
diff --git a/pdf/draw_svg_test.go b/pdf/draw_svg_test.go
index 0b50b92..847bcd9 100644
--- a/pdf/draw_svg_test.go
+++ b/pdf/draw_svg_test.go
@@ -4,13 +4,11 @@ import (
"fmt"
"testing"
- "github.com/benoitkugler/webrender/utils/testutils"
tu "github.com/benoitkugler/webrender/utils/testutils"
)
func TestUse(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
RRRRR_____
@@ -43,8 +41,7 @@ func TestUse(t *testing.T) {
// Test how SVG simple patterns are drawn.
func TestPattern(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
BBrrBBrr
@@ -77,8 +74,7 @@ func TestPattern(t *testing.T) {
}
func TestPattern_2(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
BBrrBBrr
@@ -111,8 +107,7 @@ func TestPattern_2(t *testing.T) {
}
func TestPattern_3(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
BBrrBBrr
@@ -145,8 +140,7 @@ func TestPattern_3(t *testing.T) {
}
func TestPattern_4(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
BBrrBBrr
@@ -188,8 +182,7 @@ const svgOpacitySource = `
`
func TestOpacity(t *testing.T) {
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertSameRendering(t, fmt.Sprintf(svgOpacitySource, `
`), fmt.Sprintf(svgOpacitySource, `
+ stroke="lime" fill="blue" fill-opacity="0.5" />
`), 0)
}
@@ -221,7 +213,7 @@ func TestFillOpacity(t *testing.T) {
// @pytest.mark.xfail
// func TestStrokeOpacity(t *testing.T) {
-// capt := testutils.CaptureLogs()
+// capt := tu.CaptureLogs()
// defer capt.AssertNoLogs(t)
// assertSameRendering(t, / ("stroke_opacity_reference", svgOpacitySource % `
@@ -239,7 +231,7 @@ func TestFillOpacity(t *testing.T) {
// @pytest.mark.xfail
// func TestStrokeFillOpacity(t *testing.T) {
-// capt := testutils.CaptureLogs()
+// capt := tu.CaptureLogs()
// defer capt.AssertNoLogs(t)
// assertSameRendering(t, / ("stroke_fill_opacity_reference", svgOpacitySource % `
@@ -258,7 +250,7 @@ func TestFillOpacity(t *testing.T) {
// @pytest.mark.xfail
// func TestPatternGradientStrokeFillOpacity(t *testing.T) {
-// capt := testutils.CaptureLogs()
+// capt := tu.CaptureLogs()
// defer capt.AssertNoLogs(t)
// assertSameRendering(t, / ("pattern_gradient_stroke_fill_opacity_reference", svgOpacitySource % `
@@ -306,8 +298,7 @@ func TestFillOpacity(t *testing.T) {
func TestTranslateOpacity(t *testing.T) {
// Regression test for https://github.com/Kozea/WeasyPrint/issues/1976
- capt := tu.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertSameRendering(t,
fmt.Sprintf(svgOpacitySource, `
@@ -324,8 +315,7 @@ func TestTranslateOpacity(t *testing.T) {
// Test how SVG simple shapes are drawn.
func TestRectStroke(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -350,8 +340,7 @@ func TestRectStroke(t *testing.T) {
}
func TestRectFill(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -375,8 +364,7 @@ func TestRectFill(t *testing.T) {
}
func TestRectStrokeFill(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -401,8 +389,7 @@ func TestRectStrokeFill(t *testing.T) {
}
func TestRectRound(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_zzzzzzz_
@@ -426,8 +413,7 @@ func TestRectRound(t *testing.T) {
}
func TestRectRoundZero(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
RRRRRRRRR
@@ -451,8 +437,7 @@ func TestRectRoundZero(t *testing.T) {
}
func TestLine(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -477,8 +462,7 @@ func TestLine(t *testing.T) {
}
func TestPolyline(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -503,8 +487,7 @@ func TestPolyline(t *testing.T) {
}
func TestPolylineFill(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -529,8 +512,7 @@ func TestPolylineFill(t *testing.T) {
}
func TestPolygon(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -555,8 +537,7 @@ func TestPolygon(t *testing.T) {
}
func TestPolygonFill(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -581,8 +562,7 @@ func TestPolygonFill(t *testing.T) {
}
func TestCircleStroke(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
__________
@@ -608,8 +588,7 @@ func TestCircleStroke(t *testing.T) {
}
func TestCircleFill(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
__________
@@ -635,8 +614,7 @@ func TestCircleFill(t *testing.T) {
}
func TestEllipseStroke(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
__________
@@ -662,8 +640,7 @@ func TestEllipseStroke(t *testing.T) {
}
func TestEllipseFill(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
__________
@@ -689,8 +666,7 @@ func TestEllipseFill(t *testing.T) {
}
func TestRectInG(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
RRRRR____
@@ -716,8 +692,7 @@ func TestRectInG(t *testing.T) {
}
func TestRectXYInG(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -743,8 +718,7 @@ func TestRectXYInG(t *testing.T) {
}
func TestRectStrokeZero(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -769,8 +743,7 @@ func TestRectStrokeZero(t *testing.T) {
}
func TestRectWidthHeightZero(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -797,8 +770,7 @@ func TestRectWidthHeightZero(t *testing.T) {
// attributes.
func TestVisibilityVisible(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -823,8 +795,7 @@ func TestVisibilityVisible(t *testing.T) {
}
func TestVisibilityHidden(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -849,8 +820,7 @@ func TestVisibilityHidden(t *testing.T) {
}
func TestVisibilityInheritHidden(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -876,8 +846,7 @@ func TestVisibilityInheritHidden(t *testing.T) {
}
func TestVisibilityInheritVisible(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -904,8 +873,7 @@ func TestVisibilityInheritVisible(t *testing.T) {
}
func TestDisplayInline(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -930,8 +898,7 @@ func TestDisplayInline(t *testing.T) {
}
func TestDisplayNone(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -956,8 +923,7 @@ func TestDisplayNone(t *testing.T) {
}
func TestDisplayInheritNone(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
@@ -983,8 +949,7 @@ func TestDisplayInheritNone(t *testing.T) {
}
func TestDisplayInheritInline(t *testing.T) {
- capt := testutils.CaptureLogs()
- defer capt.AssertNoLogs(t)
+ defer tu.CaptureLogs().AssertNoLogs(t)
assertPixelsEqual(t, `
_________
diff --git a/pdf/draw_test.go b/pdf/draw_test.go
index db90829..c46629a 100644
--- a/pdf/draw_test.go
+++ b/pdf/draw_test.go
@@ -34,9 +34,9 @@ var colorByName = map[byte]color.RGBA{
'G': {R: 0, G: 255, B: 0, A: 255}, // lime green
'V': {R: 191, G: 0, B: 64, A: 255}, // average of 1*B and 3*R.
'S': {R: 255, G: 63, B: 63, A: 255}, // R above R above #fff
- 'C': {R: 0, G: 255, B: 255}, // cyan
- 'M': {R: 255, G: 0, B: 255}, // magenta
- 'Y': {R: 255, G: 255, B: 0}, // yellow
+ 'C': {R: 0, G: 255, B: 255, A: 255}, // cyan
+ 'M': {R: 255, G: 0, B: 255, A: 255}, // magenta
+ 'Y': {R: 255, G: 255, B: 0, A: 255}, // yellow
'r': {R: 255, G: 0, B: 0, A: 255}, // red
'g': {R: 0, G: 128, B: 0, A: 255}, // half green
'b': {R: 0, G: 0, B: 128, A: 255}, // half blue
@@ -317,7 +317,7 @@ func assertPixelsEqualFromPixels(t *testing.T, expectedPixels [][]color.RGBA, in
for j, v := range exp {
g := gotPixels[i][j]
if v != g {
- t.Fatalf("(file://%s): pixel at (%d, %d): expected %v, got %v", got.Name(), i, j,
+ t.Fatalf("(file://%s): pixel at (row: %d, col: %d): expected %v, got %v", got.Name(), i+1, j+1,
formatColor(v), formatColor(g))
}
}
diff --git a/pdf/draw_text_test.go b/pdf/draw_text_test.go
index 2ad9c37..6c068e5 100644
--- a/pdf/draw_text_test.go
+++ b/pdf/draw_text_test.go
@@ -670,18 +670,18 @@ func TestTextSubsetComposite(t *testing.T) {
// check that subsetting does not remove
// composite glyphs deps
assertPixelsEqual(t, `
- _______
- ____R__
- ____R__
- ___R___
- _______
- _RRRRR_
- _R___R_
- _RRRRR_
- _R_____
- _R___R_
- __RRRR_
- _______
+ _______
+ _______
+ _______
+ ___RR__
+ __RR___
+ _______
+ __RRR__
+ _R___R_
+ _R___R_
+ _RRRRR_
+ _R_____
+ _R_____
`, `
é
`)
}
@@ -797,6 +798,7 @@ func TestTabulationCharacter(t *testing.T) {
}
func TestOtbFont(t *testing.T) {
+ t.Skip() // TODO: https://github.com/benoitkugler/webrender/issues/3
assertPixelsEqual(t, `
____________________
__RR______RR________
diff --git a/pdf/page.go b/pdf/page.go
index 7fdb605..6ad26b8 100644
--- a/pdf/page.go
+++ b/pdf/page.go
@@ -21,13 +21,13 @@ var (
)
func (g *group) SetAlphaMask(mask backend.Canvas) {
- alphaStream := mask.(*group).app
+ alphaStream := mask.(*group).stream
g.drawMask(&alphaStream)
}
func (g *group) SetColorPattern(p backend.Canvas, contentWidth, contentHeight fl, mt matrix.Transform, stroke bool) {
mat := model.Matrix{mt.A, mt.B, mt.C, mt.D, mt.E, mt.F}
- mat = mat.Multiply(g.app.State.Matrix)
+ mat = mat.Multiply(g.stream.State.Matrix)
// initiate the pattern ...
_, _, gridWidth, gridHeight := p.GetBoundingBox()
@@ -38,20 +38,20 @@ func (g *group) SetColorPattern(p backend.Canvas, contentWidth, contentHeight fl
TilingType: 1,
}
- contentXObject := p.(*group).app.ToXFormObject(compressStreams)
+ contentXObject := p.(*group).stream.ToXFormObject(compressStreams)
// wrap the content into a Do command
patternApp := cs.NewGraphicStream(model.Rectangle{Llx: 0, Lly: 0, Urx: contentWidth, Ury: contentHeight})
patternApp.AddXObject(contentXObject)
patternApp.ApplyToTilling(pattern)
// select the color space
- patternName := g.app.AddPattern(pattern)
+ patternName := g.stream.AddPattern(pattern)
if stroke {
- g.app.Ops(cs.OpSetStrokeColorSpace{ColorSpace: model.ColorSpacePattern})
- g.app.Ops(cs.OpSetStrokeColorN{Pattern: patternName})
+ g.stream.Ops(cs.OpSetStrokeColorSpace{ColorSpace: model.ColorSpacePattern})
+ g.stream.Ops(cs.OpSetStrokeColorN{Pattern: patternName})
} else {
- g.app.Ops(cs.OpSetFillColorSpace{ColorSpace: model.ColorSpacePattern})
- g.app.Ops(cs.OpSetFillColorN{Pattern: patternName})
+ g.stream.Ops(cs.OpSetFillColorSpace{ColorSpace: model.ColorSpacePattern})
+ g.stream.Ops(cs.OpSetFillColorN{Pattern: patternName})
}
}
@@ -62,14 +62,22 @@ func (g *group) SetBlendingMode(mode string) {
chunks[i] = strings.Title(s)
}
bm := strings.Join(chunks, "")
- g.app.SetGraphicState(&model.GraphicState{BM: []model.Name{model.ObjName(bm)}})
+ g.stream.SetGraphicState(&model.GraphicState{BM: []model.Name{model.ObjName(bm)}})
}
func (g *group) Clip(evenOdd bool) {
if evenOdd {
- g.app.Ops(cs.OpEOClip{}, cs.OpEndPath{})
+ g.stream.Ops(cs.OpEOClip{}, cs.OpEndPath{})
} else {
- g.app.Ops(cs.OpClip{}, cs.OpEndPath{})
+ g.stream.Ops(cs.OpClip{}, cs.OpEndPath{})
+ }
+}
+
+func (g *group) SetAlpha(alpha fl, stroke bool) {
+ if stroke {
+ g.stream.SetStrokeAlpha(alpha)
+ } else {
+ g.stream.SetFillAlpha(alpha)
}
}
@@ -77,24 +85,24 @@ func (g *group) SetColorRgba(color parser.RGBA, stroke bool) {
alpha := color.A
color.A = 1 // do not take into account the opacity, it is handled by `setXXXAlpha`
if stroke {
- g.app.SetColorStroke(color)
- g.app.SetStrokeAlpha(alpha)
+ g.stream.SetColorStroke(color)
+ g.stream.SetStrokeAlpha(alpha)
} else {
- g.app.SetColorFill(color)
- g.app.SetFillAlpha(alpha)
+ g.stream.SetColorFill(color)
+ g.stream.SetFillAlpha(alpha)
}
}
func (g *group) SetLineWidth(width fl) {
- g.app.Ops(cs.OpSetLineWidth{W: width})
+ g.stream.Ops(cs.OpSetLineWidth{W: width})
}
func (g *group) SetDash(dashes []fl, offset fl) {
- g.app.Ops(cs.OpSetDash{Dash: model.DashPattern{Array: dashes, Phase: offset}})
+ g.stream.Ops(cs.OpSetDash{Dash: model.DashPattern{Array: dashes, Phase: offset}})
}
func (g *group) SetStrokeOptions(opts backend.StrokeOptions) {
- g.app.Ops(
+ g.stream.Ops(
cs.OpSetLineCap{Style: uint8(opts.LineCap)},
cs.OpSetLineJoin{Style: uint8(opts.LineJoin)},
cs.OpSetMiterLimit{Limit: opts.MiterLimit},
@@ -102,7 +110,7 @@ func (g *group) SetStrokeOptions(opts backend.StrokeOptions) {
}
func (g *group) GetTransform() matrix.Transform {
- m := g.app.State.Matrix
+ m := g.stream.State.Matrix
return matrix.New(m[0], m[1], m[2], m[3], m[4], m[5])
}
@@ -111,7 +119,7 @@ func (g *group) GetTransform() matrix.Transform {
// The new transformation of user space takes place
// after any existing transformation.
func (g *group) Transform(mt matrix.Transform) {
- g.app.Transform(model.Matrix{mt.A, mt.B, mt.C, mt.D, mt.E, mt.F})
+ g.stream.Transform(model.Matrix{mt.A, mt.B, mt.C, mt.D, mt.E, mt.F})
}
// group implements backend.Canvas and
@@ -119,15 +127,15 @@ func (g *group) Transform(mt matrix.Transform) {
type group struct {
cache
- app cs.GraphicStream
+ stream cs.GraphicStream
}
func newGroup(cache cache,
left, top, right, bottom fl,
) group {
return group{
- cache: cache,
- app: cs.NewGraphicStream(model.Rectangle{Llx: left, Lly: top, Urx: right, Ury: bottom}), // y grows downward
+ cache: cache,
+ stream: cs.NewGraphicStream(model.Rectangle{Llx: left, Lly: top, Urx: right, Ury: bottom}), // y grows downward
}
}
@@ -157,7 +165,7 @@ func newContextPage(left, top, right, bottom fl,
// update the underlying PageObject with the content stream
func (cp *outputPage) finalize() {
// the MediaBox is the unsclaled BBox. TODO: why ?
- cp.app.ApplyToPageObject(&cp.page, compressStreams)
+ cp.stream.ApplyToPageObject(&cp.page, compressStreams)
if cp.customMediaBox != nil {
cp.page.MediaBox = cp.customMediaBox
}
@@ -225,13 +233,13 @@ func (cp *outputPage) SetBleedBox(left fl, top fl, right fl, bottom fl) {
// Returns the current page rectangle
func (g *group) GetBoundingBox() (left, top, right, bottom fl) {
- bbox := g.app.BoundingBox
+ bbox := g.stream.BoundingBox
return bbox.Llx, bbox.Lly, bbox.Urx, bbox.Ury
}
// Updates the current page rectangle
func (g *group) SetBoundingBox(left, top, right, bottom fl) {
- bbox := &g.app.BoundingBox
+ bbox := &g.stream.BoundingBox
bbox.Llx = left
bbox.Lly = top
bbox.Urx = right
@@ -243,9 +251,9 @@ func (g *group) SetBoundingBox(left, top, right, bottom fl) {
// If an error is encoutered, the stack is still restored
// and the error is returned
func (g *group) OnNewStack(task func()) {
- g.app.SaveState()
+ g.stream.SaveState()
task()
- _ = g.app.RestoreState() // the calls are balanced
+ _ = g.stream.RestoreState() // the calls are balanced
}
// NewGroup creates a new drawing target with the given
@@ -258,27 +266,27 @@ func (g *group) NewGroup(x fl, y fl, width fl, height fl) backend.Canvas {
// DrawGroup add the `gr` content to the current target. It will panic
// if `gr` was not created with `AddGroup`
func (g *group) DrawWithOpacity(opacity fl, gr backend.Canvas) {
- content := gr.(*group).app.ToXFormObject(compressStreams)
+ content := gr.(*group).stream.ToXFormObject(compressStreams)
form := &model.XObjectTransparencyGroup{
XObjectForm: *content,
CS: model.ColorSpaceRGB,
I: true,
}
- g.app.SetFillAlpha(opacity)
- g.app.SetStrokeAlpha(opacity)
- g.app.AddXObject(form)
+ g.stream.SetFillAlpha(opacity)
+ g.stream.SetStrokeAlpha(opacity)
+ g.stream.AddXObject(form)
}
func (g *group) drawMask(app *cs.GraphicStream) {
transparency := app.ToXFormObject(compressStreams)
- g.app.SetAlphaMask(transparency)
+ g.stream.SetAlphaMask(transparency)
}
// Adds a rectangle of the given size to the current path,
// at position “(x, y)“ in user-space coordinates.
// (X,Y) coordinates are the top left corner of the rectangle.
func (g *group) Rectangle(x fl, y fl, width fl, height fl) {
- g.app.Ops(cs.OpRectangle{X: x, Y: y, W: width, H: height})
+ g.stream.Ops(cs.OpRectangle{X: x, Y: y, W: width, H: height})
}
// A drawing operator that fills the current path
@@ -291,27 +299,27 @@ func (g *group) Paint(op backend.PaintOp) {
evenOdd := op&backend.FillEvenOdd != 0
if fill && stroke {
if evenOdd {
- g.app.Ops(cs.OpEOFillStroke{})
+ g.stream.Ops(cs.OpEOFillStroke{})
} else {
- g.app.Ops(cs.OpFillStroke{})
+ g.stream.Ops(cs.OpFillStroke{})
}
} else if fill {
if evenOdd {
- g.app.Ops(cs.OpEOFill{})
+ g.stream.Ops(cs.OpEOFill{})
} else {
- g.app.Ops(cs.OpFill{})
+ g.stream.Ops(cs.OpFill{})
}
} else if stroke {
- g.app.Ops(cs.OpStroke{})
+ g.stream.Ops(cs.OpStroke{})
} else {
- g.app.Ops(cs.OpEndPath{})
+ g.stream.Ops(cs.OpEndPath{})
}
}
// Begin a new sub-path.
// After this call the current point will be “(x, y)“.
func (g *group) MoveTo(x fl, y fl) {
- g.app.Ops(cs.OpMoveTo{X: x, Y: y})
+ g.stream.Ops(cs.OpMoveTo{X: x, Y: y})
}
// Adds a line to the path from the current point
@@ -319,18 +327,18 @@ func (g *group) MoveTo(x fl, y fl) {
// After this call the current point will be “(x, y)“.
// A current point must be defined before using this method.
func (g *group) LineTo(x fl, y fl) {
- g.app.Ops(cs.OpLineTo{X: x, Y: y})
+ g.stream.Ops(cs.OpLineTo{X: x, Y: y})
}
// Add cubic Bézier curve to current path.
// The curve shall extend to “(x3, y3)“ using “(x1, y1)“ and “(x2,
// y2)“ as the Bézier control points.
func (g *group) CubicTo(x1, y1, x2, y2, x3, y3 fl) {
- g.app.Ops(cs.OpCubicTo{X1: x1, Y1: y1, X2: x2, Y2: y2, X3: x3, Y3: y3})
+ g.stream.Ops(cs.OpCubicTo{X1: x1, Y1: y1, X2: x2, Y2: y2, X3: x3, Y3: y3})
}
// ClosePath close the current path, which will apply line join style.
-func (g *group) ClosePath() { g.app.Ops(cs.OpClosePath{}) }
+func (g *group) ClosePath() { g.stream.Ops(cs.OpClosePath{}) }
// DrawRasterImage draws the given image at the current point
func (g *group) DrawRasterImage(img backend.RasterImage, width fl, height fl) {
@@ -347,7 +355,7 @@ func (g *group) DrawRasterImage(img backend.RasterImage, width fl, height fl) {
g.images[img.ID] = obj
}
- g.app.AddXObjectDims(obj, 0, height, width, -height)
+ g.stream.AddXObjectDims(obj, 0, height, width, -height)
}
// DrawGradient draws the given gradient at the current point.
@@ -383,5 +391,5 @@ func (g *group) DrawGradient(layout backend.GradientLayout, width fl, height fl)
g.drawMask(&alphaStream)
}
- g.app.Shading(sh)
+ g.stream.Shading(sh)
}
diff --git a/pdf/pdf.go b/pdf/pdf.go
index d111241..d44a374 100644
--- a/pdf/pdf.go
+++ b/pdf/pdf.go
@@ -18,7 +18,7 @@ var (
)
// may be set to false when debugging
-const compressStreams = true
+const compressStreams = false
type fontContent struct {
content []byte
diff --git a/pdf/pdf_svg_test.go b/pdf/pdf_svg_test.go
index 843c518..5bb7afe 100644
--- a/pdf/pdf_svg_test.go
+++ b/pdf/pdf_svg_test.go
@@ -21,7 +21,7 @@ func drawStandaloneSVG(t *testing.T, input string, outFile string) {
var out model.Document
var page model.PageObject
- dst.app.ApplyToPageObject(&page, false)
+ dst.stream.ApplyToPageObject(&page, false)
out.Catalog.Pages.Kids = append(out.Catalog.Pages.Kids, &page)
if err := out.WriteFile(outFile, nil); err != nil {
diff --git a/pdf/pdf_test.go b/pdf/pdf_test.go
index bd1f75e..c182a06 100644
--- a/pdf/pdf_test.go
+++ b/pdf/pdf_test.go
@@ -200,7 +200,7 @@ func TestBookmarks4(t *testing.T) {
pdf := htmlToBytes(t, `
1
2
diff --git a/pdf/text.go b/pdf/text.go
index a5b9d59..52731fc 100644
--- a/pdf/text.go
+++ b/pdf/text.go
@@ -14,7 +14,6 @@ import (
"github.com/benoitkugler/pdf/fonts/cmaps"
"github.com/benoitkugler/pdf/model"
"github.com/benoitkugler/webrender/backend"
- "github.com/benoitkugler/webrender/matrix"
"github.com/benoitkugler/webrender/text"
drawText "github.com/benoitkugler/webrender/text/draw"
"github.com/go-text/typesetting/opentype/api"
@@ -42,20 +41,17 @@ func (g *group) SetTextPaint(op backend.PaintOp) {
} else {
tr = 3
}
- g.app.Ops(contentstream.OpSetTextRender{Render: tr})
+ g.stream.Ops(contentstream.OpSetTextRender{Render: tr})
}
// DrawText draws the given text using the current fill color.
func (g *group) DrawText(texts []backend.TextDrawing) {
- g.app.BeginText()
- defer g.app.EndText()
+ g.stream.BeginText()
+ defer g.stream.EndText()
for _, text := range texts {
- mat := matrix.New(text.FontSize, 0, 0, -text.FontSize, text.X, text.Y)
- if text.Angle != 0 { // avoid useless multiplication if angle == 0
- mat.RightMultBy(matrix.Rotation(text.Angle))
- }
- g.app.SetTextMatrix(mat.A, mat.B, mat.C, mat.D, mat.E, mat.F)
+ mat := text.Matrix()
+ g.stream.SetTextMatrix(mat.A, mat.B, mat.C, mat.D, mat.E, mat.F)
for _, run := range text.Runs {
pf := g.fonts[run.Font]
@@ -64,7 +60,7 @@ func (g *group) DrawText(texts []backend.TextDrawing) {
useFont := g.cache.fontFiles[run.Font.Origin()].isSupported
if useFont {
- g.app.SetFontAndSize(pdfFonts.BuiltFont{Meta: pf.FontDict}, 1)
+ g.stream.SetFontAndSize(pdfFonts.BuiltFont{Meta: pf.FontDict}, text.FontSize)
}
var out []contentstream.SpacedGlyph
@@ -82,7 +78,7 @@ func (g *group) DrawText(texts []backend.TextDrawing) {
}
if useFont {
- g.app.Ops(contentstream.OpShowSpaceGlyph{Glyphs: out})
+ g.stream.Ops(contentstream.OpShowSpaceGlyph{Glyphs: out})
}
}
}
@@ -184,7 +180,7 @@ func cidWidths(dict map[backend.GID]backend.GlyphExtents) []model.CIDWidth {
return widths
}
-// returns true if a valid 'glyf' or 'cff ' tables is present
+// returns true if a valid 'glyf' , 'cff ' 'or' tables is present
func isSupportedFont(content []byte) bool {
ld, err := loader.NewLoader(bytes.NewReader(content))
if err != nil {
@@ -216,7 +212,10 @@ func isSupportedFont(content []byte) bool {
hasValidGlyf = len(glyf) > 0
}
hasCff := ld.HasTable(loader.MustNewTag("CFF "))
- return hasValidGlyf || hasCff
+
+ hasBitmap := ld.HasTable(loader.MustNewTag("EBDT")) && ld.HasTable(loader.MustNewTag("EBLC"))
+
+ return hasValidGlyf || hasCff || hasBitmap
}
func newFontFile(fontDesc backend.FontDescription, font pdfFont, content []byte) *model.FontFile {
@@ -244,6 +243,167 @@ func newFontFile(fontDesc backend.FontDescription, font pdfFont, content []byte)
return fs
}
+// TODO: see https://github.com/benoitkugler/webrender/issues/3
+// // https://docs.microsoft.com/typography/opentype/spec/ebdt
+// func buildBitmapFontDictionary( pdf, font, widths,
+// compress_pdf, subset) (font_dictionary model.FontType3) {
+// font_dictionary.FontBBox = model.Rectangle{0, 0, 1, 1}
+// font_dictionary.FontMatrix = model.Matrix{1, 0, 0, 1, 0, 0}
+// if subset{
+// chars = tuple(sorted(font.cmap))
+// } else{
+// chars = tuple([]int{256})}
+// first, last = chars[0], chars[-1]
+// font_dictionary.FirstChar = first
+// // font_dictionary.LastChar = last
+// var differences []int
+// // for index, index_widths in zip(widths[::2], widths[1::2]):
+// // differences.append(index)
+// // for i in range(len(index_widths)):
+// // if i + index in chars:
+// // differences.append(f'/{i + index}')
+// // font_dictionary.Encoding = pydyf.Dictionary({ 'Type': '/Encoding', 'Differences': pydyf.Array(differences), })
+// // char_procs = pydyf.Dictionary({})
+// font_glyphs = font.ttfont["EBDT"].strikeData[0]
+// widths := make([]int, (last - first + 1))
+// glyphs_info = map[int]int{}
+// for key, glyph := range font_glyphs {
+// glyph_format = glyph.getFormat()
+// glyph_id = font.ttfont.getGlyphID(key)
+
+// // Get and store glyph metrics
+// if glyph_format == 5{
+// data = glyph.data
+// subtables = font.ttfont["EBLC"].strikes[0].indexSubTables
+// for subtable in subtables:
+// first_index = subtable.firstGlyphIndex
+// last_index = subtable.lastGlyphIndex
+// if first_index <= glyph_id <= last_index:
+// height = subtable.metrics.height
+// advance = width = subtable.metrics.width
+// bearing_x = subtable.metrics.horiBearingX
+// bearing_y = subtable.metrics.horiBearingY
+// break
+// else:
+// LOGGER.warning(f"Unknown bitmap metrics for glyph: {glyph_id}")
+// continue
+// }else{
+// data_start = 5 if glyph_format in (1, 2, 8) else 8
+// data = glyph.data[data_start:]
+// height, width = glyph.data[0:2]
+// bearing_x = int.from_bytes(glyph.data[2:3], "big", signed=True)
+// bearing_y = int.from_bytes(glyph.data[3:4], "big", signed=True)
+// advance = glyph.data[4]}
+// position_y = bearing_y - height
+// if glyph_id in chars{
+// widths[glyph_id - first] = advance}
+// stride = ceil(width / 8)
+// glyph_info = glyphs_info[glyph_id] = {
+// "width": width,
+// "height": height,
+// "x": bearing_x,
+// "y": position_y,
+// "stride": stride,
+// "bitmap": None,
+// "subglyphs": None,
+// }
+
+// // Decode bitmaps
+// if 0 in (width, height) or not data{
+// glyph_info["bitmap"] = b""}
+// elif glyph_format in (1, 6):
+// glyph_info["bitmap"] = data
+// elif glyph_format in (2, 5, 7):
+// padding = (8 - (width % 8)) % 8
+// bits = bin(int(data.hex(), 16))[2:]
+// bits = bits.zfill(8 * len(data))
+// bitmap_bits = ''.join(
+// bits[i * width:(i + 1) * width] + padding * '0'
+// for i in range(height))
+// glyph_info['bitmap'] = int(bitmap_bits, 2).to_bytes(
+// height * stride, 'big')
+// elif glyph_format in (8, 9):
+// subglyphs = glyph_info['subglyphs'] = []
+// i = 0 if glyph_format == 9 else 1
+// number_of_components = int.from_bytes(data[i:i+2], 'big')
+// for j in range(number_of_components):
+// index = (i + 2) + (j * 4)
+// subglyph_id = int.from_bytes(data[index:index+2], 'big')
+// x = int.from_bytes(data[index+2:index+3], 'big', signed=True)
+// y = int.from_bytes(data[index+3:index+4], 'big', signed=True)
+// subglyphs.append({'id': subglyph_id, 'x': x, 'y': y})
+// else: // pragma: no cover
+// LOGGER.warning(f'Unsupported bitmap glyph format: {glyph_format}')
+// glyph_info['bitmap'] = bytes(height * stride)
+// }
+// for glyph_id, glyph_info in glyphs_info.items():
+// // Don’t store glyph not in cmap
+// if glyph_id not in chars:
+// continue
+
+// // Draw glyph
+// stride = glyph_info['stride']
+// width = glyph_info['width']
+// height = glyph_info['height']
+// x = glyph_info['x']
+// y = glyph_info['y']
+// if glyph_info['bitmap'] is None:
+// length = height * stride
+// bitmap_int = int.from_bytes(bytes(length), 'big')
+// for subglyph in glyph_info['subglyphs']:
+// sub_x = subglyph['x']
+// sub_y = subglyph['y']
+// sub_id = subglyph['id']
+// if sub_id not in glyphs_info:
+// LOGGER.warning(f'Unknown subglyph: {sub_id}')
+// continue
+// subglyph = glyphs_info[sub_id]
+// if subglyph['bitmap'] is None:
+// // TODO: support subglyph in subglyph
+// LOGGER.warning(
+// f'Unsupported subglyph in subglyph: {sub_id}')
+// continue
+// for row_y in range(subglyph['height']):
+// row_slice = slice(
+// row_y * subglyph['stride'],
+// (row_y + 1) * subglyph['stride'])
+// row = subglyph['bitmap'][row_slice]
+// row_int = int.from_bytes(row, 'big')
+// shift = stride * 8 * (height - sub_y - row_y - 1)
+// stride_difference = stride - subglyph['stride']
+// if stride_difference > 0:
+// row_int <<= stride_difference * 8
+// elif stride_difference < 0:
+// row_int >>= -stride_difference * 8
+// if sub_x > 0:
+// row_int >>= sub_x
+// elif sub_x < 0:
+// row_int <<= -sub_x
+// row_int %= 1 << stride * 8
+// row_int <<= shift
+// bitmap_int |= row_int
+// bitmap = bitmap_int.to_bytes(length, 'big')
+// else:
+// bitmap = glyph_info['bitmap']
+// bitmap_stream = pydyf.Stream([
+// b'0 0 d0',
+// f'{width} 0 0 {height} {x} {y} cm'.encode(),
+// b'BI',
+// b'/IM true',
+// b'/W', width,
+// b'/H', height,
+// b'/BPC 1',
+// b'/D [1 0]',
+// b'ID', bitmap, b'EI'
+// ], compress=compress_pdf)
+// pdf.add_object(bitmap_stream)
+// char_procs[glyph_id] = bitmap_stream.reference
+
+// pdf.add_object(char_procs)
+// font_dictionary['Widths'] = pydyf.Array(widths)
+// font_dictionary['CharProcs'] = char_procs.reference
+// }
+
// post-process the font used
func (c *Output) writeFonts() {
for bFont, font := range c.cache.fonts {
diff --git a/resources_test/border.svg b/resources_test/border.svg
new file mode 100644
index 0000000..3da4da4
--- /dev/null
+++ b/resources_test/border.svg
@@ -0,0 +1,18 @@
+
diff --git a/resources_test/border2.svg b/resources_test/border2.svg
new file mode 100644
index 0000000..1a6458c
--- /dev/null
+++ b/resources_test/border2.svg
@@ -0,0 +1,191 @@
+
+
diff --git a/resources_test/pattern-transparent.svg b/resources_test/pattern-transparent.svg
new file mode 100644
index 0000000..905bb52
--- /dev/null
+++ b/resources_test/pattern-transparent.svg
@@ -0,0 +1,3 @@
+