From: Marc Battyani
Subject: cl-typesetting saturday night news
Date: 
Message-ID: <blnhqq$b45@library1.airnews.net>
New in cl-typesetting:

Math mode!
Ok it's only a basic one for now but the infrastructure is here.
I didn't wanted to do a math mode because I though it would be a big
challenge. But in fact in Common Lisp in a Common Lisp typesetting system,
it's deceptively too easy. The most annoying problem is that I will have to
import the TeX Math fonts to achieve a decent result. It would also be cool
if somebody could write a TeX Math syntax parser... So far the Math mode take
40 lines of Lisp !!! BTW by using user drawn boxes or custom boxes, the
typesetting system is open to alternative Math modes like Kenny's one (If he
survives the ILC Talk...;-)

Added superscripts, subscripts and baseline offset.

cl-typesetting is now used in production:
Last week I couldn't work a lot on cl-typesetting as I money making work has
a higher priority. In particular when you have to deliver! But I worked with
cl-typesetting. So now it is in production in a rather critical intranet web
application, generating lots of complex reports.

As usual, the new always fancier example is here:
http://www.fractalconcept.com/ex.pdf

Marc

The full source of the example:

(defparameter *par1*
  "Lisp is a family of...")

(defparameter *par2*
  "MacLisp improved on....")

(defun draw-block (content x y dx dy rotation &optional (v-align :top))
  (pdf:with-saved-state
    (pdf:translate x y)
    (pdf:rotate rotation)
    (pdf:set-gray-fill 1)
    (pdf:basic-rect -5 0 (+ dx 10) (- dy))
    (pdf:fill-and-stroke)
    (pdf:set-gray-fill 0)
    (let ((box (make-filled-vbox content dx dy v-align)))
      (stroke box 0 0))))

;; example of extension

(defclass rotated-char-box (soft-box h-mode-mixin)
  ((boxed-char :accessor boxed-char :initarg :boxed-char)
   (rotation :accessor rotation :initarg :rotation)))

(defun put-rotated-char-string (string)
  (loop for char across string
 do (add-box (make-instance 'rotated-char-box :dx *font-size*
       :dy *font-size* :boxed-char char :baseline (* *font-size* 0.8)
       :rotation (- (random 120) 60)))))

(defmethod stroke ((box rotated-char-box) x y)
  (let ((dx (dx box))(dy (dy box))
 (width (pdf:get-char-width (boxed-char box) *font* *font-size*)))
    (pdf:with-saved-state
      (pdf:translate (+ x (* dx 0.5)) (+ y (* dy 0.3)))
      (pdf:set-line-width 0.5)
      (pdf:set-gray-fill 0.8)
      (pdf:circle 0 0 (* dx 0.45))
      (pdf:fill-and-stroke)
      (pdf:set-gray-fill 0)
      (pdf:rotate (rotation box))
      (pdf:in-text-mode
       (pdf:move-text (* -0.5 width)(* -0.18 *font-size*))
       (pdf:set-font *font* (* *font-size* 0.8))
       (pdf:show-text (make-string 1 :initial-element (boxed-char box)))))))

;; a draw function for the functional rule...

(defun draw-wavelet-rule (box x0 y0)
  (let ((dx/2 (* (dx box) 0.5))
 (dy/2 (* (dy box) 0.5)))
    (pdf:with-saved-state
      (pdf:translate (+ x0 dx/2) (- y0 dy/2))
      (pdf:set-line-width 1)
      (pdf:set-color-stroke (color box))
      (pdf:move-to (- dx/2) 0)
      (loop for x from (- dx/2) by 0.2
     for y = (* dy/2 (cos (* x 0.8)) (exp (* x x -0.006)))
     while (< x dx/2)
     do (pdf:line-to x y))
      (pdf:stroke))))

;; stupid user-drawn box

(defun user-drawn-demo (box x y)
  (draw-block (compile-text ()
       (paragraph (:h-align :justified :top-margin 5 :first-line-indent 10
       :font "Times-Italic" :font-size 6.5)
           *par1*))
       x (- y (dy box)) (- (dy box) 10) (dx box) 90))

;; a chart (I will have to change this in cl-pdf: it's a real mess!)

(defun draw-pie (box x y)
  (pdf:draw-object (make-instance
      'pdf:pie-chart :x (+ x 30) :y (- y 100) :width 90 :height 90
      :serie '(12 23 65 33)
      :labels&colors
      '(("Winter" (1.0 0.0 0.0))
        ("Spring" (0.0 1.0 0.0))
        ("Summer" (0.0 0.0 1.0))
        ("Autumn" (0.0 1.0 1.0))))))

;;example document

(defun ex (&optional (file #P"/tmp/ex.pdf"))
  (pdf:with-document ()
    (pdf:with-page ()
      (pdf:with-outline-level ("Example" (pdf:register-page-reference))
 (pdf:set-line-width 0.1)
 (let ((content
        (compile-text ()
      (paragraph (:h-align :centered :font "Helvetica-Bold" :font-size 30
:color '(0.0 0 0.8))
       "cl-typesetting" :eol
       (vspace 2)
       (hrule :dy 1)
       (with-style (:font "Times-Italic" :font-size 13)
         "The cool Common Lisp typesetting system"))
   (paragraph (:h-align :justified :top-margin 10 :first-line-indent 10
          :font "Times-Italic" :font-size 10)
         "This typesetting system's goal is to be an alternative to the TeX
typesetting system. It is written in Common Lisp and uses cl-pdf as its
backend. This will enable it to be powerful, extensible and fast. Though it
is not considered very difficult, it is already better than Word...")
   (paragraph (:h-align :centered :font "Helvetica-BoldOblique" :font-size 20
:color '(1.0 0 0))
       "Now in Color!")
   (paragraph (:h-align :centered :font "Times-Italic" :font-size 12 :color
'(0.0 0.6 0.3))
       "With user defined "
       (put-rotated-char-string "extensions") :eol
       (with-style (:font "Times-Italic" :font-size 11)
         "Support for images and functional rules" :eol
         (image :file #P"/tmp/banner.jpg" :dx 100 :dy 20)))
   (hrule :dy 15 :stroke-fn 'draw-wavelet-rule)
   (vspace 3)
   (table (:col-widths '(60 80 80) :border 0.5 :background-color '(1 1 0.8)
         :cell-padding 1 :padding 2)
   (row ()
        (cell (:background-color '(0.8 1 0.8) :col-span 3)
       (paragraph (:h-align :centered :font "Times-Italic" :font-size 12)
      "Title with a col-span of 3")))
   (row ()
        (cell (:background-color '(0.8 0.8 0.8))
       (paragraph (:h-align :left :font "Times-Italic" :font-size 9)
      "Left aligned"))
        (cell (:background-color '(0.8 0.8 0.8))
       (paragraph (:h-align :centered :font "Times-Roman" :font-size 9)
      "Centered cell content"))
        (cell (:background-color '(0.8 0.8 0.8))
       (paragraph (:h-align :right :font "Times-Bold" :font-size 9)
      "Right cell content")))
   (row ()
        (cell ()(paragraph (:h-align :left :font "Times-Italic" :font-size 9)
      "This cell content should take three lines."))
        (cell (:background-color '(1 1 1))
       (paragraph (:h-align :centered :font "Times-Italic" :font-size 9)
      "A jpeg "
      (image :file #P"/tmp/fractal.jpg" :dx 15 :dy 15 :inline t
             :offset 9)
      " in the text"))
        (cell ()(paragraph (:h-align :left :font "Times-Italic" :font-size
11)
      (put-rotated-char-string "common lisp is cool"))))
   (row ()
        (cell ()(paragraph (:h-align :left :font "Times-Italic" :font-size 9)
      "An example of table inside a cell"))
        (cell (:background-color '(1 1 1))
       (table (:col-widths '(14 14 21) :border 0.2
        :background-color '(0.4 0.4 0.8))
         (row () (cell () "12")(cell () "34")(cell () "567"))
         (row () (cell () "ab")(cell () "cd")(cell () "efg"))))
        (cell ()(paragraph (:h-align :left :font "Times-Italic" :font-size 9)
      "You can nest as many tables as you want, like you do in HTML."))))
   (paragraph (:h-align :justified :top-margin 5 :first-line-indent 10 :color
'(0 0 0)
          :font "Times-Roman" :font-size 10)
       *par1*)
   (user-drawn-box :dx 210 :dy 100 :stroke-fn 'user-drawn-demo) :eol
   (paragraph (:h-align :justified :top-margin 9 :first-line-indent 10
          :left-margin 20 :right-margin 20 :font "Helvetica" :font-size 9)
       *par2*)
   (paragraph (:h-align :justified :top-margin 9 :font "Helvetica-Oblique"
          :font-size 9 :first-line-indent 20)
      *par1*)
   (user-drawn-box :dx 240 :dy 100 :stroke-fn 'draw-pie) :eol
   (paragraph (:h-align :centered :font "Times-Italic" :font-size 8)
       "An example of cl-pdf pie chart inserted.")
   (paragraph (:h-align :justified :top-margin 9 :font "Helvetica-Oblique"
:font-size 9
          :left-margin 20 :right-margin 20)
       *par2*)
   (paragraph (:h-align :centered :top-margin 10 :font "Times-Bold"
:font-size 20)
       "Kerning test" :eol
       (with-style (:font "Helvetica" :font-size 40 :left-margin 20
:right-margin 20)
         "Yes, AWAY"))
   (paragraph (:h-align :centered :top-margin 10 :font "Times-Italic"
          :font-size 16 :color '(0 0 0))
       (with-style (:font "Times-Bold" :font-size 20)
         "Basic Math Mode Test" :eol)
       (vspace 5)
       (display-formula ()
        "E"(math-super-and-sub-script () ("n+1") ("k,m"))"="
        (fraction ()
           ("x"(with-superscript () "2")"+x-1")
           ("F(x)+b-3"))
        "-e"(with-superscript () "-x"(with-superscript () "2")))
       (vspace 5)
       (with-style (:font "Times-Roman" :font-size 10)
         "As you can see, the + and the = are not properly aligned because of
the lack of a real math font. You can also note that the E subscript needs an
italic correction."))
   (paragraph (:h-align :centered :top-margin 20 :font "Helvetica"
          :font-size 40 :color '(0.8 0 0))
       "Warning!" :eol
       (with-style (:font "Times-Italic" :font-size 12)
         "This test pdf file has been made with an early version 0.4 of
cl-typesetting. A lot of basic features, like a correct hyphenation, are
still missing..." :eol
         (vspace 10)
         "Marc Battyani"))
   :vfill
   (hrule :dy 20 :stroke-fn 'draw-wavelet-rule :color '(0.8 0 0))
   :vfill
   (paragraph (:h-align :centered :font "Helvetica-Oblique" :font-size 8)
       "This project needs contributors. So if you are interested contact "
       (with-style (:font "Times-Italic" :font-size 9)
         ··············@fractalconcept.com") "."
       ))))
   (draw-block content 40 800 250 380 5)
   (draw-block content 50 425 250 380 -5)
   (draw-block content 330 800 250 380 -2)
   (draw-block content 310 400 250 380 0 :justified))))
    (pdf:write-document file)))

From: Alan Crowe
Subject: Re: cl-typesetting saturday night news
Date: 
Message-ID: <863ce8dmr9.fsf@cawtech.freeserve.co.uk>
Wow, that is coming on really well.

The only thing I spotted was the x squareds, where the 2 is
too high. The base of the 2 lines up with the top of the
x. The superscript worked well on the E to the n+1, so I
guess the supersuperscript is positioning itself right for
full size initial letters rather than superscript sized
initial letters.

Alan Crowe
From: Marc Battyani
Subject: Re: cl-typesetting saturday night news
Date: 
Message-ID: <blorir$acb@library1.airnews.net>
"Alan Crowe" <····@cawNOtech.freeSPAMserve.co.uk> wrote
> Wow, that is coming on really well.
>
> The only thing I spotted was the x squareds, where the 2 is
> too high. The base of the 2 lines up with the top of the
> x. The superscript worked well on the E to the n+1, so I
> guess the supersuperscript is positioning itself right for
> full size initial letters rather than superscript sized
> initial letters.

Yes, I don't know what % of the font height TeX uses for superscript and
subscript so I made it a parameter with a default value of 0.45 and -0.2
respectively. I you know the values used by TeX, I will change them.

The thickness and spacing of the fractions rules are also tunable parameters.

BTW I've added italic correction for the super/subscripts and upgraded the
example with it.

Marc
From: Fabrice Popineau
Subject: Re: cl-typesetting saturday night news
Date: 
Message-ID: <isn11egm.fsf@esemetz.metz.supelec.fr>
> The only thing I spotted was the
> x squareds, where the 2 is too high. 

The whole line is misaligned : the = sign vs the fraction and the + vs -
operators.

Also it doesn't space well, probably due to missing italic correction.

Fabrice
From: Marc Battyani
Subject: Re: cl-typesetting saturday night news
Date: 
Message-ID: <blu8ul$bdl@library2.airnews.net>
"Fabrice Popineau" <················@supelec.fr> wrote
>
> The whole line is misaligned : the = sign vs the fraction and the + vs -
> operators.
>
> Also it doesn't space well, probably due to missing italic correction.

Sure, That's why the text following this line in the exemple is :
"As you can see, the + and the = are not properly aligned because of the lack
of a real math font. Note the italic correction for the super/subscript of
the E."

IMO Italic correction is not needed inside the formula except when the font
change or for super/subscripts.

BTW Thanks for the hyphenation code I will try to integrate it this evening.
:)

Marc
From: Fabrice Popineau
Subject: Re: cl-typesetting saturday night news
Date: 
Message-ID: <8ynv1r6a.fsf@esemetz.metz.supelec.fr>
> Sure, That's why the text following this line in the exemple is : "As
> you can see, the + and the = are not properly aligned because of the
> lack of a real math font. Note the italic correction for the
> super/subscript of the E."

Sorry, I looked only a the math formula :-))

Fabrice