diff --git a/cmd/seshat/main.go b/cmd/seshat/main.go index 7942b88..f398287 100644 --- a/cmd/seshat/main.go +++ b/cmd/seshat/main.go @@ -52,7 +52,7 @@ func run(c config.Config) error { config.Render(c, pdf, fonts) for _, rule := range c.Rules { fmt.Printf("Running rule %s(%v)\n", rule.Type, rule.Args) - testers.Get(rule.Type)(pdf, fonts, rule.Args) + testers.Get(rule.Type)(pdf, fonts, rule.Features, rule.Args) } if err := pdf.Close(); err != nil { diff --git a/examples/config.yaml b/examples/config.yaml index 6d0afc7..7d20fe6 100644 --- a/examples/config.yaml +++ b/examples/config.yaml @@ -1,12 +1,19 @@ -font: ./font/OTF +font: ./fonts/Fira-Sans output: ./output.pdf rules: + - type: text + features: "sups" + args: + - "testing 3.14 ff ll ii 0O" - type: alphabet - type: grid args: - - 5 - - 5 + - 01a + - type: grid + features: "zero, smcp" + args: + - 01a - type: text args: - "Hello, world!" diff --git a/examples/fonts/Fira-Sans/FiraSans-Black.ttf b/examples/fonts/Fira-Sans/FiraSans-Black.ttf new file mode 100644 index 0000000..113cd3b Binary files /dev/null and b/examples/fonts/Fira-Sans/FiraSans-Black.ttf differ diff --git a/examples/fonts/Fira-Sans/FiraSans-Bold.ttf b/examples/fonts/Fira-Sans/FiraSans-Bold.ttf new file mode 100644 index 0000000..e3593fb Binary files /dev/null and b/examples/fonts/Fira-Sans/FiraSans-Bold.ttf differ diff --git a/examples/fonts/Fira-Sans/FiraSans-ExtraBold.ttf b/examples/fonts/Fira-Sans/FiraSans-ExtraBold.ttf new file mode 100644 index 0000000..83744c1 Binary files /dev/null and b/examples/fonts/Fira-Sans/FiraSans-ExtraBold.ttf differ diff --git a/examples/fonts/Fira-Sans/FiraSans-ExtraLight.ttf b/examples/fonts/Fira-Sans/FiraSans-ExtraLight.ttf new file mode 100644 index 0000000..2d4e331 Binary files /dev/null and b/examples/fonts/Fira-Sans/FiraSans-ExtraLight.ttf differ diff --git a/examples/fonts/Fira-Sans/FiraSans-Light.ttf b/examples/fonts/Fira-Sans/FiraSans-Light.ttf new file mode 100644 index 0000000..663d1de Binary files /dev/null and b/examples/fonts/Fira-Sans/FiraSans-Light.ttf differ diff --git a/examples/fonts/Fira-Sans/FiraSans-Medium.ttf b/examples/fonts/Fira-Sans/FiraSans-Medium.ttf new file mode 100644 index 0000000..001ebe7 Binary files /dev/null and b/examples/fonts/Fira-Sans/FiraSans-Medium.ttf differ diff --git a/examples/fonts/Fira-Sans/FiraSans-Regular.ttf b/examples/fonts/Fira-Sans/FiraSans-Regular.ttf new file mode 100644 index 0000000..6f80647 Binary files /dev/null and b/examples/fonts/Fira-Sans/FiraSans-Regular.ttf differ diff --git a/examples/fonts/Fira-Sans/FiraSans-SemiBold.ttf b/examples/fonts/Fira-Sans/FiraSans-SemiBold.ttf new file mode 100644 index 0000000..0c93b7e Binary files /dev/null and b/examples/fonts/Fira-Sans/FiraSans-SemiBold.ttf differ diff --git a/examples/fonts/Fira-Sans/FiraSans-Thin.ttf b/examples/fonts/Fira-Sans/FiraSans-Thin.ttf new file mode 100644 index 0000000..c925f94 Binary files /dev/null and b/examples/fonts/Fira-Sans/FiraSans-Thin.ttf differ diff --git a/examples/fonts/Fira-Sans/LICENSE b/examples/fonts/Fira-Sans/LICENSE new file mode 100644 index 0000000..0d0213a --- /dev/null +++ b/examples/fonts/Fira-Sans/LICENSE @@ -0,0 +1,93 @@ +Copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. + +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: +https://openfontlicense.org + + +----------------------------------------------------------- +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. diff --git a/examples/fonts/Fira-Sans/README.md b/examples/fonts/Fira-Sans/README.md new file mode 100644 index 0000000..812ff80 --- /dev/null +++ b/examples/fonts/Fira-Sans/README.md @@ -0,0 +1 @@ +https://fonts.google.com/specimen/Fira+Sans diff --git a/examples/font/LinealVariable.ttf b/examples/fonts/Lineal/LinealVariable.ttf similarity index 100% rename from examples/font/LinealVariable.ttf rename to examples/fonts/Lineal/LinealVariable.ttf diff --git a/examples/font/OTF/Lineal-Black.otf b/examples/fonts/Lineal/OTF/Lineal-Black.otf similarity index 100% rename from examples/font/OTF/Lineal-Black.otf rename to examples/fonts/Lineal/OTF/Lineal-Black.otf diff --git a/examples/font/OTF/Lineal-Bold.otf b/examples/fonts/Lineal/OTF/Lineal-Bold.otf similarity index 100% rename from examples/font/OTF/Lineal-Bold.otf rename to examples/fonts/Lineal/OTF/Lineal-Bold.otf diff --git a/examples/font/OTF/Lineal-Heavy.otf b/examples/fonts/Lineal/OTF/Lineal-Heavy.otf similarity index 100% rename from examples/font/OTF/Lineal-Heavy.otf rename to examples/fonts/Lineal/OTF/Lineal-Heavy.otf diff --git a/examples/font/OTF/Lineal-Light.otf b/examples/fonts/Lineal/OTF/Lineal-Light.otf similarity index 100% rename from examples/font/OTF/Lineal-Light.otf rename to examples/fonts/Lineal/OTF/Lineal-Light.otf diff --git a/examples/font/OTF/Lineal-Medium.otf b/examples/fonts/Lineal/OTF/Lineal-Medium.otf similarity index 100% rename from examples/font/OTF/Lineal-Medium.otf rename to examples/fonts/Lineal/OTF/Lineal-Medium.otf diff --git a/examples/font/OTF/Lineal-Regular.otf b/examples/fonts/Lineal/OTF/Lineal-Regular.otf similarity index 100% rename from examples/font/OTF/Lineal-Regular.otf rename to examples/fonts/Lineal/OTF/Lineal-Regular.otf diff --git a/examples/font/OTF/Lineal-Thin.otf b/examples/fonts/Lineal/OTF/Lineal-Thin.otf similarity index 100% rename from examples/font/OTF/Lineal-Thin.otf rename to examples/fonts/Lineal/OTF/Lineal-Thin.otf diff --git a/examples/font/README.md b/examples/fonts/Lineal/README.md similarity index 100% rename from examples/font/README.md rename to examples/fonts/Lineal/README.md diff --git a/examples/font/TTF/Lineal-Black.ttf b/examples/fonts/Lineal/TTF/Lineal-Black.ttf similarity index 100% rename from examples/font/TTF/Lineal-Black.ttf rename to examples/fonts/Lineal/TTF/Lineal-Black.ttf diff --git a/examples/font/TTF/Lineal-Bold.ttf b/examples/fonts/Lineal/TTF/Lineal-Bold.ttf similarity index 100% rename from examples/font/TTF/Lineal-Bold.ttf rename to examples/fonts/Lineal/TTF/Lineal-Bold.ttf diff --git a/examples/font/TTF/Lineal-Heavy.ttf b/examples/fonts/Lineal/TTF/Lineal-Heavy.ttf similarity index 100% rename from examples/font/TTF/Lineal-Heavy.ttf rename to examples/fonts/Lineal/TTF/Lineal-Heavy.ttf diff --git a/examples/font/TTF/Lineal-Light.ttf b/examples/fonts/Lineal/TTF/Lineal-Light.ttf similarity index 100% rename from examples/font/TTF/Lineal-Light.ttf rename to examples/fonts/Lineal/TTF/Lineal-Light.ttf diff --git a/examples/font/TTF/Lineal-Medium.ttf b/examples/fonts/Lineal/TTF/Lineal-Medium.ttf similarity index 100% rename from examples/font/TTF/Lineal-Medium.ttf rename to examples/fonts/Lineal/TTF/Lineal-Medium.ttf diff --git a/examples/font/TTF/Lineal-Regular.ttf b/examples/fonts/Lineal/TTF/Lineal-Regular.ttf similarity index 100% rename from examples/font/TTF/Lineal-Regular.ttf rename to examples/fonts/Lineal/TTF/Lineal-Regular.ttf diff --git a/examples/font/TTF/Lineal-Thin.ttf b/examples/fonts/Lineal/TTF/Lineal-Thin.ttf similarity index 100% rename from examples/font/TTF/Lineal-Thin.ttf rename to examples/fonts/Lineal/TTF/Lineal-Thin.ttf diff --git a/go.mod b/go.mod index b75731c..0ec7b24 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/nobe4/seshat go 1.23.2 require ( - github.com/tdewolff/canvas v0.0.0-20241004114307-d601972c0f7c + github.com/tdewolff/canvas v0.0.0-20241016131410-e8e42bbd1fc2 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index 8e9c046..c932b3e 100644 --- a/go.sum +++ b/go.sum @@ -30,8 +30,8 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF0 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/tdewolff/canvas v0.0.0-20241004114307-d601972c0f7c h1:t46xGyVm4G/XMPYRWeAY2jyC7amv2qHzP0rFJQRUQ6E= -github.com/tdewolff/canvas v0.0.0-20241004114307-d601972c0f7c/go.mod h1:1bMKQWV4mWh4GtLPMBzMaY2Z8E8zqolCi4ceTxStVFE= +github.com/tdewolff/canvas v0.0.0-20241016131410-e8e42bbd1fc2 h1:R59L76gYJW3UxGJDPuH8Bk08lzg6inwjcM6gHShmrxo= +github.com/tdewolff/canvas v0.0.0-20241016131410-e8e42bbd1fc2/go.mod h1:1bMKQWV4mWh4GtLPMBzMaY2Z8E8zqolCi4ceTxStVFE= github.com/tdewolff/font v0.0.0-20240728193914-9dc6e3441d03 h1:8gZpGeUF+0bYYNDJCWXG64YH4WdSFZDFoWp1RKil1Qg= github.com/tdewolff/font v0.0.0-20240728193914-9dc6e3441d03/go.mod h1:wiFLtNiPVz+WWkn1CekBWgSEEV5PTR7qae3wKbU0xd0= github.com/tdewolff/minify/v2 v2.20.5 h1:IbJpmpAFESnuJPdsvFBJWsDcXE5qHsmaVQrRqhOI9sI= diff --git a/internal/config/config.go b/internal/config/config.go index 10ae3d5..3373b75 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -21,10 +21,12 @@ type Config struct { } type Rule struct { - Type string `yaml:"type"` - Args []string `yaml:"args"` + Type string `yaml:"type"` + Features string `yaml:"features"` + Args []string `yaml:"args"` } +// TODO: default config should come from ./example/config.yaml var DefaultConfig = Config{ Font: ".", Output: "output.pdf", diff --git a/internal/font/loader.go b/internal/font/loader.go index 78f6b53..7f1baf0 100644 --- a/internal/font/loader.go +++ b/internal/font/loader.go @@ -21,13 +21,15 @@ type Fonts []Font var ( fontOrder = map[string]int{ - "thin": 0, - "light": 1, - "regular": 2, - "medium": 3, - "bold": 4, - "black": 5, - "heavy": 6, + "thin": 0, + "extralight": 1, + "light": 2, + "regular": 3, + "medium": 4, + "extrabold": 5, + "bold": 6, + "black": 7, + "heavy": 8, } ) diff --git a/internal/testers/alphabet/alphabet.go b/internal/testers/alphabet/alphabet.go index 7e44441..083804a 100644 --- a/internal/testers/alphabet/alphabet.go +++ b/internal/testers/alphabet/alphabet.go @@ -11,7 +11,7 @@ const ( alphabet = `a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9` ) -func Test(pdf *pdf.PDF, fonts font.Fonts, _ []string) { +func Test(pdf *pdf.PDF, fonts font.Fonts, features string, _ []string) { width, height := pdf.Size() for _, font := range fonts { @@ -22,6 +22,7 @@ func Test(pdf *pdf.PDF, fonts font.Fonts, _ []string) { size := 30.0 for y, i := height, 30; y > 0 && i > 0; i-- { face := font.Font.Face(size, canvas.Black) + face.Font.SetFeatures(features) txt := canvas.NewTextBox(face, alphabet, width, 0.0, canvas.Left, canvas.Top, 0.0, 0.0) ctx.DrawText(0, y, txt) diff --git a/internal/testers/grid/grid.go b/internal/testers/grid/grid.go index c8f85fe..854df02 100644 --- a/internal/testers/grid/grid.go +++ b/internal/testers/grid/grid.go @@ -17,17 +17,17 @@ type Letter struct { y float64 } -func Test(pdf *pdf.PDF, fonts font.Fonts, letters []string) { +func Test(pdf *pdf.PDF, fonts font.Fonts, features string, letters []string) { if len(letters) == 0 { letters = strings.Split("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "") } for _, l := range letters { - letter(pdf, fonts, string(l)) + letter(pdf, fonts, features, string(l)) } } -func letter(pdf *pdf.PDF, fonts font.Fonts, letter string) { +func letter(pdf *pdf.PDF, fonts font.Fonts, features, letter string) { letters := make([]Letter, 0) size := 100.0 @@ -35,6 +35,8 @@ func letter(pdf *pdf.PDF, fonts font.Fonts, letter string) { for i, font := range fonts { face := font.Font.Face(size, canvas.Black) + face.Font.SetFeatures(features) + txt := canvas.NewTextLine(face, letter, canvas.Left) letters = append(letters, Letter{ diff --git a/internal/testers/lorem/lorem.go b/internal/testers/lorem/lorem.go index 70051be..465a448 100644 --- a/internal/testers/lorem/lorem.go +++ b/internal/testers/lorem/lorem.go @@ -10,7 +10,7 @@ const ( lorem = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam in dui mauris. Vivamus hendrerit arcu sed` ) -func Test(pdf *pdf.PDF, fonts font.Fonts, _ []string) { +func Test(pdf *pdf.PDF, fonts font.Fonts, features string, _ []string) { width, height := pdf.Size() for _, font := range fonts { @@ -20,6 +20,7 @@ func Test(pdf *pdf.PDF, fonts font.Fonts, _ []string) { size := 30.0 for y, i := height, 30; y > 0 && i > 0; i-- { face := font.Font.Face(size, canvas.Black) + face.Font.SetFeatures(features) txt := canvas.NewTextBox(face, lorem, width, 0.0, canvas.Left, canvas.Top, 0.0, 0.0) ctx.DrawText(0, y, txt) diff --git a/internal/testers/testers.go b/internal/testers/testers.go index 25b2eb7..d30b6c7 100644 --- a/internal/testers/testers.go +++ b/internal/testers/testers.go @@ -9,7 +9,7 @@ import ( "github.com/tdewolff/canvas/renderers/pdf" ) -type TestFn func(*pdf.PDF, font.Fonts, []string) +type TestFn func(*pdf.PDF, font.Fonts, string, []string) func Get(name string) TestFn { switch name { diff --git a/internal/testers/text/text.go b/internal/testers/text/text.go index a43cb9d..5d10c22 100644 --- a/internal/testers/text/text.go +++ b/internal/testers/text/text.go @@ -6,7 +6,7 @@ import ( "github.com/tdewolff/canvas/renderers/pdf" ) -func Test(pdf *pdf.PDF, fonts font.Fonts, inputs []string) { +func Test(pdf *pdf.PDF, fonts font.Fonts, features string, inputs []string) { width, height := pdf.Size() pdf.NewPage(width, height) @@ -19,6 +19,7 @@ func Test(pdf *pdf.PDF, fonts font.Fonts, inputs []string) { size := 30.0 face := font.Font.Face(size, canvas.Black) + face.Font.SetFeatures(features) txt := canvas.NewTextBox(face, input, width, 0.0, canvas.Left, canvas.Top, 0.0, 0.0) ctx.DrawText(0, y, txt)