mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 13:56:32 +08:00
1 parent
6c14eef1ee
commit
09a49b2c26
10 files changed
+282
-25
No files matched your search
@@ -3,14 +3,14 @@ module github.com/xiaoqidun/ofdgo
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
github.com/emmansun/gmsm v0.44.1
|
||||
github.com/emmansun/gmsm v0.45.0
|
||||
github.com/go-fonts/latin-modern v0.3.3
|
||||
github.com/go-text/typesetting v0.3.5
|
||||
github.com/mububoki/jpeg2000 v1.0.0
|
||||
github.com/tdewolff/canvas v0.0.0-20260923214215-09804640d00c
|
||||
github.com/tdewolff/font v0.0.0-20260913163313-54f98bb59ee6
|
||||
github.com/xiaoqidun/jbig2 v1.1.1
|
||||
github.com/xiaoqidun/pdfgo v0.0.0-20261005044242-0007b05b8143
|
||||
github.com/xiaoqidun/pdfgo v0.0.0-20261005090911-e5eb2af5dff1
|
||||
golang.org/x/crypto v0.57.0
|
||||
golang.org/x/image v0.46.0
|
||||
golang.org/x/text v0.42.0
|
||||
|
||||
@@ -28,8 +28,8 @@ github.com/benoitkugler/textlayout v0.3.2/go.mod h1:o+1hFV+JSHBC9qNLIuwVoLedERU7
|
||||
github.com/benoitkugler/textlayout-testdata v0.1.1/go.mod h1:i/qZl09BbUOtd7Bu/W1CAubRwTWrEXWq6JwMkw8wYxo=
|
||||
github.com/benoitkugler/textprocessing v0.0.6 h1:obkMyj62GEPg3xUVYqROlCN22z1OleuZm6ULqX9Om1g=
|
||||
github.com/benoitkugler/textprocessing v0.0.6/go.mod h1:Io0gN08/PXEzrSOWFa88xHx2Xv3VjvLMY7H76YoI23A=
|
||||
github.com/emmansun/gmsm v0.44.1 h1:zDTkdtLWFG0vCbhPV+k9pte14tix/eK71At9Iai9fP4=
|
||||
github.com/emmansun/gmsm v0.44.1/go.mod h1:p6RIUta0/KboFHrOxr1x8q+pd8RZtdaTO7XNp0RmMQM=
|
||||
github.com/emmansun/gmsm v0.45.0 h1:PU/6ObyR3g05YN3jn1L5GZDowzyAi8Xhkq4svzYNyiA=
|
||||
github.com/emmansun/gmsm v0.45.0/go.mod h1:HgLSvmdePGLo+Fo2PNgdTQU6lqAepSyriSQJRpECY6w=
|
||||
github.com/go-fonts/latin-modern v0.3.3 h1:g2xNgI8yzdNzIVm+qvbMryB6yGPe0pSMss8QT3QwlJ0=
|
||||
github.com/go-fonts/latin-modern v0.3.3/go.mod h1:tHaiWDGze4EPB0Go4cLT5M3QzRY3peya09Z/8KSCrpY=
|
||||
github.com/go-text/typesetting v0.3.5 h1:XZPUooClHY0Vf/rFyUyuPRNEkawARaFzLMQcXLSEyPk=
|
||||
@@ -62,8 +62,8 @@ github.com/tdewolff/test v1.0.12 h1:7F21DqIajswxuche0geHdrUZRCWE4oko4b7bcmkkrxk=
|
||||
github.com/tdewolff/test v1.0.12/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
|
||||
github.com/xiaoqidun/jbig2 v1.1.1 h1:SjliS9ZO0e9HX5oYUfBuXrfFsXhWricrSz+XY4zORDI=
|
||||
github.com/xiaoqidun/jbig2 v1.1.1/go.mod h1:8QonVWtENmh2kc6l+leqeGl7psb79DWlHDkCpdChjfQ=
|
||||
github.com/xiaoqidun/pdfgo v0.0.0-20261005044242-0007b05b8143 h1:OELHUuQnFJHk9qyHQX2gzdMvSQNbnEyD70YeB5Eoldg=
|
||||
github.com/xiaoqidun/pdfgo v0.0.0-20261005044242-0007b05b8143/go.mod h1:4Pf0JO0BEf1uzRY+uZjlMjN/OPn3PYa0YMi6cqPPTLQ=
|
||||
github.com/xiaoqidun/pdfgo v0.0.0-20261005090911-e5eb2af5dff1 h1:AoxEA4tvcE+8tP3i4fE2f3It3DzbNBmvEVVMTp59sDM=
|
||||
github.com/xiaoqidun/pdfgo v0.0.0-20261005090911-e5eb2af5dff1/go.mod h1:4Pf0JO0BEf1uzRY+uZjlMjN/OPn3PYa0YMi6cqPPTLQ=
|
||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||
github.com/yuin/goldmark v1.8.5 h1:r6N5afV5qj/5S4UTch8agZHJ8UxNCMwX7WjkkJam2NA=
|
||||
|
||||
+16
-10
@@ -56,6 +56,7 @@ type pdfCompositor struct {
|
||||
gradients map[pdfGradientKey][]pdfShadingPixel
|
||||
transfers []*pdfgo.TransferFunction
|
||||
transferBlocked bool
|
||||
shadingSource bool
|
||||
}
|
||||
|
||||
// pdfCompositeKey 区分图元的填充与描边几何
|
||||
@@ -83,16 +84,18 @@ type pdfCompositeColorSampler struct {
|
||||
|
||||
// pdfCompositeCache 在单页内复用几何、图像分量及蒙版内容
|
||||
type pdfCompositeCache struct {
|
||||
geometry map[pdfCompositeKey]pdfCompositeGeometry
|
||||
images map[*pdfgo.Image]*pdfgo.ImageComponents
|
||||
imageMatrix map[*pdfgo.ImageMark]pdfgo.Matrix
|
||||
masks map[*pdfgo.SoftMask][]pdfCompositeNode
|
||||
meshes map[*pdfgo.MeshGradient][]pdfMeshTriangle
|
||||
patterns map[pdfgo.Paint]*pdfCompositePattern
|
||||
shadings map[pdfGradientKey]pdfCompositeGeometry
|
||||
transfers map[pdfTransferKey]*pdfgo.TransferFunction
|
||||
textDisjoint map[*pdfgo.GroupMark]bool
|
||||
groups map[*pdfgo.GroupMark]Box
|
||||
geometry map[pdfCompositeKey]pdfCompositeGeometry
|
||||
images map[*pdfgo.Image]*pdfgo.ImageComponents
|
||||
imageMatrix map[*pdfgo.ImageMark]pdfgo.Matrix
|
||||
masks map[*pdfgo.SoftMask][]pdfCompositeNode
|
||||
meshes map[*pdfgo.MeshGradient][]pdfMeshTriangle
|
||||
patterns map[pdfgo.Paint]*pdfCompositePattern
|
||||
shadingPatterns map[*pdfgo.ShadingPattern][]pdfCompositeNode
|
||||
shadingSources map[pdfShadingSourceKey][]pdfCompositeNode
|
||||
shadings map[pdfGradientKey]pdfCompositeGeometry
|
||||
transfers map[pdfTransferKey]*pdfgo.TransferFunction
|
||||
textDisjoint map[*pdfgo.GroupMark]bool
|
||||
groups map[*pdfgo.GroupMark]Box
|
||||
}
|
||||
|
||||
// compositingCache 按需创建单页合成缓存,页面切换时由导入器释放
|
||||
@@ -531,6 +534,9 @@ func (n pdfCompositeNode) direct() bool {
|
||||
return true
|
||||
}
|
||||
s, fill, stroke := n.style()
|
||||
if (n.image == nil || n.image.Image.ImageMask) && (fill && s.Fill.Shading != nil || stroke && s.Stroke.Shading != nil) {
|
||||
return false
|
||||
}
|
||||
if fill && stroke && (s.Fill.Alpha != 1 || s.Stroke.Alpha != 1 || s.SoftMask != nil) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -138,13 +138,24 @@ func (c *pdfCompositor) drawPaint(node pdfCompositeNode, outline bool, paint pdf
|
||||
}
|
||||
}
|
||||
step := 25.4 / c.importer.rasterDPI
|
||||
uniform := node.image == nil && paint.Axial == nil && paint.Radial == nil && paint.Function == nil && paint.Tiling == nil && paint.Mesh == nil
|
||||
uniform := node.image == nil && paint.Axial == nil && paint.Radial == nil && paint.Function == nil && paint.Tiling == nil && paint.Mesh == nil && paint.Shading == nil
|
||||
compatible := overprint && !processOverprint && style.OverprintMode == 1 && uniform && paint.SourceSpace == "DeviceCMYK" && space.Model == "DeviceCMYK" && !space.Calibrated()
|
||||
var marked *[4]bool
|
||||
if processOverprint {
|
||||
marked = &processMask
|
||||
}
|
||||
var pattern []pdfCompositePixel
|
||||
if paint.Shading != nil && (node.image == nil || node.image.Image.ImageMask) {
|
||||
backdrop := pixels
|
||||
if initial != nil {
|
||||
backdrop = initial
|
||||
}
|
||||
pattern, err = c.shadingPattern(paint.Shading, node, outline, backdrop, space)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer c.releasePixels(pattern)
|
||||
}
|
||||
if paint.Tiling != nil && (node.image == nil || node.image.Image.ImageMask) {
|
||||
backdrop := pixels
|
||||
if initial != nil {
|
||||
@@ -199,11 +210,15 @@ func (c *pdfCompositor) drawPaint(node pdfCompositeNode, outline bool, paint pdf
|
||||
if pattern != nil {
|
||||
sample := pattern[index]
|
||||
values = sample.values
|
||||
shape *= sample.shape
|
||||
if paint.Shading != nil {
|
||||
shape = sample.shape
|
||||
} else {
|
||||
shape *= sample.shape
|
||||
}
|
||||
if sample.shape != 0 {
|
||||
opacity *= sample.alpha / sample.shape
|
||||
}
|
||||
if node.image != nil {
|
||||
if node.image != nil && paint.Shading == nil {
|
||||
point := c.inverse.Apply(pdfgo.Point{X: c.box.X + (float64(x)+.5)*step, Y: c.box.Y + (float64(y)+.5)*step})
|
||||
var alpha float64
|
||||
_, alpha, err = c.imageColor(node.image, point, space)
|
||||
@@ -226,7 +241,11 @@ func (c *pdfCompositor) drawPaint(node pdfCompositeNode, outline bool, paint pdf
|
||||
if imageShape {
|
||||
selectionShape = alpha
|
||||
}
|
||||
opacity *= alpha
|
||||
if c.shadingSource {
|
||||
shape *= alpha
|
||||
} else {
|
||||
opacity *= alpha
|
||||
}
|
||||
}
|
||||
} else if uniform {
|
||||
if !uniformReady {
|
||||
@@ -242,7 +261,11 @@ func (c *pdfCompositor) drawPaint(node pdfCompositeNode, outline bool, paint pdf
|
||||
if imageShape {
|
||||
selectionShape = alpha
|
||||
}
|
||||
opacity *= alpha
|
||||
if c.shadingSource {
|
||||
shape *= alpha
|
||||
} else {
|
||||
opacity *= alpha
|
||||
}
|
||||
} else {
|
||||
var visible bool
|
||||
if sampler != nil {
|
||||
@@ -651,7 +674,7 @@ func (c *pdfCompositor) imageColor(mark *pdfgo.ImageMark, point pdfgo.Point, spa
|
||||
}
|
||||
}
|
||||
if mark.Image.ImageMask {
|
||||
if mark.Style.Fill.Tiling != nil {
|
||||
if mark.Style.Fill.Tiling != nil || mark.Style.Fill.Shading != nil {
|
||||
return [4]float64{}, alpha * (1 - values[0]), nil
|
||||
}
|
||||
color, visible, err := pdfCompositeColor(mark.Style.Fill, mark.Matrix.Apply(point), space, mark.Style.RenderingIntent, mark.Style.ColorConversion)
|
||||
@@ -706,6 +729,9 @@ func pdfImageProcessColorants(image *pdfgo.Image) ([4]bool, bool, error) {
|
||||
// 入参: paint 画刷, point 页面坐标, space 混合空间, intent 渲染意图, conversion 设备转换函数
|
||||
// 返回: [4]float64 混合分量, bool 是否着色, error 颜色错误
|
||||
func pdfCompositeColor(paint pdfgo.Paint, point pdfgo.Point, space *pdfgo.ColorSpace, intent pdfgo.Name, conversion pdfgo.ColorConversion) ([4]float64, bool, error) {
|
||||
if paint.Shading != nil {
|
||||
return [4]float64{}, false, &pdfgo.UnsupportedError{Feature: "local shading pattern compositing"}
|
||||
}
|
||||
if paint.Tiling != nil {
|
||||
return [4]float64{}, false, &pdfgo.UnsupportedError{Feature: "local tiling pattern compositing"}
|
||||
}
|
||||
|
||||
@@ -294,6 +294,15 @@ func (p *pdfImporter) processOverprint(nodes []pdfCompositeNode) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
for i, paint := range []pdfgo.Paint{style.Fill, style.Stroke} {
|
||||
if paint.Shading != nil && (i == 0 && fill || i == 1 && stroke) {
|
||||
nodes, err := p.compositeShadingPattern(paint.Shading)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if found, err := p.processOverprint(nodes); err != nil || found {
|
||||
return found, err
|
||||
}
|
||||
}
|
||||
if i == 0 && !fill || i == 1 && !stroke || paint.Tiling == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
// Copyright 2025-2026 肖其顿 (XIAO QI DUN)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ofdgo
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/xiaoqidun/pdfgo"
|
||||
)
|
||||
|
||||
// pdfShadingSourceKey 区分图案的使用几何及填充或描边
|
||||
type pdfShadingSourceKey struct {
|
||||
pattern *pdfgo.ShadingPattern
|
||||
geometry pdfCompositeKey
|
||||
}
|
||||
|
||||
// compositeShadingPattern 在页面内复用图案内部图元,不缓存依赖背景的像素
|
||||
// 入参: pattern 只读着色图案
|
||||
// 返回: []pdfCompositeNode 隐式挖空组, error 遍历或资源错误
|
||||
func (p *pdfImporter) compositeShadingPattern(pattern *pdfgo.ShadingPattern) ([]pdfCompositeNode, error) {
|
||||
cache := p.compositingCache()
|
||||
if nodes, found := cache.shadingPatterns[pattern]; found {
|
||||
return nodes, nil
|
||||
}
|
||||
inverse, ok := p.matrix.Inverse()
|
||||
if !ok {
|
||||
return nil, &pdfgo.UnsupportedError{Feature: "shading pattern page transform"}
|
||||
}
|
||||
box := pdfBounds([]pdfgo.Point{
|
||||
inverse.Apply(pdfgo.Point{}), inverse.Apply(pdfgo.Point{X: p.pageWidth}),
|
||||
inverse.Apply(pdfgo.Point{X: p.pageWidth, Y: p.pageHeight}), inverse.Apply(pdfgo.Point{Y: p.pageHeight}),
|
||||
})
|
||||
nodes, err := p.collectCompositeNodes(func(visitor pdfgo.Visitor) error {
|
||||
return pattern.Walk(p.ctx, pdfgo.Rectangle{XMin: box.X, YMin: box.Y, XMax: box.X + box.W, YMax: box.Y + box.H}, visitor)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cache.shadingPatterns == nil {
|
||||
cache.shadingPatterns = make(map[*pdfgo.ShadingPattern][]pdfCompositeNode)
|
||||
}
|
||||
cache.shadingPatterns[pattern] = nodes
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
// shadingPattern 统一对象和图案的几何覆盖,按相交面积合成背景及内部着色
|
||||
// 入参: pattern 着色图案, node 使用图元, outline 是否描边, backdrop 初始背景, space 父级混合空间
|
||||
// 返回: []pdfCompositePixel 源颜色、形状及不透明度, error 状态或合成错误
|
||||
func (c *pdfCompositor) shadingPattern(pattern *pdfgo.ShadingPattern, node pdfCompositeNode, outline bool, backdrop []pdfCompositePixel, space *pdfgo.ColorSpace) ([]pdfCompositePixel, error) {
|
||||
nodes, err := c.importer.shadingSources(pattern, node, outline)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
local := *c
|
||||
local.transfers, local.shadingSource = nil, true
|
||||
result, err := local.shadingSourcePixels(nodes[len(nodes)-1], backdrop, space)
|
||||
if err != nil || len(nodes) == 1 {
|
||||
return result, err
|
||||
}
|
||||
background, err := local.shadingSourcePixels(nodes[0], backdrop, space)
|
||||
if err != nil {
|
||||
c.releasePixels(result)
|
||||
return nil, err
|
||||
}
|
||||
defer c.releasePixels(background)
|
||||
coverage, err := c.coverage(nodes[0], outline)
|
||||
if err != nil {
|
||||
c.releasePixels(result)
|
||||
return nil, err
|
||||
}
|
||||
step := 25.4 / c.importer.rasterDPI
|
||||
for i := range result {
|
||||
if i%pdfCompositeTileSize == 0 {
|
||||
if err := c.importer.ctx.Err(); err != nil {
|
||||
c.releasePixels(result)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
shape := 0.0
|
||||
if coverage != nil {
|
||||
_, _, _, a := coverage.At(i%c.width, i/c.width).RGBA()
|
||||
shape = float64(a) / 65535
|
||||
}
|
||||
if nodes[0].image != nil && shape != 0 {
|
||||
point := c.inverse.Apply(pdfgo.Point{X: c.box.X + (float64(i%c.width)+.5)*step, Y: c.box.Y + (float64(i/c.width)+.5)*step})
|
||||
_, alpha, err := c.imageColor(nodes[0].image, point, space)
|
||||
if err != nil {
|
||||
c.releasePixels(result)
|
||||
return nil, err
|
||||
}
|
||||
shape *= alpha
|
||||
}
|
||||
remaining := 1.0
|
||||
if shape != 0 {
|
||||
remaining -= math.Min(1, result[i].shape/shape)
|
||||
}
|
||||
alpha := result[i].alpha + background[i].alpha*remaining
|
||||
if alpha != 0 {
|
||||
for j := 0; j < space.Components(); j++ {
|
||||
result[i].values[j] = (result[i].values[j]*result[i].alpha + background[i].values[j]*background[i].alpha*remaining) / alpha
|
||||
}
|
||||
}
|
||||
result[i].alpha, result[i].effect = alpha, alpha
|
||||
result[i].shape += background[i].shape * remaining
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// shadingSources 将内部状态绑定到使用图元,几何和裁剪仅计算一次
|
||||
// 入参: pattern 只读着色图案, node 使用图元, outline 是否描边
|
||||
// 返回: []pdfCompositeNode 背景及着色图元, error 图案遍历错误
|
||||
func (p *pdfImporter) shadingSources(pattern *pdfgo.ShadingPattern, node pdfCompositeNode, outline bool) ([]pdfCompositeNode, error) {
|
||||
cache := p.compositingCache()
|
||||
key := pdfShadingSourceKey{pattern, pdfCompositeKey{path: node.path, text: node.text, image: node.image, stroke: outline}}
|
||||
if sources, ok := cache.shadingSources[key]; ok {
|
||||
return sources, nil
|
||||
}
|
||||
nodes, err := p.compositeShadingPattern(pattern)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
outer, _, _ := node.style()
|
||||
sources := make([]pdfCompositeNode, 0, len(nodes[0].children))
|
||||
for _, child := range nodes[0].children {
|
||||
style := child.path.Style
|
||||
style.LineWidth, style.Cap, style.Join, style.MiterLimit = outer.LineWidth, outer.Cap, outer.Join, outer.MiterLimit
|
||||
style.Dash, style.DashPhase, style.StrokeAdjust = outer.Dash, outer.DashPhase, outer.StrokeAdjust
|
||||
style.Clips = append(append([]pdfgo.Path(nil), outer.Clips...), style.Clips...)
|
||||
style.Stroke, style.StrokeOverprint = style.Fill, style.FillOverprint
|
||||
source := node
|
||||
if node.path != nil {
|
||||
mark := *node.path
|
||||
mark.Style, mark.Fill, mark.Stroke = style, !outline, outline
|
||||
source.path = &mark
|
||||
} else if node.text != nil {
|
||||
mark := *node.text
|
||||
mark.Style, mark.Mode = style, 0
|
||||
if outline {
|
||||
mark.Mode = 1
|
||||
}
|
||||
source.text = &mark
|
||||
} else {
|
||||
mark := *node.image
|
||||
mark.Style = style
|
||||
source.image = &mark
|
||||
}
|
||||
sources = append(sources, source)
|
||||
}
|
||||
if cache.shadingSources == nil {
|
||||
cache.shadingSources = make(map[pdfShadingSourceKey][]pdfCompositeNode)
|
||||
}
|
||||
cache.shadingSources[key] = sources
|
||||
return sources, nil
|
||||
}
|
||||
|
||||
// shadingSourcePixels 求值单个内部图元并移除初始背景贡献
|
||||
// 入参: node 内部图元, backdrop 初始背景, space 混合空间
|
||||
// 返回: []pdfCompositePixel 源颜色和覆盖, error 合成或取消错误
|
||||
func (c *pdfCompositor) shadingSourcePixels(node pdfCompositeNode, backdrop []pdfCompositePixel, space *pdfgo.ColorSpace) ([]pdfCompositePixel, error) {
|
||||
result := c.acquirePixels(len(backdrop))
|
||||
complete := false
|
||||
defer func() {
|
||||
if !complete {
|
||||
c.releasePixels(result)
|
||||
}
|
||||
}()
|
||||
for i, pixel := range backdrop {
|
||||
result[i] = pdfCompositePixel{values: pixel.values, alpha: pixel.alpha}
|
||||
}
|
||||
if err := c.drawMark(node, result, space); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range result {
|
||||
if i%pdfCompositeTileSize == 0 {
|
||||
if err := c.importer.ctx.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
pixel := &result[i]
|
||||
if pixel.effect != 0 {
|
||||
for j := 0; j < space.Components(); j++ {
|
||||
pixel.values[j] = math.Max(0, math.Min(1, (pixel.values[j]*pixel.alpha-backdrop[i].values[j]*backdrop[i].alpha*(1-pixel.effect))/pixel.effect))
|
||||
}
|
||||
}
|
||||
pixel.alpha = pixel.effect
|
||||
}
|
||||
complete = true
|
||||
return result, nil
|
||||
}
|
||||
+2
-2
@@ -168,7 +168,7 @@ func (p *pdfImporter) groupPaths(mark pdfgo.GroupMark, walk func(pdfgo.Visitor)
|
||||
if stroke {
|
||||
color, overprint = path.Style.Stroke, path.Style.StrokeOverprint
|
||||
}
|
||||
if color.Tiling != nil || color.Axial != nil || color.Radial != nil || color.Function != nil || color.Mesh != nil || overprint && pdfOverprintNeedsSeparation(color) {
|
||||
if color.Tiling != nil || color.Shading != nil || color.Axial != nil || color.Radial != nil || color.Function != nil || color.Mesh != nil || overprint && pdfOverprintNeedsSeparation(color) {
|
||||
return fmt.Errorf("%w: patterned or overprinted group content", errPDFGroupRaster)
|
||||
}
|
||||
if color.Alpha == 0 {
|
||||
@@ -615,7 +615,7 @@ func (p *pdfImporter) maskClip(mask *pdfgo.SoftMask) (pdfgo.Path, error) {
|
||||
return err
|
||||
}
|
||||
paint := mark.Style.Fill
|
||||
if !mark.Fill || mark.Stroke || paint.Alpha != 1 || paint.CMYK != nil || paint.Axial != nil || paint.Radial != nil || paint.Function != nil || paint.Mesh != nil || paint.Tiling != nil || paint.Space != nil && paint.Space.Calibrated() || paint.RGB[0] != paint.RGB[1] || paint.RGB[1] != paint.RGB[2] || mark.Style.SoftMask != nil || !pdfNormalBlend(mark.Style.BlendMode) {
|
||||
if !mark.Fill || mark.Stroke || paint.Alpha != 1 || paint.CMYK != nil || paint.Axial != nil || paint.Radial != nil || paint.Function != nil || paint.Mesh != nil || paint.Tiling != nil || paint.Shading != nil || paint.Space != nil && paint.Space.Calibrated() || paint.RGB[0] != paint.RGB[1] || paint.RGB[1] != paint.RGB[2] || mark.Style.SoftMask != nil || !pdfNormalBlend(mark.Style.BlendMode) {
|
||||
return &pdfgo.UnsupportedError{Feature: "nonbinary mask graphic"}
|
||||
}
|
||||
visible, err := opacity(paint.RGB[0])
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ func (p *pdfImporter) image(mark pdfgo.ImageMark) error {
|
||||
if err := p.flushPath(); err != nil {
|
||||
return err
|
||||
}
|
||||
if mark.Image.ImageMask && (mark.Style.Fill.Axial != nil || mark.Style.Fill.Radial != nil || mark.Style.Fill.Function != nil || mark.Style.Fill.Mesh != nil) {
|
||||
if mark.Image.ImageMask && (mark.Style.Fill.Axial != nil || mark.Style.Fill.Radial != nil || mark.Style.Fill.Function != nil || mark.Style.Fill.Mesh != nil || mark.Style.Fill.Shading != nil) {
|
||||
if p.warning != nil {
|
||||
return p.compositeRegion(nil, pdfCompositeNode{image: &mark}, &pdfgo.ColorSpace{Model: "DeviceRGB"}, false)
|
||||
}
|
||||
|
||||
@@ -81,6 +81,9 @@ func pdfGradientStopsError(stops []pdfgo.GradientStop, space *pdfgo.ColorSpace)
|
||||
// 入参: paint 画刷
|
||||
// 返回: error 不可等价表达的渐变
|
||||
func pdfGradientError(paint pdfgo.Paint) error {
|
||||
if paint.Shading != nil {
|
||||
return &pdfgo.UnsupportedError{Feature: "shading pattern state compositing"}
|
||||
}
|
||||
if paint.Function != nil {
|
||||
return &pdfgo.UnsupportedError{Feature: "function shading conversion"}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,12 @@ func (c *pdfCompositor) selectTransfer(node pdfCompositeNode, outline bool) (*pd
|
||||
if style.Transfer == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if pattern := paint.Shading; pattern != nil && (node.image == nil || node.image.Image.ImageMask) {
|
||||
inner := pattern.Style
|
||||
if inner.Fill.Alpha != 1 || inner.SoftMask != nil || !pdfNormalBlend(inner.BlendMode) {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
if node.image != nil {
|
||||
soft, err := node.image.Image.HasSoftMask()
|
||||
if err != nil || soft {
|
||||
@@ -148,6 +154,12 @@ func (p *pdfImporter) transferOpaque(node pdfCompositeNode) (bool, error) {
|
||||
}
|
||||
}
|
||||
for i, paint := range [2]pdfgo.Paint{style.Fill, style.Stroke} {
|
||||
if pattern := paint.Shading; pattern != nil && (i == 0 && fill || i == 1 && stroke) {
|
||||
inner := pattern.Style
|
||||
if inner.Fill.Alpha != 1 || inner.SoftMask != nil || !pdfNormalBlend(inner.BlendMode) {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
if i == 0 && !fill || i == 1 && !stroke || paint.Tiling == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user