diff --git a/app/electron-builder-darwin-arm64.yml b/app/electron-builder-darwin-arm64.yml index 69b8e2136..fcf164d1b 100644 --- a/app/electron-builder-darwin-arm64.yml +++ b/app/electron-builder-darwin-arm64.yml @@ -55,5 +55,8 @@ extraResources: - from: "appearance/themes/daylight" to: "appearance/themes/daylight" filter: "!**/{.DS_Store,custom.css}" + - from: "appearance/fonts" + to: "appearance/fonts" + filter: "!**/{.DS_Store}" - from: "pandoc/pandoc-darwin-amd64.zip" to: "pandoc.zip" diff --git a/app/electron-builder-darwin.yml b/app/electron-builder-darwin.yml index 48373d35d..36265162f 100644 --- a/app/electron-builder-darwin.yml +++ b/app/electron-builder-darwin.yml @@ -55,5 +55,8 @@ extraResources: - from: "appearance/themes/daylight" to: "appearance/themes/daylight" filter: "!**/{.DS_Store,custom.css}" + - from: "appearance/fonts" + to: "appearance/fonts" + filter: "!**/{.DS_Store}" - from: "pandoc/pandoc-darwin-amd64.zip" to: "pandoc.zip" diff --git a/app/electron-builder-linux.yml b/app/electron-builder-linux.yml index 0c4a5d616..f8824082e 100644 --- a/app/electron-builder-linux.yml +++ b/app/electron-builder-linux.yml @@ -50,5 +50,8 @@ extraResources: - from: "appearance/themes/daylight" to: "appearance/themes/daylight" filter: "!**/{.DS_Store,custom.css}" + - from: "appearance/fonts" + to: "appearance/fonts" + filter: "!**/{.DS_Store}" - from: "pandoc/pandoc-linux-amd64.zip" to: "pandoc.zip" \ No newline at end of file diff --git a/app/electron-builder.yml b/app/electron-builder.yml index 73fa87d7e..7fb35c81c 100644 --- a/app/electron-builder.yml +++ b/app/electron-builder.yml @@ -67,5 +67,8 @@ extraResources: - from: "appearance/themes/daylight" to: "appearance/themes/daylight" filter: "!**/{.DS_Store,custom.css}" + - from: "src/assets/fonts" + to: "appearance/fonts" + filter: "!**/{.DS_Store}" - from: "pandoc/pandoc-windows-amd64.zip" to: "pandoc.zip" \ No newline at end of file diff --git a/app/src/assets/fonts/LxgwWenKai-Lite-1.311/LICENSE b/app/src/assets/fonts/LxgwWenKai-Lite-1.311/LICENSE new file mode 100644 index 000000000..ecce74a9e --- /dev/null +++ b/app/src/assets/fonts/LxgwWenKai-Lite-1.311/LICENSE @@ -0,0 +1,94 @@ +Copyright 2021-2023 LXGW (https://github.com/lxgw/LxgwWenKai) +Copyright 2020 The Klee Project Authors (https://github.com/fontworks-fonts/Klee) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. \ No newline at end of file diff --git a/app/src/assets/fonts/LxgwWenKai-Lite-1.311/LXGWWenKaiLite-Regular.ttf b/app/src/assets/fonts/LxgwWenKai-Lite-1.311/LXGWWenKaiLite-Regular.ttf new file mode 100644 index 000000000..6d55e919b Binary files /dev/null and b/app/src/assets/fonts/LxgwWenKai-Lite-1.311/LXGWWenKaiLite-Regular.ttf differ diff --git a/kernel/api/export.go b/kernel/api/export.go index edf88d88c..6b7f248b7 100644 --- a/kernel/api/export.go +++ b/kernel/api/export.go @@ -528,7 +528,8 @@ func processPDF(c *gin.Context) { merge = arg["merge"].(bool) } removeAssets := arg["removeAssets"].(bool) - err := model.ProcessPDF(id, path, merge, removeAssets) + //watermark := arg["watermark"].(bool) + err := model.ProcessPDF(id, path, merge, removeAssets, true) if nil != err { ret.Code = -1 ret.Msg = err.Error() diff --git a/kernel/conf/export.go b/kernel/conf/export.go index b420a266e..0bfbf1962 100644 --- a/kernel/conf/export.go +++ b/kernel/conf/export.go @@ -32,6 +32,8 @@ type Export struct { DocxTemplate string `json:"docxTemplate"` // Docx 导出时模板文件路径 PDFWatermarkStr string `json:"pdfWatermarkStr"` // PDF 导出时水印文本或水印文件路径 PDFWatermarkDesc string `json:"pdfWatermarkDesc"` // PDF 导出时水印位置、大小和样式等 + ImageWatermarkStr string `json:"imageWatermarkStr"` // 图片导出时水印文本或水印文件路径 + ImageWatermarkDesc string `json:"imageWatermarkDesc"` // 图片导出时水印位置、大小和样式等 } func NewExport() *Export { diff --git a/kernel/model/export.go b/kernel/model/export.go index fcf2229c8..0f2cf30ac 100644 --- a/kernel/model/export.go +++ b/kernel/model/export.go @@ -20,6 +20,7 @@ import ( "bytes" "errors" "fmt" + "github.com/88250/pdfcpu/pkg/font" "net/http" "net/url" "os" @@ -781,7 +782,7 @@ func processIFrame(tree *parse.Tree) { } } -func ProcessPDF(id, p string, merge, removeAssets bool) (err error) { +func ProcessPDF(id, p string, merge, removeAssets, watermark bool) (err error) { tree, _ := loadTreeByBlockID(id) if nil == tree { return @@ -810,6 +811,12 @@ func ProcessPDF(id, p string, merge, removeAssets bool) (err error) { return ast.WalkContinue }) + pdfcpu.ConfigPath = "disable" + font.UserFontDir = filepath.Join(util.HomeDir, ".config", "siyuan", "fonts") + if mkdirErr := os.MkdirAll(font.UserFontDir, 0755); nil != mkdirErr { + logging.LogErrorf("mkdir [%s] failed: %s", font.UserFontDir, mkdirErr) + return + } pdfCtx, ctxErr := api.ReadContextFile(p) if nil != ctxErr { logging.LogErrorf("read pdf context failed: %s", ctxErr) @@ -818,7 +825,7 @@ func ProcessPDF(id, p string, merge, removeAssets bool) (err error) { processPDFBookmarks(pdfCtx, headings) processPDFLinkEmbedAssets(pdfCtx, assetDests, removeAssets) - processPDFWatermark(pdfCtx) + processPDFWatermark(pdfCtx, watermark) pdfcpu.VersionStr = "SiYuan v" + util.Ver if writeErr := api.WriteContextFile(pdfCtx, p); nil != writeErr { @@ -828,10 +835,14 @@ func ProcessPDF(id, p string, merge, removeAssets bool) (err error) { return } -func processPDFWatermark(pdfCtx *pdfcpu.Context) { +func processPDFWatermark(pdfCtx *pdfcpu.Context, watermark bool) { // Support adding the watermark on export PDF https://github.com/siyuan-note/siyuan/issues/9961 // https://pdfcpu.io/core/watermark + if !watermark { + return + } + str := Conf.Export.PDFWatermarkStr if "" == str { return @@ -842,9 +853,39 @@ func processPDFWatermark(pdfCtx *pdfcpu.Context) { } desc := Conf.Export.PDFWatermarkDesc - f, e := pdfCtx.ExtractFont(1) - if nil == e { - desc = "fontname:" + f.Name + descParts := strings.Split(desc, ",") + m := map[string]string{} + for _, descPart := range descParts { + kv := strings.Split(descPart, ":") + if 2 != len(kv) { + continue + } + m[kv[0]] = kv[1] + } + if "" == m["fontname"] { + m["fontname"] = "LXGW WenKai Lite" + } + descBuilder := bytes.Buffer{} + for k, v := range m { + descBuilder.WriteString(k) + descBuilder.WriteString(":") + descBuilder.WriteString(v) + descBuilder.WriteString(",") + } + desc = descBuilder.String() + desc = desc[:len(desc)-1] + fontPath := filepath.Join(util.AppearancePath, "fonts", "LxgwWenKai-Lite-1.311", "LXGWWenKaiLite-Regular.ttf") + err := api.InstallFonts([]string{fontPath}) + if nil != err { + logging.LogErrorf("install font [%s] failed: %s", fontPath, err) + } + fonts, err := api.ListFonts() + if nil != err { + logging.LogErrorf("list fonts failed: %s", err) + } else { + for _, f := range fonts { + logging.LogInfof("installed font: %s", f) + } } mode := "text" @@ -859,7 +900,6 @@ func processPDFWatermark(pdfCtx *pdfcpu.Context) { logging.LogInfof("add PDF watermark [mode=%s, str=%s, desc=%s]", mode, str, desc) var wm *pdfcpu.Watermark - var err error switch mode { case "text": wm, err = pdfcpu.ParseTextWatermarkDetails(str, desc, false, pdfcpu.POINTS)