From 0db9413cac3f5bba67ddeed129bfdb99d8a2b99a Mon Sep 17 00:00:00 2001
From: Ekaitz Zarraga <ekaitz@elenq.tech>
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

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)))
+
+     )))
-- 
cgit v1.2.3