mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-08-30 12:12:40 +08:00
feat(电子发票): 修复一个非标准发票解析问题
This commit is contained in:
+34
-7
@@ -38,6 +38,7 @@ type Reader struct {
|
|||||||
Stamps map[string][]Stamp
|
Stamps map[string][]Stamp
|
||||||
Annots map[string][]Annotation
|
Annots map[string][]Annotation
|
||||||
fileIndex map[string]*zip.File
|
fileIndex map[string]*zip.File
|
||||||
|
fileIndexFold map[string]*zip.File
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close 关闭阅读器
|
// Close 关闭阅读器
|
||||||
@@ -53,8 +54,14 @@ func (r *Reader) Close() error {
|
|||||||
// 返回: error 错误信息
|
// 返回: error 错误信息
|
||||||
func (r *Reader) initRoot() error {
|
func (r *Reader) initRoot() error {
|
||||||
r.fileIndex = make(map[string]*zip.File)
|
r.fileIndex = make(map[string]*zip.File)
|
||||||
|
r.fileIndexFold = make(map[string]*zip.File)
|
||||||
for _, f := range r.Zip.File {
|
for _, f := range r.Zip.File {
|
||||||
r.fileIndex[f.Name] = f
|
name := cleanPackagePath(f.Name)
|
||||||
|
r.fileIndex[name] = f
|
||||||
|
fold := strings.ToLower(name)
|
||||||
|
if _, ok := r.fileIndexFold[fold]; !ok {
|
||||||
|
r.fileIndexFold[fold] = f
|
||||||
|
}
|
||||||
}
|
}
|
||||||
data, err := r.readFile("OFD.xml")
|
data, err := r.readFile("OFD.xml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -76,9 +83,8 @@ func (r *Reader) initRoot() error {
|
|||||||
// 入参: name 文件名
|
// 入参: name 文件名
|
||||||
// 返回: []byte 文件内容, error 错误信息
|
// 返回: []byte 文件内容, error 错误信息
|
||||||
func (r *Reader) readFile(name string) ([]byte, error) {
|
func (r *Reader) readFile(name string) ([]byte, error) {
|
||||||
name = strings.ReplaceAll(name, "\\", "/")
|
name = cleanPackagePath(name)
|
||||||
name = strings.TrimPrefix(name, "/")
|
if f, ok := r.packageFile(name); ok {
|
||||||
if f, ok := r.fileIndex[name]; ok {
|
|
||||||
return readZipFile(f)
|
return readZipFile(f)
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("file not found: %s", name)
|
return nil, fmt.Errorf("file not found: %s", name)
|
||||||
@@ -88,14 +94,35 @@ func (r *Reader) readFile(name string) ([]byte, error) {
|
|||||||
// 入参: name 文件名
|
// 入参: name 文件名
|
||||||
// 返回: io.ReadCloser 文件流, error 错误信息
|
// 返回: io.ReadCloser 文件流, error 错误信息
|
||||||
func (r *Reader) openFile(name string) (io.ReadCloser, error) {
|
func (r *Reader) openFile(name string) (io.ReadCloser, error) {
|
||||||
name = strings.ReplaceAll(name, "\\", "/")
|
name = cleanPackagePath(name)
|
||||||
name = strings.TrimPrefix(name, "/")
|
if f, ok := r.packageFile(name); ok {
|
||||||
if f, ok := r.fileIndex[name]; ok {
|
|
||||||
return f.Open()
|
return f.Open()
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("file not found: %s", name)
|
return nil, fmt.Errorf("file not found: %s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cleanPackagePath 清理包内文件路径
|
||||||
|
// 入参: name 文件路径
|
||||||
|
// 返回: string 清理后的文件路径
|
||||||
|
func cleanPackagePath(name string) string {
|
||||||
|
name = strings.ReplaceAll(name, "\\", "/")
|
||||||
|
name = strings.TrimPrefix(name, "/")
|
||||||
|
return path.Clean(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// packageFile 获取包内文件
|
||||||
|
// 入参: name 文件路径
|
||||||
|
// 返回: *zip.File 压缩包文件, bool 是否存在
|
||||||
|
func (r *Reader) packageFile(name string) (*zip.File, bool) {
|
||||||
|
if f, ok := r.fileIndex[name]; ok {
|
||||||
|
return f, true
|
||||||
|
}
|
||||||
|
if f, ok := r.fileIndexFold[strings.ToLower(name)]; ok {
|
||||||
|
return f, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
// readZipFile 读取zip文件内容
|
// readZipFile 读取zip文件内容
|
||||||
// 入参: f zip文件对象
|
// 入参: f zip文件对象
|
||||||
// 返回: []byte 文件内容, error 错误信息
|
// 返回: []byte 文件内容, error 错误信息
|
||||||
|
|||||||
+17
-4
@@ -805,8 +805,8 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
if i < len(xs) {
|
if i < len(xs) {
|
||||||
cx = xs[i]
|
cx = xs[i]
|
||||||
} else if i > 0 {
|
} else if i > 0 {
|
||||||
if i-1 < len(dxs) {
|
if dx, ok := textDelta(dxs, i-1); ok {
|
||||||
cx += dxs[i-1]
|
cx += dx
|
||||||
} else if len(dys) == 0 {
|
} else if len(dys) == 0 {
|
||||||
cx += face.TextWidth(str)
|
cx += face.TextWidth(str)
|
||||||
}
|
}
|
||||||
@@ -814,8 +814,8 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
if i < len(ys) {
|
if i < len(ys) {
|
||||||
cy = ys[i]
|
cy = ys[i]
|
||||||
} else if i > 0 {
|
} else if i > 0 {
|
||||||
if i-1 < len(dys) {
|
if dy, ok := textDelta(dys, i-1); ok {
|
||||||
cy += dys[i-1]
|
cy += dy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tx, ty := ctm.Transform(cx, cy)
|
tx, ty := ctm.Transform(cx, cy)
|
||||||
@@ -875,6 +875,19 @@ func (r *Renderer) renderText(ctx *canvas.Context, obj TextObject, pageH float64
|
|||||||
ctx.Pop()
|
ctx.Pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// textDelta 获取文本偏移量
|
||||||
|
// 入参: deltas 偏移量数组, index 偏移量索引
|
||||||
|
// 返回: float64 偏移量, bool 是否存在
|
||||||
|
func textDelta(deltas []float64, index int) (float64, bool) {
|
||||||
|
if len(deltas) == 0 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
if index < len(deltas) {
|
||||||
|
return deltas[index], true
|
||||||
|
}
|
||||||
|
return deltas[len(deltas)-1], true
|
||||||
|
}
|
||||||
|
|
||||||
// hasTextMatrix 判断文本是否需要应用字形变换
|
// hasTextMatrix 判断文本是否需要应用字形变换
|
||||||
// 入参: ctm 变换矩阵
|
// 入参: ctm 变换矩阵
|
||||||
// 返回: bool 是否需要变换
|
// 返回: bool 是否需要变换
|
||||||
|
|||||||
Reference in New Issue
Block a user