From 0db9413cac3f5bba67ddeed129bfdb99d8a2b99a Mon Sep 17 00:00:00 2001 From: Ekaitz Zarraga Date: Tue, 10 Mar 2020 19:50:41 +0100 Subject: Cover creator code sketch --- utils/cover/Makefile | 14 ++ utils/cover/README.md | 4 + utils/cover/barcode.scm | 118 +++++++++++++++ utils/cover/cover.scm | 390 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 526 insertions(+) create mode 100644 utils/cover/Makefile create mode 100644 utils/cover/README.md create mode 100644 utils/cover/barcode.scm create mode 100644 utils/cover/cover.scm (limited to 'utils') diff --git a/utils/cover/Makefile b/utils/cover/Makefile new file mode 100644 index 0000000..2fddab0 --- /dev/null +++ b/utils/cover/Makefile @@ -0,0 +1,14 @@ +TARGET_PDF = cover.pdf + +.PHONY: pdf +pdf: $(TARGET_PDF) + +$(TARGET_PDF): cover.svg + inkscape $^ --export-pdf=$@ + +cover.svg: cover.scm # Cover data too + chibi-scheme cover.scm > cover.svg + +.PHONY: clean +clean: + rm $(TARGET_PDF) cover.svg diff --git a/utils/cover/README.md b/utils/cover/README.md new file mode 100644 index 0000000..0f24288 --- /dev/null +++ b/utils/cover/README.md @@ -0,0 +1,4 @@ +# SVG COVER CREATOR + +Cover creator makes use of Inkscape and Chibi-Scheme's SXML capabilities to +create the final PDF's covers for physical books. diff --git a/utils/cover/barcode.scm b/utils/cover/barcode.scm new file mode 100644 index 0000000..85f28c2 --- /dev/null +++ b/utils/cover/barcode.scm @@ -0,0 +1,118 @@ +(import (chibi) + (chibi sxml) + (srfi 1)) + + +; R ENCODING +(define R (list (list #t #t #t #f #f #t #f) + (list #t #t #f #f #t #t #f) + (list #t #t #f #t #t #f #f) + (list #t #f #f #f #f #t #f) + (list #t #f #t #t #t #f #f) + (list #t #f #f #t #t #t #f) + (list #t #f #t #f #f #f #f) + (list #t #f #f #f #t #f #f) + (list #t #f #f #t #f #f #f) + (list #t #t #t #f #t #f #f))) + +; G ENCODING +(define G + (map reverse R)) + +; L ENCODING +(define L + (map (lambda (x) (map not x)) R)) + +; END +(define E '(#t #f #t)) + +; SEPARATOR +(define S '(#f #t #f #t #f)) + +(define (encode encoding num) + (case encoding + ('E E) + ('S S) + ('R (list-ref R num)) + ('L (list-ref L num)) + ('G (list-ref G num)))) + + +(define order '((E L L L L L L S R R R R R R E) + (E L L G L G G S R R R R R R E) + (E L L G G L G S R R R R R R E) + (E L L G G G L S R R R R R R E) + (E L G L L G G S R R R R R R E) + (E L G G L L G S R R R R R R E) + (E L G G G L L S R R R R R R E) + (E L G L G L G S R R R R R R E) + (E L G L G G L S R R R R R R E) + (E L G G L G L S R R R R R R E))) + +(define (barcode number) + "Get number in decima string" + (let* ((nums (string->list number)) + + (digits (map (lambda (x) (string->number (list->string (list x)))) + nums)) + + (digit-1 (car digits)) + (digits-rest (cdr digits)) + (block-1 (take digits-rest 6)) + (block-2 (drop digits-rest 6)) + (sep '(#f))) + + (concatenate (map (lambda (x y) (encode x y)) + (list-ref order digit-1) + (concatenate (list sep + block-1 + sep + block-2 + sep)))))) + + + + +(define (barcode-sxml code x y scale) + (let* ((border 0.1) + (text-size border) + (codewidth 1) + (width (+ border codewidth)) + (colwidth (exact->inexact (/ codewidth 95))) + (height 0.6) + (viewBox (string-append "0 0 " + (number->string width) + " " + (number->string height))) + (encoded (barcode code))) + `(g + (@ (transform ,(string-append "translate(" (number->string x) "," (number->string y) ")" + "scale(" (number->string scale) ")"))) + + ,(map + (lambda (render pos) + `(rect (@ (x ,(+ border (* pos colwidth))) + (y 0) + (width ,(exact->inexact colwidth)) + (height ,(if + (find (lambda (x) (= x pos)) + '(0 1 2 94 93 92 45 46 47 48 49)) + height + (- height border))) + (style ,(if render "fill: black" "fill: white"))))) + encoded + (iota (length encoded))) + + ,(map + (lambda (char pos) + `(text (@ (style ,(string-append "font-size: " (number->string text-size) ";" + "text-anchor: middle")) + (x ,(cond ((= 0 pos) (* 3.5 colwidth)) + ((<= 1 pos 6) (+ border (* (+ 3 (* (- pos 0.5) 7)) colwidth))) + ((< 6 pos) (+ border (* (+ 3 5 (* (- pos 0.5) 7)) colwidth))))) + (y ,height)) + ,(list->string (list char)))) + (string->list code) + (iota (string-length code)))))) + +#;(display (barcode-svg "9780201379624")) diff --git a/utils/cover/cover.scm b/utils/cover/cover.scm new file mode 100644 index 0000000..2678986 --- /dev/null +++ b/utils/cover/cover.scm @@ -0,0 +1,390 @@ +(import (scheme base) + (scheme char) + (chibi) + (chibi string) + (chibi sxml) + (srfi 1)) + +(include "barcode.scm") +; GUILE +#;(use-modules (sxml simple) + (srfi srfi-1)) + +;; CONTENTS +(define isbn "9780201379624") +(define book-title "Qué es la informática") +(define book-title-before "Qué es la") +(define book-title-word "Informática") +(define book-title-after "") +(define book-subject "Informática") +(define book-authors '("Giacomo Tesio" "Ekaitz Zarraga")) +(define book-summary "Hola,\n\nSoy Ekaitz\nZarragahola hola hola hola hola hola + hola hola hola hola hola hola hola hola hola hola hola + hola hola hola hola hola hola hola hola hola hola hola + hola hola hola hola hola hola hola hola hola hola hola + hola hola hola hola hola hola hola hola hola hola hola + hola hola hola hola hola hola hola hola hola hola hola + hola hola hola hola hola hola hola hola hola hola hola + hola hola hola hola hola hola hola hola hola hola hola + hola hola hola hola hola hola hola ") +(define company-info "ElenQ Technology is a project that... blabla bla bla + blablabla blablablabla blablabla") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; UTILS ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(define num number->string) +(define (mm x) ; add mm mark + (string-append (num x) "mm")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; DEFINITIONS ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; SIZE +; Take spine from the outside because it's related to the amount of pages +(define spine-width 20) ;mm +(define spine-title-margin-min (* 0.1 spine-width)) +(define spine-title-max-size 10) +(define spine-title-size + (let ((size (- spine-width (* 2 spine-title-margin-min)))) + (if (> size spine-title-max-size) + spine-title-max-size + size))) + +;B5 Paper size +(define page-height 250) ;mm +(define page-width 176) ;mm +(define margin 3) ;mm + +(define text-size (exact->inexact (/ page-height 70))); mm +(define subject-size (* 1.5 text-size)); mm +(define authors-size (* 2 text-size)) +(define title-size (* 2.5 text-size)); mm +(define main-title-size ; mm + (let ((size (exact->inexact + (* 2.1 + (/ page-width + (length (string->list book-title-word))))))) + (if (< (/ page-height 4) size) + (exact->inexact (/ page-height 4)) + size))) + +(define width (+ (* 2 margin) (* 2 page-width) spine-width)) ;mm +(define height (+ (* 2 margin) page-height)) ;mm +(define viewBox (string-append "0 0 " + (num width) + " " + (num height))) +; INFO: Setting viewbox and size to the same it makes the measurements real +; world ones, in this case millimeters +; Read more: https://mpetroff.net/2013/08/analysis-of-svg-units/ + +(define (elenq-logo sub size x y) ; 10 x 4mm + `(g (@ (id "elenq-logo") + (transform ,(string-append "translate(" (num x) "," (num y) ")" "scale(" (num size) ")"))) + (g (@ (transform "scale(0.1667)")) + (text (@ (x 0) + (y 0) + (style "font-size: 30; line-height: 1.25; font-family: armata; stroke: none; text-anchor: middle")) + "ElenQ") + (text (@ (x 0) + (y 8) + (style "font-size: 10; line-height: 1.25; font-family: armata; stroke: none; text-anchor: middle;")) + ,sub)))) +;(define elenq-technology (elenq-logo "TECHNOLOGY" 1 0 0)) +;(define elenq-publishing (elenq-logo "PUBLISHING" 1 0 0)) + +(define style + (string-append " + .margin-mark { + stroke-width: 0.1; + stroke-linecap: butt; + stroke: red; + } + .title-back { + font-family: 'Pathway Gothic One'; + font-size: "(num title-size)"; + fill: white; + } + .title-spine { + font-family: 'Pathway Gothic One'; + font-size: "(num spine-title-size)"; + dominant-baseline: mathematical; + fill: black; + } + .authors-spine { + font-family: 'Lato'; + font-size: "(num text-size)"; + dominant-baseline: mathematical; + text-anchor: end; + } + #black-part { + fill: black; + } + .text-elenq{ + font-family:Lato; + -inkscape-font-specification:'Lato Light Italic'; + font-style: italic; + font-weight: 300; + fill: black; + font-size: "(num text-size)"; + text-align: justify; + } + .text-summary { + font-family:Lato; + font-size: "(num text-size)"; + fill: white; + text-align: justify; + } + rect.subject{ + fill: black; + } + text.subject{ + fill: white; + font-size: "(num subject-size)"; + -inkscape-font-specification:'Lato Light'; + font-family:Lato; + font-weight: 300; + } + .main-title { + font-size: "(num main-title-size)"; + font-family: 'Pathway Gothic One'; + text-anchor: middle; + } + .main-title-before { + font-size: "(num (* 1.5 title-size))"; + -inkscape-font-specification:'Lato Light'; + font-family:Lato; + font-weight:300; + font-style:normal; + font-stretch:normal; + font-variant:normal; + } + .main-title-after { + font-size: "(num (* 1 title-size))"; + -inkscape-font-specification:'Lato LightItalic'; + font-family:Lato; + font-weight:300; + font-style:italic; + font-stretch:normal; + font-variant:normal; + text-anchor: end; + } + .author { + font-size: "(num authors-size)"; + font-family:Lato; + font-style:normal; + font-stretch:normal; + font-variant:normal; + text-anchor: end; + } + ")) + +; Text area, Inkscape-only svg parameter +(define (textArea text class x y w h) + `(flowRoot + (@ (class ,class)) + (flowRegion + (rect (@ (width ,w) + (height ,h) + (x ,x) + (y ,y)))) + ,(map (lambda (p) + `(flowPara ,p)) + + (reverse + (fold + (lambda (s acc) + (if (string=? s "") + (cons "" acc) + (let* ((prev (car acc)) + (val (string-append prev + (if (string=? "" prev) + "" " ") + s))) + (cons val (cdr acc))))) + (list "") + (string-split + text + #\newline)))))) + +(display "") +(display (sxml->xml + `(svg + (@ (width ,(mm width)) + (height ,(mm height)) + (viewBox ,viewBox)) + (defs + (style ,style)) + + + ; BLACK BACKGROUND FOR SUMMARY + (g (@ (transform ,(string-append + ; TODO extender lo negro en el margen + "translate("(num margin)"," (num (+ margin (* 0.05 page-height))) ") + scale(" (num (* 0.95 page-width)) ")"))) + (path (@ (id "black-part") + (d "M 1.00, 0.10 L 0.30, 0.00 L 0.00, 0.16 L 0.00, 0.67 L 0.45, 0.76 L 0.97, 0.67 Z")))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; CUTTING MARKS ;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + ,(map (lambda (posx posy rot) + `(g (@ (id ,(string-append "marks-" + (num posx) + "-" + (num posy))) + (transform ,rot)) + (line (@ + (x1 ,(+ posx)) + (y1 ,(+ posy margin)) + (x2 ,(+ posx (* 0.6 margin))) + (y2 ,(+ posy margin)) + (class "margin-mark"))) + (line (@ + (x1 ,(+ posx margin)) + (y1 ,(+ posy)) + (x2 ,(+ posx margin)) + (y2 ,(+ posy (* 0.6 margin))) + (class "margin-mark"))))) + + (list 0 0 width width) + (list 0 height 0 height) + (list "rotate(0,0,0)" + (string-append "rotate(-90, 0," (num height) ")") + (string-append "rotate(-270," (num width) ", 0)") + (string-append "rotate(-180," (num width) "," (num height) ")"))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; BACK SIDE ;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + ; TITLE + BOOK SUMMARY + ,(textArea + (string-upcase book-title) + "title-back" + (+ margin (* 0.15 page-width)) + (- (+ margin (* page-height 0.25)) 15) + (* 0.7 page-width) + (* 0.25 page-height)) + + + ,(textArea book-summary + "text-summary" + (+ margin (* 0.15 page-width)) + (+ margin (* page-height 0.25)) + (* 0.7 page-width) + (* 0.25 page-height)) + + + ; LOGO + ELENQ SUMMARY + ,(elenq-logo "TECHNOLOGY" + 3 + (* (+ (+ margin (* 0.5 page-width)) + (+ margin (* 0.5 page-width) + (- (* 0.5 page-width) (* 0.1 page-width)))) 0.5) + (+ margin (* 0.70 page-height) -10)) + ,(textArea company-info + "text-elenq" + (+ margin (* 0.5 page-width)) + (+ margin (* 0.70 page-height)) + (- (* 0.5 page-width) (* 0.1 page-width)) + (- (* 0.25 page-height) (* 0.1 page-height))) + + + ; BARCODE + ,(barcode-sxml isbn + (+ margin (* 0.1 page-width)) + (+ margin (* 0.75 page-height)) + (* 0.25 page-width)) + + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; SPINE ;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ,(let ((x (+ margin page-width)) + (y height) + (width (+ margin margin page-height)) + (height spine-width)) + `(g (@ (transform + ,(string-append "translate(" (num x) "," (num y) ") rotate (-90)"))) + (rect (@ (height ,height) + (width ,width) + (style "fill: white;"))) + + (text (@ (class "title-spine") + (x ,(* 0.2 width)) + (y ,(* 0.5 spine-width)) + (width ,(* 0.3 width)) + (height ,spine-title-size)) + ,book-title) + (text (@ (class "authors-spine") + (x ,(* 0.9 width)) + (y ,(* 0.5 spine-width)) + (width ,(* 0.3 width)) + (height ,spine-title-size)) + ,(string-join book-authors ", ")))) + + ,(elenq-logo "PUBLISHING" + (* spine-width 0.1 0.75) + (+ margin page-width (* 0.5 spine-width)) + (+ margin (* 0.95 page-height))) + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; FRONT SIDE ;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ,(let* ((win (* 0.35 page-width)) + (w (+ win margin)) + (h (* 1.5 subject-size)) + (x (- width margin win)) + (y (+ margin (* 0.15 page-height)))) + `(g + (rect (@ (class "subject") + (x ,x) + (y ,y) + (width ,w) + (height ,h))) + + (text + (@ (class "subject") + (x ,(+ x (* 0.10 w))) + (y ,(+ y (* 0.75 h))) + (w ,w) + (h ,h)) + ,book-subject))) + + (text (@ (class "main-title-before") + (x ,(exact->inexact (- width + (- page-width (/ page-width 8)) + margin))) + (y ,(+ margin (* 0.30 page-height)))) + ,book-title-before) + (text (@ (class "main-title") + (x ,(exact->inexact (- width (/ page-width 2) margin))) + (y ,(+ main-title-size margin (* 0.30 page-height)))) + ,(string-upcase book-title-word)) + + + ; TODO PENSAR SI QUITAR ESTO + (text (@ (class "main-title-after") + (x ,(exact->inexact (- width (/ page-width 8) margin))) + (y ,(+ main-title-size margin (* 0.37 page-height)))) + "Subtítulo que puede ser una frase resumen") + + ,(map (lambda (author pos) + `(text (@ (class "author") + (x ,(exact->inexact (- width (/ page-width 8) margin))) + (y ,(+ main-title-size + margin + (* 0.37 page-height) + (* pos (* 1.5 authors-size))))) + ,author)) + book-authors + (iota (length book-authors))) + + ,(elenq-logo "PUBLISHING" + 3 + (exact->inexact (- width (/ page-width 2) margin)) + (+ margin (* 0.95 page-height))) + + ))) -- cgit v1.2.3