mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-30 01:27:26 +08:00
This commit is contained in:
1 parent
6c9b3f6019
commit
777d0c7c89
8 files changed
+228
-153
No files matched your search
@@ -19,6 +19,30 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// UnmarshalXML 解析填充颜色并区分未支持的复杂颜色
|
||||||
|
// 入参: d XML解码器, start 起始节点
|
||||||
|
// 返回: error 错误信息
|
||||||
|
func (c *FillColor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
type plain FillColor
|
||||||
|
var value struct {
|
||||||
|
plain
|
||||||
|
Other *struct{} `xml:",any"`
|
||||||
|
}
|
||||||
|
if err := d.DecodeElement(&value, &start); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*c = FillColor(value.plain)
|
||||||
|
c.unsupported = value.Other != nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML 解析勾边颜色并区分未支持的复杂颜色
|
||||||
|
// 入参: d XML解码器, start 起始节点
|
||||||
|
// 返回: error 错误信息
|
||||||
|
func (c *StrokeColor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
return (*FillColor)(c).UnmarshalXML(d, start)
|
||||||
|
}
|
||||||
|
|
||||||
// graphicObjectTarget 图形对象集合
|
// graphicObjectTarget 图形对象集合
|
||||||
type graphicObjectTarget struct {
|
type graphicObjectTarget struct {
|
||||||
objects *[]GraphicObject
|
objects *[]GraphicObject
|
||||||
|
|||||||
+8
-6
@@ -22,6 +22,7 @@ type PageContent struct {
|
|||||||
ID string `xml:"-"`
|
ID string `xml:"-"`
|
||||||
Area PageArea `xml:"Area"`
|
Area PageArea `xml:"Area"`
|
||||||
Template []Template `xml:"Template"`
|
Template []Template `xml:"Template"`
|
||||||
|
PageRes string `xml:"PageRes"`
|
||||||
Content Content `xml:"Content"`
|
Content Content `xml:"Content"`
|
||||||
Actions []Action `xml:"Actions>Action"`
|
Actions []Action `xml:"Actions>Action"`
|
||||||
}
|
}
|
||||||
@@ -106,10 +107,13 @@ type TextObject struct {
|
|||||||
// FillColor 填充颜色
|
// FillColor 填充颜色
|
||||||
type FillColor struct {
|
type FillColor struct {
|
||||||
Value string `xml:"Value,attr"`
|
Value string `xml:"Value,attr"`
|
||||||
|
Index *int `xml:"Index,attr"`
|
||||||
|
ColorSpace string `xml:"ColorSpace,attr"`
|
||||||
Alpha *int `xml:"Alpha,attr"`
|
Alpha *int `xml:"Alpha,attr"`
|
||||||
Pattern *Pattern `xml:"Pattern"`
|
Pattern *Pattern `xml:"Pattern"`
|
||||||
AxialShd *AxialShd `xml:"AxialShd"`
|
AxialShd *AxialShd `xml:"AxialShd"`
|
||||||
RadialShd *RadialShd `xml:"RadialShd"`
|
RadialShd *RadialShd `xml:"RadialShd"`
|
||||||
|
unsupported bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pattern 图案填充
|
// Pattern 图案填充
|
||||||
@@ -119,6 +123,7 @@ type Pattern struct {
|
|||||||
XStep float64 `xml:"XStep,attr"`
|
XStep float64 `xml:"XStep,attr"`
|
||||||
YStep float64 `xml:"YStep,attr"`
|
YStep float64 `xml:"YStep,attr"`
|
||||||
ReflectMethod string `xml:"ReflectMethod,attr"`
|
ReflectMethod string `xml:"ReflectMethod,attr"`
|
||||||
|
RelativeTo string `xml:"RelativeTo,attr"`
|
||||||
CTM string `xml:"CTM,attr"`
|
CTM string `xml:"CTM,attr"`
|
||||||
CellContent PatternContent `xml:"CellContent"`
|
CellContent PatternContent `xml:"CellContent"`
|
||||||
}
|
}
|
||||||
@@ -175,12 +180,7 @@ type PathObject struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// StrokeColor 勾边颜色
|
// StrokeColor 勾边颜色
|
||||||
type StrokeColor struct {
|
type StrokeColor FillColor
|
||||||
Value string `xml:"Value,attr"`
|
|
||||||
Alpha *int `xml:"Alpha,attr"`
|
|
||||||
AxialShd *AxialShd `xml:"AxialShd"`
|
|
||||||
RadialShd *RadialShd `xml:"RadialShd"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// AxialShd 轴向渐变
|
// AxialShd 轴向渐变
|
||||||
type AxialShd struct {
|
type AxialShd struct {
|
||||||
@@ -216,6 +216,8 @@ type ShdSegment struct {
|
|||||||
// ShdColor 渐变颜色
|
// ShdColor 渐变颜色
|
||||||
type ShdColor struct {
|
type ShdColor struct {
|
||||||
Value string `xml:"Value,attr"`
|
Value string `xml:"Value,attr"`
|
||||||
|
Index *int `xml:"Index,attr"`
|
||||||
|
ColorSpace string `xml:"ColorSpace,attr"`
|
||||||
Alpha *int `xml:"Alpha,attr"`
|
Alpha *int `xml:"Alpha,attr"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+87
-100
@@ -24,40 +24,66 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// parseColorWithAlpha 解析带透明度的颜色
|
// parseColorWithAlpha 解析带透明度的颜色
|
||||||
// 入参: val 颜色值, alpha 透明度
|
// 入参: value 颜色值, index 调色板索引, space 颜色空间标识, alpha 透明度
|
||||||
// 返回: color.Color 颜色对象
|
// 返回: color.Color 颜色对象
|
||||||
func parseColorWithAlpha(val string, alpha *int) color.Color {
|
func (r *Renderer) parseColorWithAlpha(value string, index *int, space string, alpha *int) color.Color {
|
||||||
parts := strings.Fields(val)
|
if space == "" && r.Reader.doc != nil {
|
||||||
if len(parts) >= 3 {
|
space = strconv.Itoa(r.Reader.doc.CommonData.DefaultCS)
|
||||||
r := parseColorComponent(parts[0])
|
}
|
||||||
g := parseColorComponent(parts[1])
|
cs := r.Reader.colorSpaceCache[space]
|
||||||
b := parseColorComponent(parts[2])
|
kind, bits, count := "RGB", 8, 3
|
||||||
|
if cs != nil {
|
||||||
|
kind = cs.Type
|
||||||
|
switch cs.BitsPerComponent {
|
||||||
|
case 1, 2, 4, 8, 16:
|
||||||
|
bits = cs.BitsPerComponent
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(value) == "" && index != nil && 0 <= *index && *index < len(cs.Palette) {
|
||||||
|
value = cs.Palette[*index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch kind {
|
||||||
|
case "GRAY":
|
||||||
|
count = 1
|
||||||
|
case "CMYK":
|
||||||
|
count = 4
|
||||||
|
}
|
||||||
|
parts := strings.Fields(value)
|
||||||
|
var components [4]uint8
|
||||||
|
limit := 1<<bits - 1
|
||||||
|
if len(parts) >= count {
|
||||||
|
for i, part := range parts[:count] {
|
||||||
|
v, err := parseColorComponent(part)
|
||||||
|
if err != nil || v < 0 || limit < v {
|
||||||
|
components = [4]uint8{}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
components[i] = uint8((v*255 + limit/2) / limit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
red, green, blue := components[0], components[1], components[2]
|
||||||
|
switch kind {
|
||||||
|
case "GRAY":
|
||||||
|
green, blue = red, red
|
||||||
|
case "CMYK":
|
||||||
|
red, green, blue = color.CMYKToRGB(components[0], components[1], components[2], components[3])
|
||||||
|
}
|
||||||
a := 255
|
a := 255
|
||||||
if alpha != nil {
|
if alpha != nil {
|
||||||
a = *alpha
|
a = clampColor(*alpha)
|
||||||
}
|
}
|
||||||
a = clampColor(a)
|
return color.RGBA{R: uint8(int(red) * a / 255), G: uint8(int(green) * a / 255), B: uint8(int(blue) * a / 255), A: uint8(a)}
|
||||||
return color.RGBA{
|
|
||||||
R: uint8(clampColor(r) * a / 255),
|
|
||||||
G: uint8(clampColor(g) * a / 255),
|
|
||||||
B: uint8(clampColor(b) * a / 255),
|
|
||||||
A: uint8(a),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return color.Black
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseColorComponent 解析颜色分量
|
// parseColorComponent 解析颜色分量
|
||||||
// 入参: s 颜色分量
|
// 入参: s 颜色分量
|
||||||
// 返回: int 颜色分量值
|
// 返回: int 颜色分量值, error 错误信息
|
||||||
func parseColorComponent(s string) int {
|
func parseColorComponent(s string) (int, error) {
|
||||||
s = strings.TrimSpace(s)
|
|
||||||
if strings.HasPrefix(s, "#") {
|
if strings.HasPrefix(s, "#") {
|
||||||
v, _ := strconv.ParseInt(strings.TrimPrefix(s, "#"), 16, 0)
|
v, err := strconv.ParseInt(s[1:], 16, 0)
|
||||||
return int(v)
|
return int(v), err
|
||||||
}
|
}
|
||||||
v, _ := strconv.Atoi(s)
|
return strconv.Atoi(s)
|
||||||
return v
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// clampColor 限制颜色分量范围
|
// clampColor 限制颜色分量范围
|
||||||
@@ -135,7 +161,7 @@ func colorWithAlpha(c color.Color, alpha *int) color.Color {
|
|||||||
// parseFillColor 解析填充颜色
|
// parseFillColor 解析填充颜色
|
||||||
// 入参: fillColor 填充颜色节点
|
// 入参: fillColor 填充颜色节点
|
||||||
// 返回: color.Color 颜色对象
|
// 返回: color.Color 颜色对象
|
||||||
func parseFillColor(fillColor *FillColor) color.Color {
|
func (r *Renderer) parseFillColor(fillColor *FillColor) color.Color {
|
||||||
if fillColor == nil {
|
if fillColor == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -143,117 +169,81 @@ func parseFillColor(fillColor *FillColor) color.Color {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if fillColor.AxialShd != nil {
|
if fillColor.AxialShd != nil {
|
||||||
return parseShdColor(fillColor.AxialShd.Segment, fillColor.Alpha)
|
return r.parseShdColor(fillColor.AxialShd.Segment, fillColor.Alpha)
|
||||||
}
|
}
|
||||||
if fillColor.RadialShd != nil {
|
if fillColor.RadialShd != nil {
|
||||||
return parseShdColor(fillColor.RadialShd.Segment, fillColor.Alpha)
|
return r.parseShdColor(fillColor.RadialShd.Segment, fillColor.Alpha)
|
||||||
}
|
|
||||||
if strings.TrimSpace(fillColor.Value) != "" {
|
|
||||||
return parseColorWithAlpha(fillColor.Value, fillColor.Alpha)
|
|
||||||
}
|
}
|
||||||
|
if fillColor.unsupported && strings.TrimSpace(fillColor.Value) == "" && fillColor.Index == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
return r.parseColorWithAlpha(fillColor.Value, fillColor.Index, fillColor.ColorSpace, fillColor.Alpha)
|
||||||
|
}
|
||||||
|
|
||||||
// parseFillPaint 解析填充画刷
|
// parseFillPaint 解析填充画刷
|
||||||
// 入参: fillColor 填充颜色节点, x X坐标, y Y坐标, pageH 页面高度
|
// 入参: fillColor 填充颜色节点, x X坐标, y Y坐标, pageH 页面高度
|
||||||
// 返回: any 填充画刷
|
// 返回: any 填充画刷
|
||||||
func parseFillPaint(fillColor *FillColor, x, y, pageH float64) any {
|
func (r *Renderer) parseFillPaint(fillColor *FillColor, x, y, pageH float64) any {
|
||||||
if fillColor == nil {
|
if fillColor == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if fillColor.Pattern != nil {
|
if fillColor.Pattern != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if gradient := parseAxialShdGradient(fillColor.AxialShd, fillColor.Alpha, x, y, pageH); gradient != nil {
|
if gradient := r.parseAxialShdGradient(fillColor.AxialShd, fillColor.Alpha, x, y, pageH); gradient != nil {
|
||||||
return newShdPaint(gradient, fillColor.AxialShd.Extend, fillColor.AxialShd.MapType, fillColor.AxialShd.MapUnit)
|
return newShdPaint(gradient, fillColor.AxialShd.Extend, fillColor.AxialShd.MapType, fillColor.AxialShd.MapUnit)
|
||||||
}
|
}
|
||||||
if paint := parseRadialShdPaint(fillColor.RadialShd, fillColor.Alpha, x, y, pageH); paint != nil {
|
if paint := r.parseRadialShdPaint(fillColor.RadialShd, fillColor.Alpha, x, y, pageH); paint != nil {
|
||||||
return paint
|
return paint
|
||||||
}
|
}
|
||||||
if fillColor.AxialShd != nil {
|
return r.parseFillColor(fillColor)
|
||||||
return parseShdColor(fillColor.AxialShd.Segment, fillColor.Alpha)
|
|
||||||
}
|
|
||||||
if fillColor.RadialShd != nil {
|
|
||||||
return parseShdColor(fillColor.RadialShd.Segment, fillColor.Alpha)
|
|
||||||
}
|
|
||||||
if strings.TrimSpace(fillColor.Value) != "" {
|
|
||||||
return parseColorWithAlpha(fillColor.Value, fillColor.Alpha)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseStrokeColor 解析勾边颜色
|
// parseStrokeColor 解析勾边颜色
|
||||||
// 入参: strokeColor 勾边颜色节点
|
// 入参: strokeColor 勾边颜色节点
|
||||||
// 返回: color.Color 颜色对象
|
// 返回: color.Color 颜色对象
|
||||||
func parseStrokeColor(strokeColor *StrokeColor) color.Color {
|
func (r *Renderer) parseStrokeColor(strokeColor *StrokeColor) color.Color {
|
||||||
if strokeColor == nil {
|
return r.parseFillColor((*FillColor)(strokeColor))
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if strokeColor.AxialShd != nil {
|
|
||||||
return parseShdColor(strokeColor.AxialShd.Segment, strokeColor.Alpha)
|
|
||||||
}
|
|
||||||
if strokeColor.RadialShd != nil {
|
|
||||||
return parseShdColor(strokeColor.RadialShd.Segment, strokeColor.Alpha)
|
|
||||||
}
|
|
||||||
if strings.TrimSpace(strokeColor.Value) != "" {
|
|
||||||
return parseColorWithAlpha(strokeColor.Value, strokeColor.Alpha)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseStrokePaint 解析勾边画刷
|
// parseStrokePaint 解析勾边画刷
|
||||||
// 入参: strokeColor 勾边颜色节点, x X坐标, y Y坐标, pageH 页面高度
|
// 入参: strokeColor 勾边颜色节点, x X坐标, y Y坐标, pageH 页面高度
|
||||||
// 返回: any 勾边画刷
|
// 返回: any 勾边画刷
|
||||||
func parseStrokePaint(strokeColor *StrokeColor, x, y, pageH float64) any {
|
func (r *Renderer) parseStrokePaint(strokeColor *StrokeColor, x, y, pageH float64) any {
|
||||||
if strokeColor == nil {
|
return r.parseFillPaint((*FillColor)(strokeColor), x, y, pageH)
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if gradient := parseAxialShdGradient(strokeColor.AxialShd, strokeColor.Alpha, x, y, pageH); gradient != nil {
|
|
||||||
return newShdPaint(gradient, strokeColor.AxialShd.Extend, strokeColor.AxialShd.MapType, strokeColor.AxialShd.MapUnit)
|
|
||||||
}
|
|
||||||
if paint := parseRadialShdPaint(strokeColor.RadialShd, strokeColor.Alpha, x, y, pageH); paint != nil {
|
|
||||||
return paint
|
|
||||||
}
|
|
||||||
if strokeColor.AxialShd != nil {
|
|
||||||
return parseShdColor(strokeColor.AxialShd.Segment, strokeColor.Alpha)
|
|
||||||
}
|
|
||||||
if strokeColor.RadialShd != nil {
|
|
||||||
return parseShdColor(strokeColor.RadialShd.Segment, strokeColor.Alpha)
|
|
||||||
}
|
|
||||||
if strings.TrimSpace(strokeColor.Value) != "" {
|
|
||||||
return parseColorWithAlpha(strokeColor.Value, strokeColor.Alpha)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// patternColor 获取图案单元默认颜色
|
type patternPaint struct {
|
||||||
// 入参: fillColor 填充颜色节点
|
*Pattern
|
||||||
// 返回: color.Color 默认颜色
|
color color.Color
|
||||||
func patternColor(fillColor *FillColor) color.Color {
|
alpha *int
|
||||||
if fillColor == nil || strings.TrimSpace(fillColor.Value) == "" {
|
}
|
||||||
|
|
||||||
|
// parsePatternPaint 解析底纹画刷
|
||||||
|
// 入参: pattern 底纹对象, value 颜色值, index 调色板索引, space 颜色空间标识, alpha 透明度
|
||||||
|
// 返回: *patternPaint 底纹画刷
|
||||||
|
func (r *Renderer) parsePatternPaint(pattern *Pattern, value string, index *int, space string, alpha *int) *patternPaint {
|
||||||
|
if pattern == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return parseColorWithAlpha(fillColor.Value, fillColor.Alpha)
|
return &patternPaint{Pattern: pattern, color: r.parseColorWithAlpha(value, index, space, nil), alpha: alpha}
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseShdColor 解析渐变颜色
|
// parseShdColor 解析渐变颜色
|
||||||
// 入参: segments 渐变分段, alpha 透明度
|
// 入参: segments 渐变分段, alpha 透明度
|
||||||
// 返回: color.Color 颜色对象
|
// 返回: color.Color 颜色对象
|
||||||
func parseShdColor(segments []ShdSegment, alpha *int) color.Color {
|
func (r *Renderer) parseShdColor(segments []ShdSegment, alpha *int) color.Color {
|
||||||
for _, segment := range segments {
|
if len(segments) == 0 {
|
||||||
if strings.TrimSpace(segment.Color.Value) == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
segmentAlpha := mergeAlpha(segment.Color.Alpha, alpha)
|
|
||||||
return parseColorWithAlpha(segment.Color.Value, segmentAlpha)
|
|
||||||
}
|
|
||||||
return color.Black
|
return color.Black
|
||||||
}
|
}
|
||||||
|
c := segments[0].Color
|
||||||
|
return r.parseColorWithAlpha(c.Value, c.Index, c.ColorSpace, mergeAlpha(c.Alpha, alpha))
|
||||||
|
}
|
||||||
|
|
||||||
// parseShdSegments 解析渐变分段
|
// parseShdSegments 解析渐变分段
|
||||||
// 入参: segments 渐变分段, alpha 透明度
|
// 入参: segments 渐变分段, alpha 透明度
|
||||||
// 返回: canvas.Grad 渐变分段
|
// 返回: canvas.Grad 渐变分段
|
||||||
func parseShdSegments(segments []ShdSegment, alpha *int) canvas.Grad {
|
func (r *Renderer) parseShdSegments(segments []ShdSegment, alpha *int) canvas.Grad {
|
||||||
gradient := canvas.NewGradient()
|
gradient := canvas.NewGradient()
|
||||||
position, step := 0.0, 0.0
|
position, step := 0.0, 0.0
|
||||||
for i, segment := range segments {
|
for i, segment := range segments {
|
||||||
@@ -275,11 +265,8 @@ func parseShdSegments(segments []ShdSegment, alpha *int) canvas.Grad {
|
|||||||
}
|
}
|
||||||
offset := position
|
offset := position
|
||||||
position += step
|
position += step
|
||||||
if strings.TrimSpace(segment.Color.Value) == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
segmentAlpha := mergeAlpha(segment.Color.Alpha, alpha)
|
segmentAlpha := mergeAlpha(segment.Color.Alpha, alpha)
|
||||||
gradient.Add(offset, colorToRGBA(parseColorWithAlpha(segment.Color.Value, segmentAlpha)))
|
gradient.Add(offset, colorToRGBA(r.parseColorWithAlpha(segment.Color.Value, segment.Color.Index, segment.Color.ColorSpace, segmentAlpha)))
|
||||||
}
|
}
|
||||||
if len(gradient) == 0 {
|
if len(gradient) == 0 {
|
||||||
return nil
|
return nil
|
||||||
@@ -290,7 +277,7 @@ func parseShdSegments(segments []ShdSegment, alpha *int) canvas.Grad {
|
|||||||
// parseAxialShdGradient 解析轴向渐变
|
// parseAxialShdGradient 解析轴向渐变
|
||||||
// 入参: axialShd 轴向渐变节点, alpha 透明度, x X坐标, y Y坐标, pageH 页面高度
|
// 入参: axialShd 轴向渐变节点, alpha 透明度, x X坐标, y Y坐标, pageH 页面高度
|
||||||
// 返回: canvas.Gradient 渐变对象
|
// 返回: canvas.Gradient 渐变对象
|
||||||
func parseAxialShdGradient(axialShd *AxialShd, alpha *int, x, y, pageH float64) canvas.Gradient {
|
func (r *Renderer) parseAxialShdGradient(axialShd *AxialShd, alpha *int, x, y, pageH float64) canvas.Gradient {
|
||||||
if axialShd == nil {
|
if axialShd == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -299,7 +286,7 @@ func parseAxialShdGradient(axialShd *AxialShd, alpha *int, x, y, pageH float64)
|
|||||||
if len(start) < 2 || len(end) < 2 {
|
if len(start) < 2 || len(end) < 2 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
gradient := parseShdSegments(axialShd.Segment, alpha)
|
gradient := r.parseShdSegments(axialShd.Segment, alpha)
|
||||||
if gradient == nil {
|
if gradient == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -342,7 +329,7 @@ func axialShdClip(ctx *canvas.Context, gradient *canvas.LinearGradient, extend i
|
|||||||
// parseRadialShdPaint 解析径向渐变画刷
|
// parseRadialShdPaint 解析径向渐变画刷
|
||||||
// 入参: radialShd 径向渐变节点, alpha 透明度, x X坐标, y Y坐标, pageH 页面高度
|
// 入参: radialShd 径向渐变节点, alpha 透明度, x X坐标, y Y坐标, pageH 页面高度
|
||||||
// 返回: *shdPaint 渐变画刷
|
// 返回: *shdPaint 渐变画刷
|
||||||
func parseRadialShdPaint(radialShd *RadialShd, alpha *int, x, y, pageH float64) *shdPaint {
|
func (r *Renderer) parseRadialShdPaint(radialShd *RadialShd, alpha *int, x, y, pageH float64) *shdPaint {
|
||||||
if radialShd == nil || radialShd.EndRadius <= 0 {
|
if radialShd == nil || radialShd.EndRadius <= 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -351,7 +338,7 @@ func parseRadialShdPaint(radialShd *RadialShd, alpha *int, x, y, pageH float64)
|
|||||||
if len(start) < 2 || len(end) < 2 {
|
if len(start) < 2 || len(end) < 2 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
gradient := parseShdSegments(radialShd.Segment, alpha)
|
gradient := r.parseShdSegments(radialShd.Segment, alpha)
|
||||||
if gradient == nil {
|
if gradient == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ type Reader struct {
|
|||||||
RootDir string
|
RootDir string
|
||||||
ResMap map[string]string
|
ResMap map[string]string
|
||||||
fontCache map[string]*Font
|
fontCache map[string]*Font
|
||||||
|
colorSpaceCache map[string]*ColorSpace
|
||||||
drawParamCache map[string]*DrawParam
|
drawParamCache map[string]*DrawParam
|
||||||
compositeGraphicUnitCache map[string]*CompositeGraphicUnit
|
compositeGraphicUnitCache map[string]*CompositeGraphicUnit
|
||||||
doc *Document
|
doc *Document
|
||||||
@@ -74,6 +75,7 @@ func (r *Reader) initRoot() error {
|
|||||||
r.OFD = &ofd
|
r.OFD = &ofd
|
||||||
r.ResMap = make(map[string]string)
|
r.ResMap = make(map[string]string)
|
||||||
r.fontCache = make(map[string]*Font)
|
r.fontCache = make(map[string]*Font)
|
||||||
|
r.colorSpaceCache = make(map[string]*ColorSpace)
|
||||||
r.drawParamCache = make(map[string]*DrawParam)
|
r.drawParamCache = make(map[string]*DrawParam)
|
||||||
r.compositeGraphicUnitCache = make(map[string]*CompositeGraphicUnit)
|
r.compositeGraphicUnitCache = make(map[string]*CompositeGraphicUnit)
|
||||||
return nil
|
return nil
|
||||||
@@ -186,6 +188,10 @@ func (r *Reader) loadRes(resPath string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
baseLoc := res.BaseLoc
|
baseLoc := res.BaseLoc
|
||||||
|
for i := range res.ColorSpaces.ColorSpace {
|
||||||
|
cs := &res.ColorSpaces.ColorSpace[i]
|
||||||
|
r.colorSpaceCache[cs.ID] = cs
|
||||||
|
}
|
||||||
for _, mm := range res.MultiMedias.MultiMedia {
|
for _, mm := range res.MultiMedias.MultiMedia {
|
||||||
if mm.MediaFile != "" {
|
if mm.MediaFile != "" {
|
||||||
if finalPath := resolveResourcePath(resPath, baseLoc, mm.MediaFile); finalPath != "" {
|
if finalPath := resolveResourcePath(resPath, baseLoc, mm.MediaFile); finalPath != "" {
|
||||||
@@ -245,6 +251,9 @@ func (r *Reader) PageContent(page Page) (*PageContent, error) {
|
|||||||
return nil, fmt.Errorf("failed to unmarshal page content: %w", err)
|
return nil, fmt.Errorf("failed to unmarshal page content: %w", err)
|
||||||
}
|
}
|
||||||
content.ID = page.ID
|
content.ID = page.ID
|
||||||
|
if content.PageRes != "" {
|
||||||
|
r.loadRes(resolveResourcePath(page.BaseLoc, "", content.PageRes))
|
||||||
|
}
|
||||||
return &content, nil
|
return &content, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -194,10 +194,10 @@ func (r *Renderer) drawParamDefaults(id string, defaultFill, defaultStroke color
|
|||||||
defaultLW = dp.LineWidth
|
defaultLW = dp.LineWidth
|
||||||
}
|
}
|
||||||
if dp.FillColor != nil {
|
if dp.FillColor != nil {
|
||||||
defaultFill = parseFillColor(dp.FillColor)
|
defaultFill = r.parseFillColor(dp.FillColor)
|
||||||
}
|
}
|
||||||
if dp.StrokeColor != nil {
|
if dp.StrokeColor != nil {
|
||||||
defaultStroke = parseStrokeColor(dp.StrokeColor)
|
defaultStroke = r.parseStrokeColor(dp.StrokeColor)
|
||||||
}
|
}
|
||||||
return defaultFill, defaultStroke, defaultLW
|
return defaultFill, defaultStroke, defaultLW
|
||||||
}
|
}
|
||||||
|
|||||||
+43
-31
@@ -30,8 +30,8 @@ type pathStyle struct {
|
|||||||
strokeColor color.Color
|
strokeColor color.Color
|
||||||
fillPaint any
|
fillPaint any
|
||||||
strokePaint any
|
strokePaint any
|
||||||
fillPattern *Pattern
|
fillPattern *patternPaint
|
||||||
fillPatternColor color.Color
|
strokePattern *patternPaint
|
||||||
lineWidth float64
|
lineWidth float64
|
||||||
lineCap canvas.Capper
|
lineCap canvas.Capper
|
||||||
lineJoin canvas.Joiner
|
lineJoin canvas.Joiner
|
||||||
@@ -59,21 +59,21 @@ func newPathStyle(defaultFill, defaultStroke color.Color, defaultLW float64, alp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// applyFillColor 应用填充颜色
|
// applyFillColor 应用填充颜色
|
||||||
// 入参: fill 填充颜色, bx 边界X坐标, by 边界Y坐标, pageH 页面高度, alpha 对象透明度
|
// 入参: r 渲染器, fill 填充颜色, bx 边界X坐标, by 边界Y坐标, pageH 页面高度, alpha 对象透明度
|
||||||
func (s *pathStyle) applyFillColor(fill *FillColor, bx, by, pageH float64, alpha *int) {
|
func (s *pathStyle) applyFillColor(r *Renderer, fill *FillColor, bx, by, pageH float64, alpha *int) {
|
||||||
fillColorNode := withFillAlpha(fill, alpha)
|
fillColorNode := withFillAlpha(fill, alpha)
|
||||||
s.fillPattern = fillColorNode.Pattern
|
s.fillPattern = r.parsePatternPaint(fillColorNode.Pattern, fillColorNode.Value, fillColorNode.Index, fillColorNode.ColorSpace, fillColorNode.Alpha)
|
||||||
s.fillPatternColor = patternColor(fillColorNode)
|
s.fillColor = r.parseFillColor(fillColorNode)
|
||||||
s.fillColor = parseFillColor(fillColorNode)
|
s.fillPaint = r.parseFillPaint(fillColorNode, bx, by, pageH)
|
||||||
s.fillPaint = parseFillPaint(fillColorNode, bx, by, pageH)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyStrokeColor 应用描边颜色
|
// applyStrokeColor 应用描边颜色
|
||||||
// 入参: stroke 描边颜色, bx 边界X坐标, by 边界Y坐标, pageH 页面高度, alpha 对象透明度
|
// 入参: r 渲染器, stroke 描边颜色, bx 边界X坐标, by 边界Y坐标, pageH 页面高度, alpha 对象透明度
|
||||||
func (s *pathStyle) applyStrokeColor(stroke *StrokeColor, bx, by, pageH float64, alpha *int) {
|
func (s *pathStyle) applyStrokeColor(r *Renderer, stroke *StrokeColor, bx, by, pageH float64, alpha *int) {
|
||||||
strokeColorNode := withStrokeAlpha(stroke, alpha)
|
strokeColorNode := withStrokeAlpha(stroke, alpha)
|
||||||
s.strokeColor = parseStrokeColor(strokeColorNode)
|
s.strokePattern = r.parsePatternPaint(strokeColorNode.Pattern, strokeColorNode.Value, strokeColorNode.Index, strokeColorNode.ColorSpace, strokeColorNode.Alpha)
|
||||||
s.strokePaint = parseStrokePaint(strokeColorNode, bx, by, pageH)
|
s.strokeColor = r.parseStrokeColor(strokeColorNode)
|
||||||
|
s.strokePaint = r.parseStrokePaint(strokeColorNode, bx, by, pageH)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pathLineCap 转换线帽样式
|
// pathLineCap 转换线帽样式
|
||||||
@@ -103,16 +103,16 @@ func pathLineJoin(join string, fallback canvas.Joiner) canvas.Joiner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// applyDrawParam 应用绘制参数样式
|
// applyDrawParam 应用绘制参数样式
|
||||||
// 入参: dp 绘制参数, bx 边界X坐标, by 边界Y坐标, pageH 页面高度, alpha 对象透明度
|
// 入参: r 渲染器, dp 绘制参数, bx 边界X坐标, by 边界Y坐标, pageH 页面高度, alpha 对象透明度
|
||||||
func (s *pathStyle) applyDrawParam(dp *DrawParam, bx, by, pageH float64, alpha *int) {
|
func (s *pathStyle) applyDrawParam(r *Renderer, dp *DrawParam, bx, by, pageH float64, alpha *int) {
|
||||||
if dp.LineWidth > 0 {
|
if dp.LineWidth > 0 {
|
||||||
s.lineWidth = dp.LineWidth
|
s.lineWidth = dp.LineWidth
|
||||||
}
|
}
|
||||||
if dp.FillColor != nil {
|
if dp.FillColor != nil {
|
||||||
s.applyFillColor(dp.FillColor, bx, by, pageH, alpha)
|
s.applyFillColor(r, dp.FillColor, bx, by, pageH, alpha)
|
||||||
}
|
}
|
||||||
if dp.StrokeColor != nil {
|
if dp.StrokeColor != nil {
|
||||||
s.applyStrokeColor(dp.StrokeColor, bx, by, pageH, alpha)
|
s.applyStrokeColor(r, dp.StrokeColor, bx, by, pageH, alpha)
|
||||||
}
|
}
|
||||||
if dp.Cap != "" {
|
if dp.Cap != "" {
|
||||||
s.lineCap = pathLineCap(dp.Cap, s.lineCap)
|
s.lineCap = pathLineCap(dp.Cap, s.lineCap)
|
||||||
@@ -127,16 +127,16 @@ func (s *pathStyle) applyDrawParam(dp *DrawParam, bx, by, pageH float64, alpha *
|
|||||||
}
|
}
|
||||||
|
|
||||||
// applyPathObject 应用路径对象样式
|
// applyPathObject 应用路径对象样式
|
||||||
// 入参: obj 路径对象, bx 边界X坐标, by 边界Y坐标, pageH 页面高度
|
// 入参: r 渲染器, obj 路径对象, bx 边界X坐标, by 边界Y坐标, pageH 页面高度
|
||||||
func (s *pathStyle) applyPathObject(obj PathObject, bx, by, pageH float64) {
|
func (s *pathStyle) applyPathObject(r *Renderer, obj PathObject, bx, by, pageH float64) {
|
||||||
if obj.LineWidth > 0 {
|
if obj.LineWidth > 0 {
|
||||||
s.lineWidth = obj.LineWidth
|
s.lineWidth = obj.LineWidth
|
||||||
}
|
}
|
||||||
if obj.FillColor != nil {
|
if obj.FillColor != nil {
|
||||||
s.applyFillColor(obj.FillColor, bx, by, pageH, obj.Alpha)
|
s.applyFillColor(r, obj.FillColor, bx, by, pageH, obj.Alpha)
|
||||||
}
|
}
|
||||||
if obj.StrokeColor != nil {
|
if obj.StrokeColor != nil {
|
||||||
s.applyStrokeColor(obj.StrokeColor, bx, by, pageH, obj.Alpha)
|
s.applyStrokeColor(r, obj.StrokeColor, bx, by, pageH, obj.Alpha)
|
||||||
}
|
}
|
||||||
if obj.Cap != "" {
|
if obj.Cap != "" {
|
||||||
s.lineCap = pathLineCap(obj.Cap, canvas.ButtCap)
|
s.lineCap = pathLineCap(obj.Cap, canvas.ButtCap)
|
||||||
@@ -183,11 +183,15 @@ func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64
|
|||||||
style := newPathStyle(defaultFill, defaultStroke, defaultLW, obj.Alpha)
|
style := newPathStyle(defaultFill, defaultStroke, defaultLW, obj.Alpha)
|
||||||
if obj.DrawParam != "" {
|
if obj.DrawParam != "" {
|
||||||
if dp := r.getDrawParam(obj.DrawParam, nil); dp != nil {
|
if dp := r.getDrawParam(obj.DrawParam, nil); dp != nil {
|
||||||
style.applyDrawParam(dp, bx, by, pageH, obj.Alpha)
|
style.applyDrawParam(r, dp, bx, by, pageH, obj.Alpha)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
style.applyPathObject(obj, bx, by, pageH)
|
style.applyPathObject(r, obj, bx, by, pageH)
|
||||||
style.scale(ctm)
|
style.scale(ctm)
|
||||||
|
patternCTM := TranslationMatrix(bx, by).Multiply(ctm)
|
||||||
|
if boundaryInCTM && parentCTM != nil {
|
||||||
|
patternCTM = parentCTM.Multiply(TranslationMatrix(bx, by)).Multiply(localCTM)
|
||||||
|
}
|
||||||
pathCTM := ctm
|
pathCTM := ctm
|
||||||
if boundaryInCTM {
|
if boundaryInCTM {
|
||||||
pathCTM = localCTM
|
pathCTM = localCTM
|
||||||
@@ -227,7 +231,7 @@ func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64
|
|||||||
fp = applyClipPath(fp, fillClip)
|
fp = applyClipPath(fp, fillClip)
|
||||||
}
|
}
|
||||||
if style.fillPattern != nil {
|
if style.fillPattern != nil {
|
||||||
r.renderPattern(ctx, style.fillPattern, style.fillPatternColor, pageH, fp, ctm, bx, by)
|
r.renderPattern(ctx, style.fillPattern, pageH, fp, patternCTM)
|
||||||
} else if style.fillPaint != nil {
|
} else if style.fillPaint != nil {
|
||||||
ctx.SetFillRule(fillRule)
|
ctx.SetFillRule(fillRule)
|
||||||
ctx.SetFill(fillPaint)
|
ctx.SetFill(fillPaint)
|
||||||
@@ -259,13 +263,17 @@ func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64
|
|||||||
ctx.SetDashes(0)
|
ctx.SetDashes(0)
|
||||||
}
|
}
|
||||||
strokeClip := intersectClipPath(clipPath, shadingClip)
|
strokeClip := intersectClipPath(clipPath, shadingClip)
|
||||||
if strokeClip != nil || strokeView != canvas.Identity {
|
if strokeClip != nil || strokeView != canvas.Identity || style.strokePattern != nil {
|
||||||
sp = sp.Copy()
|
sp = sp.Copy()
|
||||||
sp = sp.Stroke(style.lineWidth, style.lineCap, style.lineJoin, canvas.Tolerance)
|
sp = sp.Stroke(style.lineWidth, style.lineCap, style.lineJoin, canvas.Tolerance)
|
||||||
sp = applyClipPath(sp, strokeClip)
|
sp = applyClipPath(sp, strokeClip)
|
||||||
|
if style.strokePattern != nil {
|
||||||
|
r.renderPattern(ctx, style.strokePattern, pageH, sp, patternCTM)
|
||||||
|
} else {
|
||||||
ctx.SetFill(strokePaint)
|
ctx.SetFill(strokePaint)
|
||||||
ctx.SetStrokeColor(canvas.Transparent)
|
ctx.SetStrokeColor(canvas.Transparent)
|
||||||
drawShdPath(ctx, sp, strokeView)
|
drawShdPath(ctx, sp, strokeView)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ctx.DrawPath(0, 0, sp)
|
ctx.DrawPath(0, 0, sp)
|
||||||
}
|
}
|
||||||
@@ -274,22 +282,25 @@ func (r *Renderer) renderPath(ctx *canvas.Context, obj PathObject, pageH float64
|
|||||||
}
|
}
|
||||||
|
|
||||||
// renderPattern 渲染图案填充
|
// renderPattern 渲染图案填充
|
||||||
// 入参: ctx 画布上下文, pattern 图案对象, defaultColor 默认颜色, pageH 页面高度, clip 填充区域, parentCTM 父级CTM, bx 边界X坐标, by 边界Y坐标
|
// 入参: ctx 画布上下文, pattern 底纹画刷, pageH 页面高度, clip 绘制区域, objectCTM 对象变换矩阵
|
||||||
func (r *Renderer) renderPattern(ctx *canvas.Context, pattern *Pattern, defaultColor color.Color, pageH float64, clip *canvas.Path, parentCTM Matrix, bx, by float64) {
|
func (r *Renderer) renderPattern(ctx *canvas.Context, pattern *patternPaint, pageH float64, clip *canvas.Path, objectCTM Matrix) {
|
||||||
if pattern == nil || clip == nil || len(pattern.CellContent.Objects) == 0 {
|
if clip == nil || clip.Empty() || len(pattern.CellContent.Objects) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
xStep, yStep := pattern.XStep, pattern.YStep
|
xStep, yStep := pattern.XStep, pattern.YStep
|
||||||
if xStep == 0 {
|
if xStep < pattern.Width {
|
||||||
xStep = pattern.Width
|
xStep = pattern.Width
|
||||||
}
|
}
|
||||||
if yStep == 0 {
|
if yStep < pattern.Height {
|
||||||
yStep = pattern.Height
|
yStep = pattern.Height
|
||||||
}
|
}
|
||||||
if xStep <= 0 || yStep <= 0 {
|
if xStep <= 0 || yStep <= 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
patternCTM := TranslationMatrix(bx, by).Multiply(parentCTM).Multiply(NewMatrix(pattern.CTM))
|
patternCTM := NewMatrix(pattern.CTM)
|
||||||
|
if pattern.RelativeTo != "Page" {
|
||||||
|
patternCTM = objectCTM.Multiply(patternCTM)
|
||||||
|
}
|
||||||
invCTM, ok := patternCTM.Invert()
|
invCTM, ok := patternCTM.Invert()
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
@@ -329,7 +340,8 @@ func (r *Renderer) renderPattern(ctx *canvas.Context, pattern *Pattern, defaultC
|
|||||||
tileCTM = tileCTM.Multiply(Matrix{a: 1, d: -1, f: pattern.Height})
|
tileCTM = tileCTM.Multiply(Matrix{a: 1, d: -1, f: pattern.Height})
|
||||||
}
|
}
|
||||||
for _, obj := range pattern.CellContent.Objects {
|
for _, obj := range pattern.CellContent.Objects {
|
||||||
r.renderObject(ctx, obj, pageH, defaultColor, defaultColor, 0, &tileCTM, true, clip)
|
obj = mergeGraphicObjectAlpha(obj, pattern.alpha)
|
||||||
|
r.renderObject(ctx, obj, pageH, pattern.color, pattern.color, 0, &tileCTM, true, clip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+41
-14
@@ -76,15 +76,19 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
fillColor = colorWithAlpha(canvas.Black, obj.Alpha)
|
fillColor = colorWithAlpha(canvas.Black, obj.Alpha)
|
||||||
}
|
}
|
||||||
var fillPaint any = fillColor
|
var fillPaint any = fillColor
|
||||||
|
var fillPattern *patternPaint
|
||||||
|
var fillColorNode *FillColor
|
||||||
if dp != nil && dp.FillColor != nil {
|
if dp != nil && dp.FillColor != nil {
|
||||||
fillColorNode := withFillAlpha(dp.FillColor, obj.Alpha)
|
fillColorNode = dp.FillColor
|
||||||
fillColor = parseFillColor(fillColorNode)
|
|
||||||
fillPaint = parseFillPaint(fillColorNode, bx, by, pageH)
|
|
||||||
}
|
}
|
||||||
if obj.FillColor != nil {
|
if obj.FillColor != nil {
|
||||||
fillColorNode := withFillAlpha(obj.FillColor, obj.Alpha)
|
fillColorNode = obj.FillColor
|
||||||
fillColor = parseFillColor(fillColorNode)
|
}
|
||||||
fillPaint = parseFillPaint(fillColorNode, bx, by, pageH)
|
if fillColorNode != nil {
|
||||||
|
fillColorNode = withFillAlpha(fillColorNode, obj.Alpha)
|
||||||
|
fillColor = r.parseFillColor(fillColorNode)
|
||||||
|
fillPaint = r.parseFillPaint(fillColorNode, bx, by, pageH)
|
||||||
|
fillPattern = r.parsePatternPaint(fillColorNode.Pattern, fillColorNode.Value, fillColorNode.Index, fillColorNode.ColorSpace, fillColorNode.Alpha)
|
||||||
}
|
}
|
||||||
if fillPaint == nil {
|
if fillPaint == nil {
|
||||||
fillPaint = fillColor
|
fillPaint = fillColor
|
||||||
@@ -96,10 +100,10 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
strokeView := canvas.Identity
|
strokeView := canvas.Identity
|
||||||
if shouldStroke {
|
if shouldStroke {
|
||||||
if dp != nil {
|
if dp != nil {
|
||||||
strokeStyle.applyDrawParam(dp, bx, by, pageH, obj.Alpha)
|
strokeStyle.applyDrawParam(r, dp, bx, by, pageH, obj.Alpha)
|
||||||
}
|
}
|
||||||
if obj.StrokeColor != nil {
|
if obj.StrokeColor != nil {
|
||||||
strokeStyle.applyStrokeColor(obj.StrokeColor, bx, by, pageH, obj.Alpha)
|
strokeStyle.applyStrokeColor(r, obj.StrokeColor, bx, by, pageH, obj.Alpha)
|
||||||
}
|
}
|
||||||
if obj.LineWidth > 0 {
|
if obj.LineWidth > 0 {
|
||||||
strokeStyle.lineWidth = obj.LineWidth
|
strokeStyle.lineWidth = obj.LineWidth
|
||||||
@@ -111,6 +115,10 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
strokeStyle.strokePaint, shadingClip, strokeView = resolveShdPaint(ctx, strokeStyle.strokePaint)
|
strokeStyle.strokePaint, shadingClip, strokeView = resolveShdPaint(ctx, strokeStyle.strokePaint)
|
||||||
strokeClip = intersectClipPath(strokeClip, shadingClip)
|
strokeClip = intersectClipPath(strokeClip, shadingClip)
|
||||||
}
|
}
|
||||||
|
patternCTM := TranslationMatrix(bx, by).Multiply(ctm)
|
||||||
|
if boundaryInCTM && parentCTM != nil {
|
||||||
|
patternCTM = parentCTM.Multiply(TranslationMatrix(bx, by)).Multiply(localCTM)
|
||||||
|
}
|
||||||
fontStyle := canvas.FontRegular
|
fontStyle := canvas.FontRegular
|
||||||
weight := obj.Weight
|
weight := obj.Weight
|
||||||
if weight == 0 && dp != nil && dp.Weight > 0 {
|
if weight == 0 && dp != nil && dp.Weight > 0 {
|
||||||
@@ -173,7 +181,7 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
}
|
}
|
||||||
dxs, dys := parseFloats(tc.DeltaX), parseFloats(tc.DeltaY)
|
dxs, dys := parseFloats(tc.DeltaX), parseFloats(tc.DeltaY)
|
||||||
xs, ys := parseFloats(tc.X), parseFloats(tc.Y)
|
xs, ys := parseFloats(tc.X), parseFloats(tc.Y)
|
||||||
drawAsPath := embeddedFont || textCodePositioned(tc, xs, ys) || fillClip != nil || shadedFill || shouldStroke
|
drawAsPath := embeddedFont || textCodePositioned(tc, xs, ys) || fillClip != nil || shadedFill || fillPattern != nil || shouldStroke
|
||||||
cx, cy := 0.0, 0.0
|
cx, cy := 0.0, 0.0
|
||||||
previousAdvance := 0.0
|
previousAdvance := 0.0
|
||||||
if len(xs) > 0 {
|
if len(xs) > 0 {
|
||||||
@@ -238,7 +246,9 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
transform = transform.Mul(glyphMatrix)
|
transform = transform.Mul(glyphMatrix)
|
||||||
}
|
}
|
||||||
path := glyphPath.Copy().Transform(transform.Scale(scaleX, 1))
|
path := glyphPath.Copy().Transform(transform.Scale(scaleX, 1))
|
||||||
if shouldFill && fillPaint != nil {
|
if shouldFill && fillPattern != nil {
|
||||||
|
r.renderPattern(ctx, fillPattern, pageH, applyClipPath(path.Copy(), fillClip), patternCTM)
|
||||||
|
} else if shouldFill && fillPaint != nil {
|
||||||
ctx.SetFill(fillPaint)
|
ctx.SetFill(fillPaint)
|
||||||
ctx.SetStrokeColor(canvas.Transparent)
|
ctx.SetStrokeColor(canvas.Transparent)
|
||||||
drawShdPath(ctx, applyClipPath(path.Copy(), fillClip), fillView)
|
drawShdPath(ctx, applyClipPath(path.Copy(), fillClip), fillView)
|
||||||
@@ -247,26 +257,35 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
path = path.Dash(strokeStyle.dashOffset, strokeStyle.dashPattern...)
|
path = path.Dash(strokeStyle.dashOffset, strokeStyle.dashPattern...)
|
||||||
}
|
}
|
||||||
path = path.Stroke(strokeStyle.lineWidth, strokeStyle.lineCap, strokeStyle.lineJoin, canvas.Tolerance)
|
path = path.Stroke(strokeStyle.lineWidth, strokeStyle.lineCap, strokeStyle.lineJoin, canvas.Tolerance)
|
||||||
|
path = applyClipPath(path, strokeClip)
|
||||||
|
if strokeStyle.strokePattern != nil {
|
||||||
|
r.renderPattern(ctx, strokeStyle.strokePattern, pageH, path, patternCTM)
|
||||||
|
} else {
|
||||||
ctx.SetFill(strokeStyle.strokePaint)
|
ctx.SetFill(strokeStyle.strokePaint)
|
||||||
ctx.SetStrokeColor(canvas.Transparent)
|
ctx.SetStrokeColor(canvas.Transparent)
|
||||||
drawShdPath(ctx, applyClipPath(path, strokeClip), strokeView)
|
drawShdPath(ctx, path, strokeView)
|
||||||
|
}
|
||||||
if hasUnderline {
|
if hasUnderline {
|
||||||
underline := &canvas.Path{}
|
underline := &canvas.Path{}
|
||||||
underline.MoveTo(0, -sizeMM*0.1)
|
underline.MoveTo(0, -sizeMM*0.1)
|
||||||
underline.LineTo(glyphWidth*scaleX, -sizeMM*0.1)
|
underline.LineTo(glyphWidth*scaleX, -sizeMM*0.1)
|
||||||
underline = underline.Stroke(sizeMM*0.05, canvas.ButtCap, canvas.MiterJoin, canvas.Tolerance)
|
underline = underline.Stroke(sizeMM*0.05, canvas.ButtCap, canvas.MiterJoin, canvas.Tolerance)
|
||||||
if shouldFill {
|
if shouldFill && fillPattern != nil {
|
||||||
|
r.renderPattern(ctx, fillPattern, pageH, applyClipPath(underline.Transform(transform), clipPath), patternCTM)
|
||||||
|
} else if shouldFill {
|
||||||
ctx.SetFillColor(fillColor)
|
ctx.SetFillColor(fillColor)
|
||||||
ctx.DrawPath(0, 0, applyClipPath(underline.Transform(transform), clipPath))
|
ctx.DrawPath(0, 0, applyClipPath(underline.Transform(transform), clipPath))
|
||||||
|
} else if strokeStyle.strokePattern != nil {
|
||||||
|
r.renderPattern(ctx, strokeStyle.strokePattern, pageH, applyClipPath(underline.Transform(transform), strokeClip), patternCTM)
|
||||||
} else {
|
} else {
|
||||||
drawShdPath(ctx, applyClipPath(underline.Transform(transform), strokeClip), strokeView)
|
drawShdPath(ctx, applyClipPath(underline.Transform(transform), strokeClip), strokeView)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if fillPaint != nil {
|
if fillPaint != nil || fillPattern != nil {
|
||||||
ctx.SetFill(fillPaint)
|
ctx.SetFill(fillPaint)
|
||||||
if fillClip != nil || shadedFill {
|
if fillClip != nil || shadedFill || fillPattern != nil {
|
||||||
scaleX := hScale
|
scaleX := hScale
|
||||||
if advanceLimit > 0 && glyphWidth*scaleX > advanceLimit {
|
if advanceLimit > 0 && glyphWidth*scaleX > advanceLimit {
|
||||||
scaleX = advanceLimit / glyphWidth
|
scaleX = advanceLimit / glyphWidth
|
||||||
@@ -277,7 +296,11 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
textTransform = textTransform.Mul(glyphMatrix)
|
textTransform = textTransform.Mul(glyphMatrix)
|
||||||
}
|
}
|
||||||
glyphPath = applyClipPath(glyphPath.Copy().Transform(textTransform.Scale(scaleX, 1)), fillClip)
|
glyphPath = applyClipPath(glyphPath.Copy().Transform(textTransform.Scale(scaleX, 1)), fillClip)
|
||||||
|
if fillPattern != nil {
|
||||||
|
r.renderPattern(ctx, fillPattern, pageH, glyphPath, patternCTM)
|
||||||
|
} else {
|
||||||
drawShdPath(ctx, glyphPath, fillView)
|
drawShdPath(ctx, glyphPath, fillView)
|
||||||
|
}
|
||||||
if hasUnderline {
|
if hasUnderline {
|
||||||
uw := sizeMM * 0.05
|
uw := sizeMM * 0.05
|
||||||
off := sizeMM * 0.1
|
off := sizeMM * 0.1
|
||||||
@@ -286,10 +309,14 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
underline.LineTo(textWidth, -off)
|
underline.LineTo(textWidth, -off)
|
||||||
underline = underline.Stroke(uw, canvas.ButtCap, canvas.MiterJoin, canvas.Tolerance)
|
underline = underline.Stroke(uw, canvas.ButtCap, canvas.MiterJoin, canvas.Tolerance)
|
||||||
underline = applyClipPath(underline.Transform(textTransform), clipPath)
|
underline = applyClipPath(underline.Transform(textTransform), clipPath)
|
||||||
|
if fillPattern != nil {
|
||||||
|
r.renderPattern(ctx, fillPattern, pageH, underline, patternCTM)
|
||||||
|
} else {
|
||||||
ctx.SetFillColor(fillColor)
|
ctx.SetFillColor(fillColor)
|
||||||
ctx.SetStrokeColor(canvas.Transparent)
|
ctx.SetStrokeColor(canvas.Transparent)
|
||||||
ctx.DrawPath(0, 0, underline)
|
ctx.DrawPath(0, 0, underline)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
drawGlyph := func(x, y float64) {
|
drawGlyph := func(x, y float64) {
|
||||||
|
|||||||
@@ -20,12 +20,26 @@ import "encoding/xml"
|
|||||||
type Res struct {
|
type Res struct {
|
||||||
XMLName xml.Name `xml:"Res"`
|
XMLName xml.Name `xml:"Res"`
|
||||||
BaseLoc string `xml:"BaseLoc,attr"`
|
BaseLoc string `xml:"BaseLoc,attr"`
|
||||||
|
ColorSpaces ColorSpaces `xml:"ColorSpaces"`
|
||||||
Fonts Fonts `xml:"Fonts"`
|
Fonts Fonts `xml:"Fonts"`
|
||||||
MultiMedias MultiMedias `xml:"MultiMedias"`
|
MultiMedias MultiMedias `xml:"MultiMedias"`
|
||||||
DrawParams DrawParams `xml:"DrawParams"`
|
DrawParams DrawParams `xml:"DrawParams"`
|
||||||
CompositeGraphicUnits CompositeGraphicUnits `xml:"CompositeGraphicUnits"`
|
CompositeGraphicUnits CompositeGraphicUnits `xml:"CompositeGraphicUnits"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ColorSpaces 颜色空间集合
|
||||||
|
type ColorSpaces struct {
|
||||||
|
ColorSpace []ColorSpace `xml:"ColorSpace"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ColorSpace 颜色空间定义
|
||||||
|
type ColorSpace struct {
|
||||||
|
ID string `xml:"ID,attr"`
|
||||||
|
Type string `xml:"Type,attr"`
|
||||||
|
BitsPerComponent int `xml:"BitsPerComponent,attr"`
|
||||||
|
Palette []string `xml:"Palette>CV"`
|
||||||
|
}
|
||||||
|
|
||||||
// Fonts 字体集合
|
// Fonts 字体集合
|
||||||
type Fonts struct {
|
type Fonts struct {
|
||||||
Font []Font `xml:"Font"`
|
Font []Font `xml:"Font"`
|
||||||
|
|||||||
Reference in new issue
Block a user