summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEkaitz Zarraga <ekaitz@elenq.tech>2020-03-10 19:50:41 +0100
committerEkaitz Zarraga <ekaitz@elenq.tech>2020-03-10 19:50:41 +0100
commit0db9413cac3f5bba67ddeed129bfdb99d8a2b99a (patch)
tree3cb830dbee5796dc0e4137f7bbaa4d4830ff5af7
parentee634eae16f472c3ab1a69da0b8804d48dd9a793 (diff)
Cover creator code sketch
-rw-r--r--utils/cover/Makefile14
-rw-r--r--utils/cover/README.md4
-rw-r--r--utils/cover/barcode.scm118
-rw-r--r--utils/cover/cover.scm390
4 files changed, 526 insertions, 0 deletions
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 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>")
+(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)))
+
+ )))