mirror of
https://github.com/goose121/clx-truetype.git
synced 2026-09-10 07:16:25 -04:00
initial commit
This commit is contained in:
commit
d2d095c30a
17
.gitignore
vendored
Normal file
17
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
*.fasl
|
||||
*.aux
|
||||
*.cp
|
||||
*.fn
|
||||
*.fns
|
||||
*.info
|
||||
*.ky
|
||||
*.log
|
||||
*.pg
|
||||
*.toc
|
||||
*.tp
|
||||
*.tps
|
||||
*.vr
|
||||
*.rvs
|
||||
*.vrs
|
||||
include-stamp
|
||||
web/
|
||||
15
Makefile
Normal file
15
Makefile
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
.PHONY: web
|
||||
|
||||
web:
|
||||
rm -rf web
|
||||
mkdir web
|
||||
make -C doc html pdf
|
||||
cp doc/*.html doc/*.pdf web/
|
||||
cp web/clx-truetype.html web/index.html
|
||||
|
||||
pages: web
|
||||
git checkout gh-pages
|
||||
cp web/* .
|
||||
git commit -a -c master
|
||||
rm -rf web/
|
||||
git checkout -f master
|
||||
5
README.txt
Normal file
5
README.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
Pure Common Lisp TrueType antialiased fonts rendering using CLX and Xrender extension.
|
||||
|
||||
email: filonenko.mikhail@gmail.com
|
||||
jabber: asvil@jabber.ru
|
||||
skype: filonenko.mikhail
|
||||
28
clx-truetype.asd
Normal file
28
clx-truetype.asd
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
;;;; clx-truetype.asd
|
||||
|
||||
(asdf:defsystem #:clx-truetype
|
||||
:serial t
|
||||
:description "clx-truetype is pure common lisp solution for antialiased TrueType font rendering using CLX and XRender extension."
|
||||
:author "Michael Filonenko <filonenko.mikhail@gmail.com>"
|
||||
:license "MIT"
|
||||
:depends-on (#:clx
|
||||
#:zpb-ttf
|
||||
#:cl-vectors
|
||||
#:cl-paths-ttf
|
||||
#:cl-aa
|
||||
#:cl-fad
|
||||
#:cl-store)
|
||||
:components ((:file "package")
|
||||
(:file "clx-utils")
|
||||
(:file "font-cache")
|
||||
(:file "clx-truetype")))
|
||||
|
||||
|
||||
(asdf:defsystem #:clx-truetype-test
|
||||
:serial t
|
||||
:description "Testing library for clx-truetype."
|
||||
:author "Michael Filonenko <filonenko.mikhail@gmail.com>"
|
||||
:license "MIT"
|
||||
:depends-on (#:clx-truetype)
|
||||
:components ((:module test
|
||||
:components ((:file "hello-world")))))
|
||||
537
clx-truetype.lisp
Normal file
537
clx-truetype.lisp
Normal file
|
|
@ -0,0 +1,537 @@
|
|||
;;;; clx-truetype.lisp
|
||||
|
||||
(in-package #:clx-truetype)
|
||||
|
||||
(defclass font ()
|
||||
((family :type string :initarg :family :accessor font-family :documentation "Font family.")
|
||||
(subfamily :type string :initarg :subfamily :accessor font-subfamily :documentation "Font subfamily. For e.g. regular, italic, bold, bold italib.")
|
||||
(size :type numeric :initarg :size :accessor font-size :initform 12 :documentation "Font size in points.")
|
||||
(underline :type boolean :initarg :underline :initform nil :accessor font-underline :documentation "Draw line under text string.")
|
||||
(strikethrough :type boolean :initarg :strikethrough :initform nil :accessor font-strikethrough :documentation "Draw strike through text string.")
|
||||
(overline :type boolean :initarg :overline :initform nil :accessor font-overline :documentation "Draw line over text string.")
|
||||
(background :initarg :background :initform nil :accessor font-background :documentation "Background color.")
|
||||
(foreground :initarg :foregroung :initform nil :accessor font-foregroung :documentation "Foreground color.")
|
||||
(overwrite-gcontext :type boolean :initarg overwrite-gcontext :initform nil
|
||||
:accessor font-overwrite-gcontext :documentation "Use font values for background and foreground colors.")
|
||||
(antialiased :type boolean :initarg antialiased :initform t :accessor font-antialiased :documentation "Antialias text string."))
|
||||
(:documentation "Class for representing font information."))
|
||||
|
||||
(defun check-valid-font-families (family subfamily)
|
||||
(when (or (null (gethash family *font-cache*))
|
||||
(null (gethash subfamily (gethash family *font-cache*))))
|
||||
(error "Font is not found: ~A ~A" family subfamily)))
|
||||
|
||||
(defmethod initialize-instance :before
|
||||
((instance font) &rest initargs &key family subfamily &allow-other-keys)
|
||||
(check-valid-font-families family subfamily))
|
||||
|
||||
(defmethod (setf font-family) :before
|
||||
(family (instance font))
|
||||
(check-valid-font-families family (font-subfamily instance)))
|
||||
|
||||
(defmethod (setf font-subfamily) :before
|
||||
(subfamily (instance font))
|
||||
(check-valid-font-families (font-family instance) subfamily))
|
||||
|
||||
;;; ZPB-TTF font objects cache
|
||||
(defun get-font-pathname (font)
|
||||
(gethash (font-subfamily font) (gethash (font-family font) *font-cache*)))
|
||||
|
||||
(defvar *font-loader-cache* (make-hash-table :test 'equal))
|
||||
|
||||
(defmacro with-font-loader ((loader font) &body body)
|
||||
(let ((exists-p (gensym))
|
||||
(font-path (gensym)))
|
||||
`(let ((,font-path (get-font-pathname ,font)))
|
||||
(multiple-value-bind (,loader ,exists-p)
|
||||
(gethash ,font-path *font-loader-cache* (zpb-ttf:open-font-loader ,font-path))
|
||||
(unless ,exists-p
|
||||
(setf (gethash ,font-path *font-loader-cache*) ,loader))
|
||||
,@body))))
|
||||
|
||||
;;; Screen DPI
|
||||
(defun screen-default-dpi (screen)
|
||||
"Returns default dpi for @var{screen}. pixel width * 25.4/millimeters width"
|
||||
(values (floor (* (xlib:screen-width screen) 25.4)
|
||||
(xlib:screen-width-in-millimeters screen))
|
||||
(floor (* (xlib:screen-height screen) 25.4)
|
||||
(xlib:screen-height-in-millimeters screen))))
|
||||
|
||||
(defun screen-dpi (screen)
|
||||
"Returns current dpi for @var{screen}."
|
||||
(values (getf (xlib:screen-plist screen) :dpi-x
|
||||
(floor (* (xlib:screen-width screen) 25.4)
|
||||
(xlib:screen-width-in-millimeters screen)))
|
||||
(getf (xlib:screen-plist screen) :dpi-y
|
||||
(floor (* (xlib:screen-height screen) 25.4)
|
||||
(xlib:screen-height-in-millimeters screen)))))
|
||||
|
||||
(defun (setf screen-dpi) (value screen)
|
||||
"Sets current dpi for @var{screen}."
|
||||
(setf (getf (xlib:screen-plist screen) :dpi-x) value
|
||||
(getf (xlib:screen-plist screen) :dpi-y) value))
|
||||
|
||||
;;; Font metrics
|
||||
(defun font-units->pixels-x (drawable font)
|
||||
"px = funits*coeff. Function returns coeff."
|
||||
(with-font-loader (loader font)
|
||||
(multiple-value-bind (dpi-x dpi-y)
|
||||
(screen-dpi (drawable-screen drawable))
|
||||
(with-slots (size) font
|
||||
(let* ((units/em (zpb-ttf:units/em loader))
|
||||
(pixel-size-x (* size (/ dpi-x 72))))
|
||||
(* pixel-size-x (/ units/em)))))))
|
||||
|
||||
(defun font-units->pixels-y (drawable font)
|
||||
"px = funits*coeff. Function returns coeff."
|
||||
(with-font-loader (loader font)
|
||||
(multiple-value-bind (dpi-x dpi-y)
|
||||
(screen-dpi (drawable-screen drawable))
|
||||
(with-slots (size) font
|
||||
(let* ((units/em (zpb-ttf:units/em loader))
|
||||
(pixel-size-y (* size (/ dpi-y 72))))
|
||||
(* pixel-size-y (/ units/em)))))))
|
||||
|
||||
(defun font-ascent (drawable font)
|
||||
"Returns ascent of @var{font}. @{drawable} must be window, pixmap or screen."
|
||||
(with-font-loader (loader font)
|
||||
(ceiling (* (font-units->pixels-y drawable font) (zpb-ttf:ascender loader)))))
|
||||
|
||||
(defun font-descent (drawable font)
|
||||
"Returns descent of @var{font}. @{drawable} must be window, pixmap or screen."
|
||||
(with-font-loader (loader font)
|
||||
(floor (* (font-units->pixels-y drawable font) (zpb-ttf:descender loader)))))
|
||||
|
||||
(defun font-line-gap (drawable font)
|
||||
"Returns line gap of @var{font}. @{drawable} must be window, pixmap or screen."
|
||||
(with-font-loader (loader font)
|
||||
(ceiling (* (font-units->pixels-y drawable font) (zpb-ttf:line-gap loader)))))
|
||||
|
||||
;;; baseline-to-baseline = ascent - descent + line gap
|
||||
(defun baseline-to-baseline (drawable font)
|
||||
"Returns distance between baselines of @var{font}. @{drawable} must be window, pixmap or screen. ascent - descent + line gap"
|
||||
(+ (font-ascent drawable font) (- (font-descent drawable font))
|
||||
(font-line-gap drawable font)))
|
||||
|
||||
(defun text-bounding-box (drawable font string)
|
||||
"Returns text bounding box. @{drawable} must be window, pixmap or screen. Text bounding box is only for contours. Bounding box for space (#x20) is zero."
|
||||
(with-font-loader (loader font)
|
||||
(let* ((bbox
|
||||
(zpb-ttf:string-bounding-box string loader))
|
||||
(units->pixels-x (font-units->pixels-x drawable font))
|
||||
(units->pixels-y (font-units->pixels-y drawable font))
|
||||
(xmin (zpb-ttf:xmin bbox))
|
||||
(ymin (zpb-ttf:ymin bbox))
|
||||
(xmax (zpb-ttf:xmax bbox))
|
||||
(ymax (zpb-ttf:ymax bbox)))
|
||||
(when (font-underline font)
|
||||
(setf ymin (min ymin (- (zpb-ttf:underline-position loader)
|
||||
(zpb-ttf:underline-thickness loader)))))
|
||||
(when (font-overline font)
|
||||
(setf ymax (max ymax (+ (zpb-ttf:ascender loader)
|
||||
(zpb-ttf:underline-position loader)
|
||||
(+ (zpb-ttf:underline-thickness loader))))))
|
||||
(vector (floor (* xmin
|
||||
units->pixels-x))
|
||||
(floor (* ymin
|
||||
units->pixels-y))
|
||||
(ceiling (* xmax
|
||||
units->pixels-x))
|
||||
(ceiling (* ymax
|
||||
units->pixels-y))))))
|
||||
|
||||
(defun text-width (drawable font string)
|
||||
"Returns width of text bounding box. @{drawable} must be window, pixmap or screen."
|
||||
(let ((bbox (text-bounding-box drawable font string)))
|
||||
(- (xmax bbox) (xmin bbox))))
|
||||
|
||||
(defun text-height (drawable font string)
|
||||
"Returns height of text bounding box. @{drawable} must be window, pixmap or screen."
|
||||
(let ((bbox (text-bounding-box drawable font string)))
|
||||
(- (ymax bbox) (ymin bbox))))
|
||||
|
||||
(defun text-line-bounding-box (drawable font string)
|
||||
"Returns text line bounding box. @var{drawable} must be window, pixmap or screen. Text line bounding box is bigger than text bounding box. It's height is ascent + descent, width is sum of advance widths minus sum of kernings."
|
||||
(with-font-loader (loader font)
|
||||
(let* ((units->pixels-x (font-units->pixels-x drawable font))
|
||||
(xmin 0)
|
||||
(ymin (font-descent drawable font))
|
||||
(ymax (font-ascent drawable font))
|
||||
(string-length (length string))
|
||||
(xmax (if (> string-length 0)
|
||||
(zpb-ttf:advance-width (zpb-ttf:find-glyph (elt string 0) loader))
|
||||
0)))
|
||||
(if (zpb-ttf:fixed-pitch-p loader)
|
||||
(setf xmax (* xmax string-length))
|
||||
(do ((i 1 (1+ i)))
|
||||
((>= i string-length))
|
||||
(incf xmax
|
||||
(+ (zpb-ttf:advance-width (zpb-ttf:find-glyph (elt string i) loader))
|
||||
(zpb-ttf:kerning-offset (elt string (1- i)) (elt string i) loader)))))
|
||||
(vector (floor (* xmin units->pixels-x))
|
||||
ymin
|
||||
(ceiling (* xmax
|
||||
units->pixels-x))
|
||||
ymax))))
|
||||
|
||||
(defun text-line-width (drawable font string)
|
||||
"Returns width of text line bounding box. @var{drawable} must be window, pixmap or screen. It is sum of advance widths minus sum of kernings."
|
||||
(let ((bbox (text-line-bounding-box drawable font string)))
|
||||
(- (xmax bbox) (xmin bbox))))
|
||||
|
||||
(defun text-line-height (drawable font string)
|
||||
"Returns height of text line bounding box. @var{drawable} must be window, pixmap or screen."
|
||||
(let ((bbox (text-line-bounding-box drawable font string)))
|
||||
(- (ymax bbox) (ymin bbox))))
|
||||
|
||||
(defun xmin (bounding-box)
|
||||
"Returns left side x of @var{bounding-box}"
|
||||
(typecase bounding-box
|
||||
(vector (elt bounding-box 0))))
|
||||
|
||||
(defun ymin (bounding-box)
|
||||
"Returns bottom side y of @var{bounding-box}"
|
||||
(typecase bounding-box
|
||||
(vector (elt bounding-box 1))))
|
||||
|
||||
(defun xmax (bounding-box)
|
||||
"Returns right side x of @var{bounding-box}"
|
||||
(typecase bounding-box
|
||||
(vector (elt bounding-box 2))))
|
||||
|
||||
(defun ymax (bounding-box)
|
||||
"Returns top side y of @var{bounding-box}"
|
||||
(typecase bounding-box
|
||||
(vector (elt bounding-box 3))))
|
||||
|
||||
;;; Font rendering
|
||||
(defun clamp (value min max)
|
||||
"Clamps the value 'value' into the range [min,max]."
|
||||
(max min (min max value)))
|
||||
|
||||
(defun make-state (font)
|
||||
"Wrapper around antialising and not antialiasing renderers."
|
||||
(if (font-antialiased font)
|
||||
(aa:make-state)
|
||||
(aa-bin:make-state)))
|
||||
|
||||
(defun aa-bin/update-state (state paths)
|
||||
"Update state for not antialiasing renderer."
|
||||
(if (listp paths)
|
||||
(dolist (path paths)
|
||||
(aa-bin/update-state state path))
|
||||
(let ((iterator (paths:path-iterator-segmented paths)))
|
||||
(multiple-value-bind (i1 k1 e1) (paths:path-iterator-next iterator)
|
||||
(declare (ignore i1))
|
||||
(when (and k1 (not e1))
|
||||
;; at least 2 knots
|
||||
(let ((first-knot k1))
|
||||
(loop
|
||||
(multiple-value-bind (i2 k2 e2) (paths:path-iterator-next iterator)
|
||||
(declare (ignore i2))
|
||||
(aa-bin:line-f state
|
||||
(paths:point-x k1) (paths:point-y k1)
|
||||
(paths:point-x k2) (paths:point-y k2))
|
||||
(setf k1 k2)
|
||||
(when e2
|
||||
(return))))
|
||||
(aa-bin:line-f state
|
||||
(paths:point-x k1) (paths:point-y k1)
|
||||
(paths:point-x first-knot) (paths:point-y first-knot)))))))
|
||||
state)
|
||||
|
||||
(defun update-state (font state paths)
|
||||
"Wrapper around antialising and not antialiasing renderers."
|
||||
(if (font-antialiased font)
|
||||
(vectors:update-state state paths)
|
||||
(aa-bin/update-state state paths)))
|
||||
|
||||
(defun cells-sweep (font state function &optional function-span)
|
||||
"Wrapper around antialising and not antialiasig renderers."
|
||||
(if (font-antialiased font)
|
||||
(aa:cells-sweep state function function-span)
|
||||
(aa-bin:cells-sweep state function function-span)))
|
||||
|
||||
(defun text-pixarray (drawable font string)
|
||||
"Render a text string of 'face', returning a 2D (unsigned-byte 8) array
|
||||
suitable as an alpha mask, and dimensions. This function returns five
|
||||
values: alpha mask byte array, x-origin, y-origin (subtracted from
|
||||
position before rendering), horizontal and vertical advances.
|
||||
@var{drawable} must be window or pixmap."
|
||||
(with-font-loader (font-loader font)
|
||||
(let* ((bbox (text-bounding-box drawable font string))
|
||||
(min-x (xmin bbox))
|
||||
(min-y (ymin bbox))
|
||||
(max-x (xmax bbox))
|
||||
(max-y (ymax bbox))
|
||||
(width (- max-x min-x))
|
||||
(height (- max-y min-y))
|
||||
(units->pixels-x (font-units->pixels-x drawable font))
|
||||
(units->pixels-y (font-units->pixels-y drawable font))
|
||||
(array (make-array (list height width)
|
||||
:initial-element 0
|
||||
:element-type '(unsigned-byte 8)))
|
||||
(state (make-state font))
|
||||
(paths (paths-ttf:paths-from-string font-loader string
|
||||
:offset (paths:make-point (- min-x)
|
||||
max-y)
|
||||
:scale-x units->pixels-x
|
||||
:scale-y (- units->pixels-y))))
|
||||
(when (or (= 0 width) (= 0 height))
|
||||
(return-from text-pixarray (values nil 0 0 0 0)))
|
||||
(when (font-underline font)
|
||||
(let* ((thickness (* units->pixels-y (zpb-ttf:underline-thickness font-loader)))
|
||||
(underline-offset (* units->pixels-y (zpb-ttf:underline-position font-loader)))
|
||||
(underline-path (paths:make-rectangle-path 0 (+ max-y (- underline-offset))
|
||||
max-x (+ max-y (- underline-offset) thickness))))
|
||||
(push underline-path paths)))
|
||||
(when (font-strikethrough font)
|
||||
(let* ((thickness (* units->pixels-y (zpb-ttf:underline-thickness font-loader)))
|
||||
(underline-offset (* 2 units->pixels-y (zpb-ttf:underline-position font-loader)))
|
||||
(line-path (paths:make-rectangle-path 0 (+ max-y underline-offset) max-x (+ max-y underline-offset thickness))))
|
||||
(push line-path paths)))
|
||||
(when (font-overline font)
|
||||
(let* ((thickness (* units->pixels-y (zpb-ttf:underline-thickness font-loader)))
|
||||
(underline-offset (* units->pixels-y (zpb-ttf:underline-position font-loader)))
|
||||
(ascend (* units->pixels-y (zpb-ttf:ascender font-loader)))
|
||||
(overline-path (paths:make-rectangle-path 0 (- max-y ascend underline-offset)
|
||||
max-x
|
||||
(- max-y ascend underline-offset thickness))))
|
||||
(push overline-path paths)))
|
||||
(update-state font state paths)
|
||||
(cells-sweep font state
|
||||
(lambda (x y alpha)
|
||||
(when (and (<= 0 x (1- width))
|
||||
(<= 0 y (1- height)))
|
||||
(setf alpha (min 255 (abs alpha))
|
||||
(aref array y x) (clamp
|
||||
(floor (+ (* (- 256 alpha) (aref array y x))
|
||||
(* alpha 255))
|
||||
256)
|
||||
0 255)))))
|
||||
(values array
|
||||
min-x
|
||||
max-y
|
||||
width
|
||||
height))))
|
||||
|
||||
|
||||
(defun text-line-pixarray (drawable font string)
|
||||
"Render a text line of 'face', returning a 2D (unsigned-byte 8) array
|
||||
suitable as an alpha mask, and dimensions. This function returns five
|
||||
values: alpha mask byte array, x-origin, y-origin (subtracted from
|
||||
position before rendering), horizontal and vertical advances.
|
||||
@var{drawable} must be window or pixmap."
|
||||
(with-font-loader (font-loader font)
|
||||
(let* ((bbox (text-line-bounding-box drawable font string))
|
||||
(min-x (xmin bbox))
|
||||
(min-y (ymin bbox))
|
||||
(max-x (xmax bbox))
|
||||
(max-y (ymax bbox))
|
||||
(width (- max-x min-x))
|
||||
(height (- max-y min-y))
|
||||
(units->pixels-x (font-units->pixels-x drawable font))
|
||||
(units->pixels-y (font-units->pixels-y drawable font))
|
||||
(array (make-array (list height width)
|
||||
:initial-element 0
|
||||
:element-type '(unsigned-byte 8)))
|
||||
(state (make-state font))
|
||||
(paths (paths-ttf:paths-from-string font-loader string
|
||||
:offset (paths:make-point (- min-x)
|
||||
max-y)
|
||||
:scale-x units->pixels-x
|
||||
:scale-y (- units->pixels-y))))
|
||||
(when (or (= 0 width) (= 0 height))
|
||||
(return-from text-line-pixarray (values nil 0 0 0 0)))
|
||||
(when (font-underline font)
|
||||
(let* ((thickness (* units->pixels-y (zpb-ttf:underline-thickness font-loader)))
|
||||
(underline-offset (* units->pixels-y (zpb-ttf:underline-position font-loader)))
|
||||
(underline-path (paths:make-rectangle-path 0 (+ max-y (- underline-offset))
|
||||
max-x (+ max-y (- underline-offset) thickness))))
|
||||
(push underline-path paths)))
|
||||
(when (font-strikethrough font)
|
||||
(let* ((thickness (* units->pixels-y (zpb-ttf:underline-thickness font-loader)))
|
||||
(underline-offset (* 2 units->pixels-y (zpb-ttf:underline-position font-loader)))
|
||||
(line-path (paths:make-rectangle-path 0 (+ max-y underline-offset) max-x (+ max-y underline-offset thickness))))
|
||||
(push line-path paths)))
|
||||
(when (font-overline font)
|
||||
(let* ((thickness (* units->pixels-y (zpb-ttf:underline-thickness font-loader)))
|
||||
(underline-offset (* units->pixels-y (zpb-ttf:underline-position font-loader)))
|
||||
(ascend (* units->pixels-y (zpb-ttf:ascender font-loader)))
|
||||
(overline-path (paths:make-rectangle-path 0 (- max-y ascend underline-offset)
|
||||
max-x
|
||||
(- max-y ascend underline-offset thickness))))
|
||||
(push overline-path paths)))
|
||||
(update-state font state paths)
|
||||
(cells-sweep font state
|
||||
(lambda (x y alpha)
|
||||
(when (and (<= 0 x (1- width))
|
||||
(<= 0 y (1- height)))
|
||||
(setf alpha (min 255 (abs alpha))
|
||||
(aref array y x) (clamp
|
||||
(floor (+ (* (- 256 alpha) (aref array y x))
|
||||
(* alpha 255))
|
||||
256)
|
||||
0 255)))))
|
||||
(values array
|
||||
min-x
|
||||
max-y
|
||||
width
|
||||
height))))
|
||||
|
||||
(defun update-foreground (drawable gcontext font)
|
||||
"Lazy updates foreground for drawable. @var{drawable} must be window or pixmap."
|
||||
(let ((pixmap (or (getf (xlib:drawable-plist drawable) :ttf-pen-surface)
|
||||
(setf (getf (xlib:drawable-plist drawable) :ttf-pen-surface)
|
||||
(xlib:create-pixmap
|
||||
:drawable drawable
|
||||
:depth (xlib:drawable-depth drawable)
|
||||
:width 1 :height 1)))))
|
||||
(let ((color (the xlib:card32
|
||||
(if (font-overwrite-gcontext font)
|
||||
(font-foregroung font)
|
||||
(xlib:gcontext-foreground gcontext)))))
|
||||
(when (or (null (getf (xlib:drawable-plist drawable) :ttf-foreground))
|
||||
(/= (getf (xlib:drawable-plist drawable) :ttf-foreground)
|
||||
color))
|
||||
(let ((previous-color (xlib:gcontext-foreground gcontext)))
|
||||
(setf (xlib:gcontext-foreground gcontext) color)
|
||||
(xlib:draw-point pixmap gcontext 0 0)
|
||||
(setf (xlib:gcontext-foreground gcontext) previous-color)
|
||||
(setf (getf (xlib:drawable-plist drawable) :ttf-foreground) color))))))
|
||||
|
||||
(defun update-background (drawable gcontext font x y width height)
|
||||
"Lazy updates background for drawable. @var{drawable} must be window or pixmap."
|
||||
(let ((previous-color (xlib:gcontext-foreground gcontext))
|
||||
(color (the xlib:card32
|
||||
(if (font-overwrite-gcontext font)
|
||||
(font-background font)
|
||||
(xlib:gcontext-background gcontext)))))
|
||||
(setf (xlib:gcontext-foreground gcontext) color)
|
||||
(xlib:draw-rectangle drawable gcontext x y width height t)
|
||||
(setf (xlib:gcontext-foreground gcontext) previous-color)))
|
||||
|
||||
;;; Caching X11 objects
|
||||
(defun get-drawable-picture (drawable)
|
||||
(or (getf (xlib:drawable-plist drawable) :ttf-surface)
|
||||
(setf (getf (xlib:drawable-plist drawable) :ttf-surface)
|
||||
(xlib:render-create-picture drawable :format
|
||||
(xlib:find-window-picture-format drawable)))))
|
||||
|
||||
(defun get-drawable-pen-picture (drawable)
|
||||
(or (getf (xlib:drawable-plist drawable) :ttf-pen)
|
||||
(setf (getf (xlib:drawable-plist drawable) :ttf-pen)
|
||||
(xlib:render-create-picture
|
||||
(or (getf (xlib:drawable-plist drawable) :ttf-pen-surface)
|
||||
(setf (getf (xlib:drawable-plist drawable) :ttf-pen-surface)
|
||||
(xlib:create-pixmap
|
||||
:drawable drawable
|
||||
:depth (xlib:drawable-depth drawable)
|
||||
:width 1 :height 1)))
|
||||
:format (xlib:find-window-picture-format drawable)))))
|
||||
|
||||
(defun display-alpha-picture-format (display)
|
||||
(or (getf (xlib:display-plist display) :ttf-alpha-format)
|
||||
(setf (getf (xlib:display-plist display) :ttf-alpha-format)
|
||||
(first
|
||||
(xlib:find-matching-picture-formats
|
||||
display
|
||||
:depth 8 :alpha 8 :red 0 :blue 0 :green 0)))))
|
||||
|
||||
;;; Drawing text
|
||||
|
||||
(defun draw-text (drawable gcontext font string x y &key (start 0) (end (length string)))
|
||||
"Draws text string using @var{font} on @var{drawable} with graphic context @var{gcontext}. @var{x}, @var{y} are the left point of base line. @var{start} and @var{end} are used for substring rendering.
|
||||
If @var{gcontext} has background color, text bounding box will be filled with it. Text line bounding box is bigger than text bounding box. @var{drawable} must be window or pixmap."
|
||||
(when (>= start end)
|
||||
(return-from draw-text))
|
||||
(multiple-value-bind (alpha-data min-x max-y width height)
|
||||
(text-pixarray drawable font (subseq string start end))
|
||||
(when (or (= 0 width) (= 0 height))
|
||||
(return-from draw-text))
|
||||
(let* ((display (xlib:drawable-display drawable))
|
||||
(image (xlib:create-image :width width :height height :depth 8 :data alpha-data))
|
||||
(alpha-pixmap (xlib:create-pixmap :width width :height height :depth 8 :drawable drawable))
|
||||
(alpha-gc (xlib:create-gcontext :drawable alpha-pixmap))
|
||||
(alpha-picture
|
||||
(progn
|
||||
(xlib:put-image alpha-pixmap alpha-gc image :x 0 :y 0)
|
||||
(xlib:render-create-picture alpha-pixmap :format
|
||||
(display-alpha-picture-format display))))
|
||||
(source-picture (get-drawable-pen-picture drawable))
|
||||
(destination-picture (get-drawable-picture drawable)))
|
||||
(update-foreground drawable gcontext font)
|
||||
(update-background drawable gcontext font (+ x min-x) (- y max-y) width height)
|
||||
;; Sync the destination picture with the gcontext
|
||||
(setf (xlib:picture-clip-x-origin destination-picture) (xlib:gcontext-clip-x gcontext))
|
||||
(setf (xlib:picture-clip-y-origin destination-picture) (xlib:gcontext-clip-y gcontext))
|
||||
(setf (xlib:picture-subwindow-mode destination-picture) (xlib:gcontext-subwindow-mode gcontext))
|
||||
(setf (xlib::picture-clip-mask destination-picture)
|
||||
(xlib::gcontext-clip-mask gcontext))
|
||||
(xlib:render-composite :over source-picture alpha-picture destination-picture 0 0 0 0 (+ x min-x) (- y max-y) width height)
|
||||
nil)))
|
||||
|
||||
(defun draw-text-line (drawable gcontext font string x y &key (start 0) (end (length string)))
|
||||
"Draws text string using @var{font} on @var{drawable} with graphic context @var{gcontext}. @var{x}, @var{y} are the left point of base line. @var{start} and @var{end} are used for substring rendering.
|
||||
If @var{gcontext} has background color, text line bounding box will be filled with it. Text line bounding box is bigger than text bounding box. @var{drawable} must be window or pixmap."
|
||||
(when (>= start end)
|
||||
(return-from draw-text-line))
|
||||
(multiple-value-bind (alpha-data min-x max-y width height)
|
||||
(text-line-pixarray drawable font (subseq string start end))
|
||||
(when (or (= 0 width) (= 0 height))
|
||||
(return-from draw-text-line))
|
||||
(let* ((display (xlib:drawable-display drawable))
|
||||
(image (xlib:create-image :width width :height height :depth 8 :data alpha-data))
|
||||
(alpha-pixmap (xlib:create-pixmap :width width :height height :depth 8 :drawable drawable))
|
||||
(alpha-gc (xlib:create-gcontext :drawable alpha-pixmap))
|
||||
(alpha-picture
|
||||
(progn
|
||||
(xlib:put-image alpha-pixmap alpha-gc image :x 0 :y 0)
|
||||
(xlib:render-create-picture alpha-pixmap :format
|
||||
(display-alpha-picture-format display))))
|
||||
(source-picture (get-drawable-pen-picture drawable))
|
||||
(destination-picture (get-drawable-picture drawable)))
|
||||
(update-foreground drawable gcontext font)
|
||||
(update-background drawable gcontext font (+ x min-x) (- y max-y) width height)
|
||||
;; Sync the destination picture with the gcontext
|
||||
(setf (xlib:picture-clip-x-origin destination-picture) (xlib:gcontext-clip-x gcontext))
|
||||
(setf (xlib:picture-clip-y-origin destination-picture) (xlib:gcontext-clip-y gcontext))
|
||||
(setf (xlib:picture-subwindow-mode destination-picture) (xlib:gcontext-subwindow-mode gcontext))
|
||||
(setf (xlib::picture-clip-mask destination-picture)
|
||||
(xlib::gcontext-clip-mask gcontext))
|
||||
(xlib:render-composite :over source-picture alpha-picture destination-picture 0 0 0 0 (+ x min-x) (- y max-y) width height)
|
||||
nil)))
|
||||
|
||||
;;; Test utils
|
||||
|
||||
(defun trgrey (i)
|
||||
"Visualize alpha mask using graphic characters"
|
||||
(cond
|
||||
((> i 200) "██")
|
||||
((> i 150) "▓▓")
|
||||
((> i 100) "▒▒")
|
||||
((> i 50) "░░")
|
||||
(t " ")))
|
||||
|
||||
(defun print-pixarray (array)
|
||||
"Print 2d array of alpha mask using graphic characters."
|
||||
(do ((i 0 (1+ i)))
|
||||
((>= i (array-dimension array 0)) nil)
|
||||
(do ((j 0 (1+ j)))
|
||||
((>= j (array-dimension array 1)) nil)
|
||||
(format t "~A" (trgrey (aref array i j))))
|
||||
(format t "~%")))
|
||||
|
||||
(defun font-lines-height (drawable font lines-count)
|
||||
"Returns text lines height in pixels. For one line height is ascender+descender. For more than one line height is ascender+descender+linegap."
|
||||
(if (> lines-count 0)
|
||||
(+ (+ (xft:font-ascent drawable font)
|
||||
(- (xft:font-descent drawable font)))
|
||||
(* (1- lines-count) (+ (xft:font-ascent drawable font)
|
||||
(- (xft:font-descent drawable font))
|
||||
(xft:font-line-gap drawable font))))
|
||||
0))
|
||||
|
||||
|
||||
;;; "clx-truetype" goes here. Hacks and glory await!
|
||||
|
||||
12
clx-utils.lisp
Normal file
12
clx-utils.lisp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
;;; Utils
|
||||
|
||||
(in-package #:clx-truetype)
|
||||
|
||||
(defun drawable-screen (drawable)
|
||||
(typecase drawable
|
||||
(xlib:drawable
|
||||
(dolist (screen (xlib:display-roots (xlib:drawable-display drawable)))
|
||||
(when (equalp (xlib:screen-root screen) (xlib:drawable-root drawable))
|
||||
(return screen))))
|
||||
(xlib:screen drawable)
|
||||
(t nil)))
|
||||
34
doc/Makefile
Normal file
34
doc/Makefile
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
.PHONY: clean
|
||||
|
||||
all: html pdf info
|
||||
|
||||
clean:
|
||||
rm -rf include
|
||||
rm -f *.pdf *.html *.info
|
||||
rm -f *.aux *.cp *.fn *.fns *.ky *.log *.pg *.toc *.tp *.tps *.vr
|
||||
rm -f include-stamp
|
||||
|
||||
clx-truetype.texinfo:
|
||||
|
||||
|
||||
include-stamp: ../*.lisp ../*.asd
|
||||
sbcl \
|
||||
--eval '(let ((asdf:*central-registry* (cons #p"../" (cons #p"/home/michael/webspace/sb-texinfo/" asdf:*central-registry*)))) (require :sb-texinfo) (require :clx-truetype))' \
|
||||
--eval '(sb-texinfo:generate-includes "include/" (list (find-package :clx-truetype)) :base-package :clx-truetype)' \
|
||||
--eval '(quit)'
|
||||
touch include-stamp
|
||||
|
||||
%.html: clx-truetype.texinfo style.css include-stamp
|
||||
makeinfo --html --no-split --css-include=style.css $<
|
||||
|
||||
%.pdf: clx-truetype.texinfo include-stamp
|
||||
texi2dvi -p $<
|
||||
|
||||
%.info: clx-truetype.texinfo include-stamp
|
||||
makeinfo --no-split $<
|
||||
|
||||
html: clx-truetype.html
|
||||
|
||||
pdf: clx-truetype.pdf
|
||||
|
||||
info: clx-truetype.info
|
||||
545
doc/clx-truetype.html
Normal file
545
doc/clx-truetype.html
Normal file
|
|
@ -0,0 +1,545 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<title>CLX-TRUETYPE</title>
|
||||
<meta http-equiv="Content-Type" content="text/html">
|
||||
<meta name="description" content="CLX-TRUETYPE">
|
||||
<meta name="generator" content="makeinfo 4.13">
|
||||
<link title="Top" rel="top" href="#Top">
|
||||
<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<style type="text/css"><!--
|
||||
pre.display { font-family:inherit }
|
||||
pre.format { font-family:inherit }
|
||||
pre.smalldisplay { font-family:inherit; font-size:smaller }
|
||||
pre.smallformat { font-family:inherit; font-size:smaller }
|
||||
pre.smallexample { font-size:smaller }
|
||||
pre.smalllisp { font-size:smaller }
|
||||
span.sc { font-variant:small-caps }
|
||||
span.roman { font-family:serif; font-weight:normal; }
|
||||
span.sansserif { font-family:sans-serif; font-weight:normal; }
|
||||
.node { visibility:hidden; height: 0px; }
|
||||
.menu { visibility:hidden; height: 0px; }
|
||||
.appendix { background-color:#d3d3d3; padding: 0.2em; }
|
||||
.chapter { background-color:#d3d3d3; padding: 0.2em; }
|
||||
.section { background-color:#d3d3d3; padding: 0.2em; }
|
||||
.settitle { background-color:#d3d3d3; }
|
||||
.contents { border: 2px solid black;
|
||||
margin: 1cm 1cm 1cm 1cm;
|
||||
padding-left: 3mm; }
|
||||
.lisp { padding: 0; margin: 0em; }
|
||||
body { padding: 2em 8em; font-family: sans-serif; }
|
||||
h1 { padding: 1em; text-align: center; }
|
||||
li { margin: 1em; }
|
||||
|
||||
--></style>
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="settitle">CLX-TRUETYPE</h1>
|
||||
<div class="node">
|
||||
<a name="Top"></a>
|
||||
<p><hr>
|
||||
Next: <a rel="next" accesskey="n" href="#Overview">Overview</a>,
|
||||
Up: <a rel="up" accesskey="u" href="#dir">(dir)</a>
|
||||
|
||||
</div>
|
||||
|
||||
<h2 class="unnumbered">Introduction</h2>
|
||||
|
||||
<p><span class="sc">clx-truetype </span> renders TrueType fonts over X11 drawable (window or pixmap)
|
||||
using CLX, XRender, ZPB-TTF, CL-VECTORS.
|
||||
|
||||
<p><span class="sc">clx-truetype </span> was originally written for mcclim font rendering
|
||||
by Gilbert Baumann and Andy Hefner.
|
||||
|
||||
<!-- Version control -->
|
||||
<p><span class="sc">clx-truetype </span> is maintained in Git:
|
||||
<pre class="example"> git clone git://github.com/filonenko-mikhail/clx-truetype
|
||||
</pre>
|
||||
<p>will get you a local copy.
|
||||
<pre class="example"> <a href="http://github.com/filonenko-mikhail/clx-truetype/">http://github.com/filonenko-mikhail/clx-truetype/</a>
|
||||
</pre>
|
||||
<p>is the GitHub project page, where the issue tracker is located.
|
||||
|
||||
<div class="contents">
|
||||
<h2>Table of Contents</h2>
|
||||
<ul>
|
||||
<li><a name="toc_Top" href="#Top">Introduction</a>
|
||||
<li><a name="toc_Overview" href="#Overview">1 Overview</a>
|
||||
<li><a name="toc_Examples" href="#Examples">2 Examples</a>
|
||||
<li><a name="toc_Dictionary" href="#Dictionary">3 Dictionary</a>
|
||||
<li><a name="toc_Concept-Index" href="#Concept-Index">Appendix A Concept Index</a>
|
||||
<li><a name="toc_Function-Index" href="#Function-Index">Appendix B Function Index</a>
|
||||
<li><a name="toc_Variable-Index" href="#Variable-Index">Appendix C Variable Index</a>
|
||||
<li><a name="toc_Type-Index" href="#Type-Index">Appendix D Type Index</a>
|
||||
<li><a name="toc_Colophon" href="#Colophon">Colophon</a>
|
||||
</li></ul>
|
||||
</div>
|
||||
|
||||
<ul class="menu">
|
||||
<li><a accesskey="1" href="#Overview">Overview</a>
|
||||
<li><a accesskey="2" href="#Examples">Examples</a>
|
||||
<li><a accesskey="3" href="#Dictionary">Dictionary</a>
|
||||
<li><a accesskey="4" href="#Concept-Index">Concept Index</a>
|
||||
<li><a accesskey="5" href="#Function-Index">Function Index</a>
|
||||
<li><a accesskey="6" href="#Variable-Index">Variable Index</a>
|
||||
<li><a accesskey="7" href="#Type-Index">Type Index</a>
|
||||
<li><a accesskey="8" href="#Colophon">Colophon</a>
|
||||
</ul>
|
||||
|
||||
<div class="node">
|
||||
<a name="Overview"></a>
|
||||
<p><hr>
|
||||
Next: <a rel="next" accesskey="n" href="#Examples">Examples</a>,
|
||||
Previous: <a rel="previous" accesskey="p" href="#Top">Top</a>,
|
||||
Up: <a rel="up" accesskey="u" href="#Top">Top</a>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- node-name, next, previous, up -->
|
||||
<h2 class="chapter">1 Overview</h2>
|
||||
|
||||
<p><span class="sc">clx-truetype </span> is library for text rendering over X11 drawable using CLX, XRender,
|
||||
ZPB-TTF, CL-VECTORS.
|
||||
|
||||
<p>TrueType font metrics
|
||||
|
||||
<div class="block-image"><img src="ttf-metrics.png" alt="ttf-metrics.png"></div>
|
||||
|
||||
<ul>
|
||||
<li>TrueType hints are not supported.
|
||||
<li>RGB antialiasing is not supported.
|
||||
<li>Text rendering do not use XRender glyph sets.
|
||||
</ul>
|
||||
|
||||
<div class="node">
|
||||
<a name="Examples"></a>
|
||||
<p><hr>
|
||||
Next: <a rel="next" accesskey="n" href="#Dictionary">Dictionary</a>,
|
||||
Previous: <a rel="previous" accesskey="p" href="#Overview">Overview</a>,
|
||||
Up: <a rel="up" accesskey="u" href="#Top">Top</a>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- node-name, next, previous, up -->
|
||||
<h2 class="chapter">2 Examples</h2>
|
||||
|
||||
<p>Drawing text is quite simple.
|
||||
|
||||
<p>First and only one time step is loading font cache using
|
||||
<a href="#Function-cache_002dfonts"><code>cache-fonts</code></a>.
|
||||
If you add font to your system, you should call it again.
|
||||
|
||||
<pre class="lisp"> (cache-fonts)
|
||||
</pre>
|
||||
<p>Make instance of font:
|
||||
|
||||
<pre class="lisp"> (font (make-instance 'font :family "Times New Roman" :subfamily "Bold Italic"
|
||||
:size 12 :antialiased t))
|
||||
</pre>
|
||||
<p>Draw it using <a href="#Function-draw_002dtext"><code>draw-text</code></a> or <a href="#Function-draw_002dtext_002dline"><code>draw-text-line</code></a> functions:
|
||||
|
||||
<pre class="lisp"> (draw-text window grackon font "The quick brown fox jumps over the lazy dog." 100 100)
|
||||
</pre>
|
||||
<p>Move <<cursor>> using <a href="#Function-baseline_002dto_002dbaseline"><code>baseline-to-baseline</code></a> distance.
|
||||
|
||||
<p>Here it is complete example. Just insert it into repl, and evaluate (show-window).
|
||||
|
||||
<pre class="lisp"> (defpackage #:clx-truetype-test
|
||||
(:nicknames :xft-test)
|
||||
(:use #:cl #:xft)
|
||||
(:export show-window))
|
||||
|
||||
(in-package :clx-truetype-test)
|
||||
|
||||
(defvar *display* (xlib:open-default-display))
|
||||
|
||||
(defvar *screen* (xlib:display-default-screen *display*))
|
||||
(defvar *root* (xlib:screen-root *screen*))
|
||||
|
||||
(defun show-window ()
|
||||
(let* ((black (xlib:screen-black-pixel *screen*))
|
||||
(white (xlib:screen-white-pixel *screen*))
|
||||
(window
|
||||
(xlib:create-window :parent *root* :x 0 :y 0 :width 640 :height 480
|
||||
:class :input-output
|
||||
:background white
|
||||
:event-mask '(:key-press :key-release :exposure :button-press
|
||||
:structure-notify)))
|
||||
(grackon (xlib:create-gcontext
|
||||
:drawable window
|
||||
:foreground black
|
||||
:background white))
|
||||
(font (make-instance 'font :family "Times New Roman" :subfamily "Bold Italic"
|
||||
:size 12 :antialiased t)))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(xlib:map-window window)
|
||||
(setf (xlib:gcontext-foreground grackon) black)
|
||||
(xlib:event-case (*display* :force-output-p t
|
||||
:discard-p t)
|
||||
(:exposure ()
|
||||
(draw-text window grackon font "The quick brown fox jumps over the lazy dog." 100 100)
|
||||
(when (= 0 (random 2))
|
||||
(rotatef (xlib:gcontext-foreground grackon) (xlib:gcontext-background grackon)))
|
||||
(draw-text window grackon font "Съешь же ещё этих мягких французских булок, да выпей чаю." 100 (+ 100 (baseline-to-baseline window font)))
|
||||
(setf (font-antialiased font) (= 0 (random 2)))
|
||||
(if (= 0 (random 2))
|
||||
(setf (font-subfamily font) "Regular")
|
||||
(setf (font-subfamily font) "Italic"))
|
||||
(draw-text window grackon font "Жебракують філософи при ґанку церкви в Гадячі, ще й шатро їхнє п’яне знаємо." 100 (+ 100 (* 2 (baseline-to-baseline window font))))
|
||||
(draw-text window grackon font "Press space to exit. Нажмите пробел для выхода." 100 (+ 100 (* 3 (baseline-to-baseline window font)))))
|
||||
(:button-press () t)
|
||||
(:key-press (code state) (char= #\Space (xlib:keycode->character *display* code state)))))
|
||||
(progn
|
||||
(xlib:free-gcontext grackon)
|
||||
(xlib:destroy-window window)
|
||||
(xlib:display-force-output *display*)))))
|
||||
</pre>
|
||||
<p>Result is
|
||||
|
||||
<div class="block-image"><img src="example.png" alt="example.png"></div>
|
||||
|
||||
<div class="node">
|
||||
<a name="Dictionary"></a>
|
||||
<p><hr>
|
||||
Next: <a rel="next" accesskey="n" href="#Concept-Index">Concept Index</a>,
|
||||
Previous: <a rel="previous" accesskey="p" href="#Examples">Examples</a>,
|
||||
Up: <a rel="up" accesskey="u" href="#Top">Top</a>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- node-name, next, previous, up -->
|
||||
<h2 class="chapter">3 Dictionary</h2>
|
||||
|
||||
<p><a name="Package-xft"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Package: <b>xft</b><var><a name="index-xft-1"></a></var><br>
|
||||
<blockquote><p>Package contains <code>api</code> for TrueType text rendering using <code>clx</code>, XRender. Glyphs information is obtained by <code>zpb-ttf</code>. Font rasterization is made by <code>cl-vectors</code>.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-g_t_0040earmuffs_007bfont_002ddirs_007d-2"></a><a name="Variable-_002afont_002ddirs_002a"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Variable: <b>*font-dirs*</b><var><a name="index-g_t_0040earmuffs_007bfont_002ddirs_007d-3"></a></var><br>
|
||||
<blockquote><p>List of directories, which contain TrueType fonts.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-cache_002dfonts-4"></a><a name="Function-cache_002dfonts"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>cache-fonts</b><var><a name="index-cache_002dfonts-5"></a></var><br>
|
||||
<blockquote><p>Caches fonts from *font-dirs* directories.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-cache_002dfont_002dfile-6"></a><a name="Function-cache_002dfont_002dfile"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>cache-font-file</b><var> pathname<a name="index-cache_002dfont_002dfile-7"></a></var><br>
|
||||
<blockquote><p>Caches font file into hashmap.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-get_002dfont_002dfamilies-8"></a><a name="Function-get_002dfont_002dfamilies"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>get-font-families</b><var><a name="index-get_002dfont_002dfamilies-9"></a></var><br>
|
||||
<blockquote><p>Returns cached font families.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-get_002dfont_002dsubfamilies-10"></a><a name="Function-get_002dfont_002dsubfamilies"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>get-font-subfamilies</b><var> font-family<a name="index-get_002dfont_002dsubfamilies-11"></a></var><br>
|
||||
<blockquote><p>Returns font subfamilies for current. For e.g. regular, italic, bold, etc.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-font-12"></a><a name="Class-font"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Class: <b>font</b><var><a name="index-font-13"></a></var><br>
|
||||
<blockquote><p>Class precedence list: <code>font, standard-object, t</code>
|
||||
|
||||
<p>Slots:
|
||||
<ul>
|
||||
<li><code>family</code> — initarg: <code>:family<!-- /@w --></code>; reader: <code>clx-truetype:font-family<!-- /@w --></code>; writer: <code>(setf clx-truetype:font-family)<!-- /@w --></code>
|
||||
|
||||
<p>Font family.
|
||||
<li><code>subfamily</code> — initarg: <code>:subfamily<!-- /@w --></code>; reader: <code>clx-truetype:font-subfamily<!-- /@w --></code>; writer: <code>(setf clx-truetype:font-subfamily)<!-- /@w --></code>
|
||||
|
||||
<p>Font subfamily. For e.g. regular, italic, bold, bold italib.
|
||||
<li><code>size</code> — initarg: <code>:size<!-- /@w --></code>; reader: <code>clx-truetype:font-size<!-- /@w --></code>; writer: <code>(setf clx-truetype:font-size)<!-- /@w --></code>
|
||||
|
||||
<p>Font size in points.
|
||||
<li><code>underline</code> — initarg: <code>:underline<!-- /@w --></code>; reader: <code>clx-truetype:font-underline<!-- /@w --></code>; writer: <code>(setf clx-truetype:font-underline)<!-- /@w --></code>
|
||||
|
||||
<p>Draw line under text string.
|
||||
<li><code>strikethrough</code> — initarg: <code>:strikethrough<!-- /@w --></code>; reader: <code>clx-truetype:font-strikethrough<!-- /@w --></code>; writer: <code>(setf clx-truetype:font-strikethrough)<!-- /@w --></code>
|
||||
|
||||
<p>Draw strike through text string.
|
||||
<li><code>overline</code> — initarg: <code>:overline<!-- /@w --></code>; reader: <code>clx-truetype:font-overline<!-- /@w --></code>; writer: <code>(setf clx-truetype:font-overline)<!-- /@w --></code>
|
||||
|
||||
<p>Draw line over text string.
|
||||
<li><code>background</code> — initarg: <code>:background<!-- /@w --></code>; reader: <code>clx-truetype:font-background<!-- /@w --></code>; writer: <code>(setf clx-truetype:font-background)<!-- /@w --></code>
|
||||
|
||||
<p>Background color.
|
||||
<li><code>foreground</code> — initarg: <code>:foregroung<!-- /@w --></code>; reader: <code>clx-truetype:font-foregroung<!-- /@w --></code>; writer: <code>(setf clx-truetype:font-foregroung)<!-- /@w --></code>
|
||||
|
||||
<p>Foreground color.
|
||||
<li><code>overwrite-gcontext</code> — initarg: <code>clx-truetype::overwrite-gcontext<!-- /@w --></code>; reader: <code>clx-truetype:font-overwrite-gcontext<!-- /@w --></code>; writer: <code>(setf clx-truetype:font-overwrite-gcontext)<!-- /@w --></code>
|
||||
|
||||
<p>Use font values for background and foreground colors.
|
||||
<li><code>antialiased</code> — initarg: <code>clx-truetype::antialiased<!-- /@w --></code>; reader: <code>clx-truetype:font-antialiased<!-- /@w --></code>; writer: <code>(setf clx-truetype:font-antialiased)<!-- /@w --></code>
|
||||
|
||||
<p>Antialias text string.
|
||||
</ul>
|
||||
|
||||
<p>Class for representing font information.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-screen_002ddefault_002ddpi-14"></a><a name="Function-screen_002ddefault_002ddpi"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>screen-default-dpi</b><var> screen<a name="index-screen_002ddefault_002ddpi-15"></a></var><br>
|
||||
<blockquote><p>Returns default dpi for @var{screen}. pixel width <code>*</code> 25.4/millimeters width
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-screen_002ddpi-16"></a><a name="Function-screen_002ddpi"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>screen-dpi</b><var> screen<a name="index-screen_002ddpi-17"></a></var><br>
|
||||
<blockquote><p>Returns current dpi for @var{screen}.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-g_t_0040setf_007bscreen_002ddpi_007d-18"></a><a name="Function-_0028setf-screen_002ddpi_0029"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>(setf screen-dpi)</b><var> value screen<a name="index-g_t_0040setf_007bscreen_002ddpi_007d-19"></a></var><br>
|
||||
<blockquote><p>Sets current dpi for @var{screen}.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-font_002dascent-20"></a><a name="Function-font_002dascent"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>font-ascent</b><var> drawable font<a name="index-font_002dascent-21"></a></var><br>
|
||||
<blockquote><p>Returns ascent of @var{font}. @{drawable} must be window, pixmap or screen.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-font_002ddescent-22"></a><a name="Function-font_002ddescent"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>font-descent</b><var> drawable font<a name="index-font_002ddescent-23"></a></var><br>
|
||||
<blockquote><p>Returns descent of @var{font}. @{drawable} must be window, pixmap or screen.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-font_002dline_002dgap-24"></a><a name="Function-font_002dline_002dgap"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>font-line-gap</b><var> drawable font<a name="index-font_002dline_002dgap-25"></a></var><br>
|
||||
<blockquote><p>Returns line gap of @var{font}. @{drawable} must be window, pixmap or screen.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-baseline_002dto_002dbaseline-26"></a><a name="Function-baseline_002dto_002dbaseline"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>baseline-to-baseline</b><var> drawable font<a name="index-baseline_002dto_002dbaseline-27"></a></var><br>
|
||||
<blockquote><p>Returns distance between baselines of @var{font}. @{drawable} must be window, pixmap or screen. ascent <code>-</code> descent <code>+</code> line gap
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-text_002dbounding_002dbox-28"></a><a name="Function-text_002dbounding_002dbox"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>text-bounding-box</b><var> drawable font string<a name="index-text_002dbounding_002dbox-29"></a></var><br>
|
||||
<blockquote><p>Returns text bounding box. @{drawable} must be window, pixmap or screen. Text bounding box is only for contours. Bounding box for space (#x20) is zero.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-text_002dwidth-30"></a><a name="Function-text_002dwidth"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>text-width</b><var> drawable font string<a name="index-text_002dwidth-31"></a></var><br>
|
||||
<blockquote><p>Returns width of text bounding box. @{drawable} must be window, pixmap or screen.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-text_002dheight-32"></a><a name="Function-text_002dheight"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>text-height</b><var> drawable font string<a name="index-text_002dheight-33"></a></var><br>
|
||||
<blockquote><p>Returns height of text bounding box. @{drawable} must be window, pixmap or screen.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-text_002dline_002dbounding_002dbox-34"></a><a name="Function-text_002dline_002dbounding_002dbox"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>text-line-bounding-box</b><var> drawable font string<a name="index-text_002dline_002dbounding_002dbox-35"></a></var><br>
|
||||
<blockquote><p>Returns text line bounding box. @var{drawable} must be window, pixmap or screen. Text line bounding box is bigger than text bounding box. It's height is ascent <code>+</code> descent, width is sum of advance widths minus sum of kernings.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-text_002dline_002dwidth-36"></a><a name="Function-text_002dline_002dwidth"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>text-line-width</b><var> drawable font string<a name="index-text_002dline_002dwidth-37"></a></var><br>
|
||||
<blockquote><p>Returns width of text line bounding box. @var{drawable} must be window, pixmap or screen. It is sum of advance widths minus sum of kernings.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-text_002dline_002dheight-38"></a><a name="Function-text_002dline_002dheight"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>text-line-height</b><var> drawable font string<a name="index-text_002dline_002dheight-39"></a></var><br>
|
||||
<blockquote><p>Returns height of text line bounding box. @var{drawable} must be window, pixmap or screen.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-xmin-40"></a><a name="Function-xmin"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>xmin</b><var> bounding-box<a name="index-xmin-41"></a></var><br>
|
||||
<blockquote><p>Returns left side x of @var{bounding-box}
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-ymin-42"></a><a name="Function-ymin"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>ymin</b><var> bounding-box<a name="index-ymin-43"></a></var><br>
|
||||
<blockquote><p>Returns bottom side y of @var{bounding-box}
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-xmax-44"></a><a name="Function-xmax"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>xmax</b><var> bounding-box<a name="index-xmax-45"></a></var><br>
|
||||
<blockquote><p>Returns right side x of @var{bounding-box}
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-ymax-46"></a><a name="Function-ymax"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>ymax</b><var> bounding-box<a name="index-ymax-47"></a></var><br>
|
||||
<blockquote><p>Returns top side y of @var{bounding-box}
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-draw_002dtext-48"></a><a name="Function-draw_002dtext"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>draw-text</b><var> drawable gcontext font string x y &key start end<a name="index-draw_002dtext-49"></a></var><br>
|
||||
<blockquote><p>Draws text string using @var{font} on @var{drawable} with graphic context @var{gcontext}. @var{x}, @var{y} are the left point of base line. @var{start} and @var{end} are used for substring rendering.
|
||||
If @var{gcontext} has background color, text bounding box will be filled with it. Text line bounding box is bigger than text bounding box. @var{drawable} must be window or pixmap.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-draw_002dtext_002dline-50"></a><a name="Function-draw_002dtext_002dline"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>draw-text-line</b><var> drawable gcontext font string x y &key start end<a name="index-draw_002dtext_002dline-51"></a></var><br>
|
||||
<blockquote><p>Draws text string using @var{font} on @var{drawable} with graphic context @var{gcontext}. @var{x}, @var{y} are the left point of base line. @var{start} and @var{end} are used for substring rendering.
|
||||
If @var{gcontext} has background color, text line bounding box will be filled with it. Text line bounding box is bigger than text bounding box. @var{drawable} must be window or pixmap.
|
||||
</p></blockquote></div>
|
||||
|
||||
<p><a name="index-font_002dlines_002dheight-52"></a><a name="Function-font_002dlines_002dheight"></a>
|
||||
|
||||
<div class="defun">
|
||||
— Function: <b>font-lines-height</b><var> drawable font lines-count<a name="index-font_002dlines_002dheight-53"></a></var><br>
|
||||
<blockquote><p>Returns text lines height in pixels. For one line height is ascender+descender. For more than one line height is ascender+descender+linegap.
|
||||
</p></blockquote></div>
|
||||
|
||||
<div class="node">
|
||||
<a name="Concept-Index"></a>
|
||||
<p><hr>
|
||||
Next: <a rel="next" accesskey="n" href="#Function-Index">Function Index</a>,
|
||||
Previous: <a rel="previous" accesskey="p" href="#Dictionary">Dictionary</a>,
|
||||
Up: <a rel="up" accesskey="u" href="#Top">Top</a>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- node-name, next, previous, up -->
|
||||
<h2 class="appendix">Appendix A Concept Index</h2>
|
||||
|
||||
<ul class="index-cp" compact>
|
||||
</ul><div class="node">
|
||||
<a name="Function-Index"></a>
|
||||
<p><hr>
|
||||
Next: <a rel="next" accesskey="n" href="#Variable-Index">Variable Index</a>,
|
||||
Previous: <a rel="previous" accesskey="p" href="#Concept-Index">Concept Index</a>,
|
||||
Up: <a rel="up" accesskey="u" href="#Top">Top</a>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- node-name, next, previous, up -->
|
||||
<h2 class="appendix">Appendix B Function Index</h2>
|
||||
|
||||
|
||||
|
||||
<ul class="index-fn" compact>
|
||||
<li><a href="#index-g_t_0040setf_007bscreen_002ddpi_007d-18"><code>(setf screen-dpi)</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-baseline_002dto_002dbaseline-26"><code>baseline-to-baseline</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-cache_002dfont_002dfile-6"><code>cache-font-file</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-cache_002dfonts-4"><code>cache-fonts</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-draw_002dtext-48"><code>draw-text</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-draw_002dtext_002dline-50"><code>draw-text-line</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-font_002dascent-20"><code>font-ascent</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-font_002ddescent-22"><code>font-descent</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-font_002dline_002dgap-24"><code>font-line-gap</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-font_002dlines_002dheight-52"><code>font-lines-height</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-get_002dfont_002dfamilies-8"><code>get-font-families</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-get_002dfont_002dsubfamilies-10"><code>get-font-subfamilies</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-screen_002ddefault_002ddpi-14"><code>screen-default-dpi</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-screen_002ddpi-16"><code>screen-dpi</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-text_002dbounding_002dbox-28"><code>text-bounding-box</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-text_002dheight-32"><code>text-height</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-text_002dline_002dbounding_002dbox-34"><code>text-line-bounding-box</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-text_002dline_002dheight-38"><code>text-line-height</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-text_002dline_002dwidth-36"><code>text-line-width</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-text_002dwidth-30"><code>text-width</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-xmax-44"><code>xmax</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-xmin-40"><code>xmin</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-ymax-46"><code>ymax</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-ymin-42"><code>ymin</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
</ul><div class="node">
|
||||
<a name="Variable-Index"></a>
|
||||
<p><hr>
|
||||
Next: <a rel="next" accesskey="n" href="#Type-Index">Type Index</a>,
|
||||
Previous: <a rel="previous" accesskey="p" href="#Function-Index">Function Index</a>,
|
||||
Up: <a rel="up" accesskey="u" href="#Top">Top</a>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- node-name, next, previous, up -->
|
||||
<h2 class="appendix">Appendix C Variable Index</h2>
|
||||
|
||||
|
||||
|
||||
<ul class="index-vr" compact>
|
||||
<li><a href="#index-g_t_0040earmuffs_007bfont_002ddirs_007d-2"><code>*font-dirs*</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
<li><a href="#index-xft-1"><code>xft</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
</ul><div class="node">
|
||||
<a name="Type-Index"></a>
|
||||
<p><hr>
|
||||
Next: <a rel="next" accesskey="n" href="#Colophon">Colophon</a>,
|
||||
Previous: <a rel="previous" accesskey="p" href="#Variable-Index">Variable Index</a>,
|
||||
Up: <a rel="up" accesskey="u" href="#Top">Top</a>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- node-name, next, previous, up -->
|
||||
<h2 class="appendix">Appendix D Type Index</h2>
|
||||
|
||||
|
||||
|
||||
<ul class="index-tp" compact>
|
||||
<li><a href="#index-font-12"><code>font</code></a>: <a href="#Dictionary">Dictionary</a></li>
|
||||
</ul><div class="node">
|
||||
<a name="Colophon"></a>
|
||||
<p><hr>
|
||||
Previous: <a rel="previous" accesskey="p" href="#Type-Index">Type Index</a>,
|
||||
Up: <a rel="up" accesskey="u" href="#Top">Top</a>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- node-name, next, previous, up -->
|
||||
<h2 class="unnumbered">Colophon</h2>
|
||||
|
||||
<p>This manual is maintained in Texinfo, and automatically translated
|
||||
into other forms (e.g. HTML or pdf). If you're <em>reading</em> this
|
||||
manual in one of these non-Texinfo translated forms, that's fine, but
|
||||
if you want to <em>modify</em> this manual, you are strongly advised to
|
||||
seek out a Texinfo version and modify that instead of modifying a
|
||||
translated version.
|
||||
|
||||
</body></html>
|
||||
|
||||
BIN
doc/clx-truetype.pdf
Normal file
BIN
doc/clx-truetype.pdf
Normal file
Binary file not shown.
207
doc/clx-truetype.texinfo
Normal file
207
doc/clx-truetype.texinfo
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
\input texinfo @c -*-texinfo-*-
|
||||
@c %**start of header
|
||||
@setfilename clx-truetype.info
|
||||
@settitle CLX-TRUETYPE
|
||||
@c %**end of header
|
||||
|
||||
@c for install-info
|
||||
@dircategory Software development
|
||||
@direntry
|
||||
* clx-truetype: Documentation String to CLX TrueType renderer
|
||||
@end direntry
|
||||
|
||||
@finalout
|
||||
@setcontentsaftertitlepage
|
||||
|
||||
@macro project
|
||||
@sc{clx-truetype }
|
||||
@end macro
|
||||
|
||||
@titlepage
|
||||
@title @project
|
||||
@subtitle CLX TrueType Font Renderer
|
||||
@end titlepage
|
||||
|
||||
@include include/sb-texinfo.texinfo
|
||||
|
||||
@node Top
|
||||
@top Introduction
|
||||
|
||||
@project renders TrueType fonts over X11 drawable (window or pixmap)
|
||||
using CLX, XRender, ZPB-TTF, CL-VECTORS.
|
||||
|
||||
@project was originally written for mcclim font rendering
|
||||
by Gilbert Baumann and Andy Hefner.
|
||||
|
||||
@c Version control
|
||||
@project is maintained in Git:
|
||||
@example
|
||||
git clone git://github.com/filonenko-mikhail/clx-truetype
|
||||
@end example
|
||||
will get you a local copy.
|
||||
@example
|
||||
@url{http://github.com/filonenko-mikhail/clx-truetype/}
|
||||
@end example
|
||||
is the GitHub project page, where the issue tracker is located.
|
||||
|
||||
@contents
|
||||
|
||||
@menu
|
||||
* Overview::
|
||||
* Examples::
|
||||
* Dictionary::
|
||||
* Concept Index::
|
||||
* Function Index::
|
||||
* Variable Index::
|
||||
* Type Index::
|
||||
* Colophon::
|
||||
@end menu
|
||||
|
||||
@node Overview
|
||||
@comment node-name, next, previous, up
|
||||
@chapter Overview
|
||||
|
||||
@project is library for text rendering over X11 drawable using CLX, XRender,
|
||||
ZPB-TTF, CL-VECTORS.
|
||||
|
||||
TrueType font metrics
|
||||
|
||||
@image{ttf-metrics}
|
||||
|
||||
@itemize
|
||||
@item
|
||||
TrueType hints are not supported.
|
||||
@item
|
||||
RGB antialiasing is not supported.
|
||||
@item
|
||||
Text rendering do not use XRender glyph sets.
|
||||
@end itemize
|
||||
|
||||
|
||||
@node Examples
|
||||
@comment node-name, next, previous, up
|
||||
@chapter Examples
|
||||
|
||||
Drawing text is quite simple.
|
||||
|
||||
First and only one time step is loading font cache using
|
||||
@reffun{cache-fonts}.
|
||||
If you add font to your system, you should call it again.
|
||||
|
||||
@lisp
|
||||
(cache-fonts)
|
||||
@end lisp
|
||||
|
||||
Make instance of font:
|
||||
|
||||
@lisp
|
||||
(font (make-instance 'font :family "Times New Roman" :subfamily "Bold Italic"
|
||||
:size 12 :antialiased t))
|
||||
@end lisp
|
||||
|
||||
Draw it using @reffun{draw-text} or @reffun{draw-text-line} functions:
|
||||
|
||||
@lisp
|
||||
(draw-text window grackon font "The quick brown fox jumps over the lazy dog." 100 100)
|
||||
@end lisp
|
||||
|
||||
Move <<cursor>> using @reffun{baseline-to-baseline} distance.
|
||||
|
||||
Here it is complete example. Just insert it into repl, and evaluate (show-window).
|
||||
|
||||
@lisp
|
||||
(defpackage #:clx-truetype-test
|
||||
(:nicknames :xft-test)
|
||||
(:use #:cl #:xft)
|
||||
(:export show-window))
|
||||
|
||||
(in-package :clx-truetype-test)
|
||||
|
||||
(defvar *display* (xlib:open-default-display))
|
||||
|
||||
(defvar *screen* (xlib:display-default-screen *display*))
|
||||
(defvar *root* (xlib:screen-root *screen*))
|
||||
|
||||
(defun show-window ()
|
||||
(let* ((black (xlib:screen-black-pixel *screen*))
|
||||
(white (xlib:screen-white-pixel *screen*))
|
||||
(window
|
||||
(xlib:create-window :parent *root* :x 0 :y 0 :width 640 :height 480
|
||||
:class :input-output
|
||||
:background white
|
||||
:event-mask '(:key-press :key-release :exposure :button-press
|
||||
:structure-notify)))
|
||||
(grackon (xlib:create-gcontext
|
||||
:drawable window
|
||||
:foreground black
|
||||
:background white))
|
||||
(font (make-instance 'font :family "Times New Roman" :subfamily "Bold Italic"
|
||||
:size 12 :antialiased t)))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(xlib:map-window window)
|
||||
(setf (xlib:gcontext-foreground grackon) black)
|
||||
(xlib:event-case (*display* :force-output-p t
|
||||
:discard-p t)
|
||||
(:exposure ()
|
||||
(draw-text window grackon font "The quick brown fox jumps over the lazy dog." 100 100)
|
||||
(when (= 0 (random 2))
|
||||
(rotatef (xlib:gcontext-foreground grackon) (xlib:gcontext-background grackon)))
|
||||
(draw-text window grackon font "Съешь же ещё этих мягких французских булок, да выпей чаю." 100 (+ 100 (baseline-to-baseline window font)))
|
||||
(setf (font-antialiased font) (= 0 (random 2)))
|
||||
(if (= 0 (random 2))
|
||||
(setf (font-subfamily font) "Regular")
|
||||
(setf (font-subfamily font) "Italic"))
|
||||
(draw-text window grackon font "Жебракують філософи при ґанку церкви в Гадячі, ще й шатро їхнє п’яне знаємо." 100 (+ 100 (* 2 (baseline-to-baseline window font))))
|
||||
(draw-text window grackon font "Press space to exit. Нажмите пробел для выхода." 100 (+ 100 (* 3 (baseline-to-baseline window font)))))
|
||||
(:button-press () t)
|
||||
(:key-press (code state) (char= #\Space (xlib:keycode->character *display* code state)))))
|
||||
(progn
|
||||
(xlib:free-gcontext grackon)
|
||||
(xlib:destroy-window window)
|
||||
(xlib:display-force-output *display*)))))
|
||||
@end lisp
|
||||
|
||||
Result is
|
||||
|
||||
@image{example}
|
||||
|
||||
@node Dictionary
|
||||
@comment node-name, next, previous, up
|
||||
@chapter Dictionary
|
||||
|
||||
@include include/package-xft.texinfo
|
||||
|
||||
@include include/var-xft-star-font-dirs-star.texinfo
|
||||
|
||||
@include include/fun-xft-cache-fonts.texinfo
|
||||
@include include/fun-xft-cache-font-file.texinfo
|
||||
@include include/fun-xft-get-font-families.texinfo
|
||||
@include include/fun-xft-get-font-subfamilies.texinfo
|
||||
|
||||
@include include/class-xft-font.texinfo
|
||||
@include include/fun-xft-screen-default-dpi.texinfo
|
||||
@include include/fun-xft-screen-dpi.texinfo
|
||||
@include include/fun-xft-setf-screen-dpi.texinfo
|
||||
@include include/fun-xft-font-ascent.texinfo
|
||||
@include include/fun-xft-font-descent.texinfo
|
||||
@include include/fun-xft-font-line-gap.texinfo
|
||||
@include include/fun-xft-baseline-to-baseline.texinfo
|
||||
@include include/fun-xft-text-bounding-box.texinfo
|
||||
@include include/fun-xft-text-width.texinfo
|
||||
@include include/fun-xft-text-height.texinfo
|
||||
@include include/fun-xft-text-line-bounding-box.texinfo
|
||||
@include include/fun-xft-text-line-width.texinfo
|
||||
@include include/fun-xft-text-line-height.texinfo
|
||||
@include include/fun-xft-xmin.texinfo
|
||||
@include include/fun-xft-ymin.texinfo
|
||||
@include include/fun-xft-xmax.texinfo
|
||||
@include include/fun-xft-ymax.texinfo
|
||||
@include include/fun-xft-draw-text.texinfo
|
||||
@include include/fun-xft-draw-text-line.texinfo
|
||||
@include include/fun-xft-font-lines-height.texinfo
|
||||
|
||||
|
||||
@include include/backmatter.texinfo
|
||||
|
||||
@bye
|
||||
BIN
doc/example.png
Normal file
BIN
doc/example.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
39
doc/include/backmatter.texinfo
Normal file
39
doc/include/backmatter.texinfo
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
@node Concept Index
|
||||
@comment node-name, next, previous, up
|
||||
@appendix Concept Index
|
||||
|
||||
@printindex cp
|
||||
|
||||
|
||||
@node Function Index
|
||||
@comment node-name, next, previous, up
|
||||
@appendix Function Index
|
||||
|
||||
@printindex fn
|
||||
|
||||
|
||||
@node Variable Index
|
||||
@comment node-name, next, previous, up
|
||||
@appendix Variable Index
|
||||
|
||||
@printindex vr
|
||||
|
||||
|
||||
@node Type Index
|
||||
@comment node-name, next, previous, up
|
||||
@appendix Type Index
|
||||
|
||||
@printindex tp
|
||||
|
||||
|
||||
@node Colophon
|
||||
@comment node-name, next, previous, up
|
||||
@unnumbered Colophon
|
||||
|
||||
This manual is maintained in Texinfo, and automatically translated
|
||||
into other forms (e.g. HTML or pdf). If you're @emph{reading} this
|
||||
manual in one of these non-Texinfo translated forms, that's fine, but
|
||||
if you want to @emph{modify} this manual, you are strongly advised to
|
||||
seek out a Texinfo version and modify that instead of modifying a
|
||||
translated version.
|
||||
41
doc/include/class-xft-font.texinfo
Normal file
41
doc/include/class-xft-font.texinfo
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
@tindex font
|
||||
@anchor{Class font}
|
||||
@deftp {Class} {font}
|
||||
Class precedence list: @code{@lw{font}, @lw{standard-object}, @lw{t}}
|
||||
|
||||
Slots:
|
||||
@itemize
|
||||
@item @code{family} --- initarg: @code{@w{:family}}; reader: @code{@w{clx-truetype:font-family}}; writer: @code{@w{(setf clx-truetype:font-family)}}
|
||||
|
||||
Font family.
|
||||
@item @code{subfamily} --- initarg: @code{@w{:subfamily}}; reader: @code{@w{clx-truetype:font-subfamily}}; writer: @code{@w{(setf clx-truetype:font-subfamily)}}
|
||||
|
||||
Font subfamily. For e.g. regular, italic, bold, bold italib.
|
||||
@item @code{size} --- initarg: @code{@w{:size}}; reader: @code{@w{clx-truetype:font-size}}; writer: @code{@w{(setf clx-truetype:font-size)}}
|
||||
|
||||
Font size in points.
|
||||
@item @code{underline} --- initarg: @code{@w{:underline}}; reader: @code{@w{clx-truetype:font-underline}}; writer: @code{@w{(setf clx-truetype:font-underline)}}
|
||||
|
||||
Draw line under text string.
|
||||
@item @code{strikethrough} --- initarg: @code{@w{:strikethrough}}; reader: @code{@w{clx-truetype:font-strikethrough}}; writer: @code{@w{(setf clx-truetype:font-strikethrough)}}
|
||||
|
||||
Draw strike through text string.
|
||||
@item @code{overline} --- initarg: @code{@w{:overline}}; reader: @code{@w{clx-truetype:font-overline}}; writer: @code{@w{(setf clx-truetype:font-overline)}}
|
||||
|
||||
Draw line over text string.
|
||||
@item @code{background} --- initarg: @code{@w{:background}}; reader: @code{@w{clx-truetype:font-background}}; writer: @code{@w{(setf clx-truetype:font-background)}}
|
||||
|
||||
Background color.
|
||||
@item @code{foreground} --- initarg: @code{@w{:foregroung}}; reader: @code{@w{clx-truetype:font-foregroung}}; writer: @code{@w{(setf clx-truetype:font-foregroung)}}
|
||||
|
||||
Foreground color.
|
||||
@item @code{overwrite-gcontext} --- initarg: @code{@w{clx-truetype::overwrite-gcontext}}; reader: @code{@w{clx-truetype:font-overwrite-gcontext}}; writer: @code{@w{(setf clx-truetype:font-overwrite-gcontext)}}
|
||||
|
||||
Use font values for background and foreground colors.
|
||||
@item @code{antialiased} --- initarg: @code{@w{clx-truetype::antialiased}}; reader: @code{@w{clx-truetype:font-antialiased}}; writer: @code{@w{(setf clx-truetype:font-antialiased)}}
|
||||
|
||||
Antialias text string.
|
||||
@end itemize
|
||||
|
||||
Class for representing font information.
|
||||
@end deftp
|
||||
5
doc/include/fun-xft-baseline-to-baseline.texinfo
Normal file
5
doc/include/fun-xft-baseline-to-baseline.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex baseline-to-baseline
|
||||
@anchor{Function baseline-to-baseline}
|
||||
@deffn {Function} {baseline-to-baseline} drawable font
|
||||
Returns distance between baselines of @@var@{font@}. @@@{drawable@} must be window, pixmap or screen. ascent @code{-} descent @code{+} line gap
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-cache-font-file.texinfo
Normal file
5
doc/include/fun-xft-cache-font-file.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex cache-font-file
|
||||
@anchor{Function cache-font-file}
|
||||
@deffn {Function} {cache-font-file} pathname
|
||||
Caches font file into hashmap.
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-cache-fonts.texinfo
Normal file
5
doc/include/fun-xft-cache-fonts.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex cache-fonts
|
||||
@anchor{Function cache-fonts}
|
||||
@deffn {Function} {cache-fonts}
|
||||
Caches fonts from *font-dirs* directories.
|
||||
@end deffn
|
||||
6
doc/include/fun-xft-draw-text-line.texinfo
Normal file
6
doc/include/fun-xft-draw-text-line.texinfo
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
@findex draw-text-line
|
||||
@anchor{Function draw-text-line}
|
||||
@deffn {Function} {draw-text-line} drawable gcontext font string x y @&key start end
|
||||
Draws text string using @@var@{font@} on @@var@{drawable@} with graphic context @@var@{gcontext@}. @@var@{x@}, @@var@{y@} are the left point of base line. @@var@{start@} and @@var@{end@} are used for substring rendering.
|
||||
If @@var@{gcontext@} has background color, text line bounding box will be filled with it. Text line bounding box is bigger than text bounding box. @@var@{drawable@} must be window or pixmap.
|
||||
@end deffn
|
||||
6
doc/include/fun-xft-draw-text.texinfo
Normal file
6
doc/include/fun-xft-draw-text.texinfo
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
@findex draw-text
|
||||
@anchor{Function draw-text}
|
||||
@deffn {Function} {draw-text} drawable gcontext font string x y @&key start end
|
||||
Draws text string using @@var@{font@} on @@var@{drawable@} with graphic context @@var@{gcontext@}. @@var@{x@}, @@var@{y@} are the left point of base line. @@var@{start@} and @@var@{end@} are used for substring rendering.
|
||||
If @@var@{gcontext@} has background color, text bounding box will be filled with it. Text line bounding box is bigger than text bounding box. @@var@{drawable@} must be window or pixmap.
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-font-ascent.texinfo
Normal file
5
doc/include/fun-xft-font-ascent.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex font-ascent
|
||||
@anchor{Function font-ascent}
|
||||
@deffn {Function} {font-ascent} drawable font
|
||||
Returns ascent of @@var@{font@}. @@@{drawable@} must be window, pixmap or screen.
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-font-descent.texinfo
Normal file
5
doc/include/fun-xft-font-descent.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex font-descent
|
||||
@anchor{Function font-descent}
|
||||
@deffn {Function} {font-descent} drawable font
|
||||
Returns descent of @@var@{font@}. @@@{drawable@} must be window, pixmap or screen.
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-font-line-gap.texinfo
Normal file
5
doc/include/fun-xft-font-line-gap.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex font-line-gap
|
||||
@anchor{Function font-line-gap}
|
||||
@deffn {Function} {font-line-gap} drawable font
|
||||
Returns line gap of @@var@{font@}. @@@{drawable@} must be window, pixmap or screen.
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-font-lines-height.texinfo
Normal file
5
doc/include/fun-xft-font-lines-height.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex font-lines-height
|
||||
@anchor{Function font-lines-height}
|
||||
@deffn {Function} {font-lines-height} drawable font lines-count
|
||||
Returns text lines height in pixels. For one line height is ascender+descender. For more than one line height is ascender+descender+linegap.
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-get-font-families.texinfo
Normal file
5
doc/include/fun-xft-get-font-families.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex get-font-families
|
||||
@anchor{Function get-font-families}
|
||||
@deffn {Function} {get-font-families}
|
||||
Returns cached font families.
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-get-font-subfamilies.texinfo
Normal file
5
doc/include/fun-xft-get-font-subfamilies.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex get-font-subfamilies
|
||||
@anchor{Function get-font-subfamilies}
|
||||
@deffn {Function} {get-font-subfamilies} font-family
|
||||
Returns font subfamilies for current. For e.g. regular, italic, bold, etc.
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-screen-default-dpi.texinfo
Normal file
5
doc/include/fun-xft-screen-default-dpi.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex screen-default-dpi
|
||||
@anchor{Function screen-default-dpi}
|
||||
@deffn {Function} {screen-default-dpi} screen
|
||||
Returns default dpi for @@var@{screen@}. pixel width @code{*} 25.4/millimeters width
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-screen-dpi.texinfo
Normal file
5
doc/include/fun-xft-screen-dpi.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex screen-dpi
|
||||
@anchor{Function screen-dpi}
|
||||
@deffn {Function} {screen-dpi} screen
|
||||
Returns current dpi for @@var@{screen@}.
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-setf-screen-dpi.texinfo
Normal file
5
doc/include/fun-xft-setf-screen-dpi.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex @setf{screen-dpi}
|
||||
@anchor{Function (setf screen-dpi)}
|
||||
@deffn {Function} {@setf{screen-dpi}} value screen
|
||||
Sets current dpi for @@var@{screen@}.
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-text-bounding-box.texinfo
Normal file
5
doc/include/fun-xft-text-bounding-box.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex text-bounding-box
|
||||
@anchor{Function text-bounding-box}
|
||||
@deffn {Function} {text-bounding-box} drawable font string
|
||||
Returns text bounding box. @@@{drawable@} must be window, pixmap or screen. Text bounding box is only for contours. Bounding box for space (#x20) is zero.
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-text-height.texinfo
Normal file
5
doc/include/fun-xft-text-height.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex text-height
|
||||
@anchor{Function text-height}
|
||||
@deffn {Function} {text-height} drawable font string
|
||||
Returns height of text bounding box. @@@{drawable@} must be window, pixmap or screen.
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-text-line-bounding-box.texinfo
Normal file
5
doc/include/fun-xft-text-line-bounding-box.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex text-line-bounding-box
|
||||
@anchor{Function text-line-bounding-box}
|
||||
@deffn {Function} {text-line-bounding-box} drawable font string
|
||||
Returns text line bounding box. @@var@{drawable@} must be window, pixmap or screen. Text line bounding box is bigger than text bounding box. It's height is ascent @code{+} descent, width is sum of advance widths minus sum of kernings.
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-text-line-height.texinfo
Normal file
5
doc/include/fun-xft-text-line-height.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex text-line-height
|
||||
@anchor{Function text-line-height}
|
||||
@deffn {Function} {text-line-height} drawable font string
|
||||
Returns height of text line bounding box. @@var@{drawable@} must be window, pixmap or screen.
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-text-line-width.texinfo
Normal file
5
doc/include/fun-xft-text-line-width.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex text-line-width
|
||||
@anchor{Function text-line-width}
|
||||
@deffn {Function} {text-line-width} drawable font string
|
||||
Returns width of text line bounding box. @@var@{drawable@} must be window, pixmap or screen. It is sum of advance widths minus sum of kernings.
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-text-width.texinfo
Normal file
5
doc/include/fun-xft-text-width.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex text-width
|
||||
@anchor{Function text-width}
|
||||
@deffn {Function} {text-width} drawable font string
|
||||
Returns width of text bounding box. @@@{drawable@} must be window, pixmap or screen.
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-xmax.texinfo
Normal file
5
doc/include/fun-xft-xmax.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex xmax
|
||||
@anchor{Function xmax}
|
||||
@deffn {Function} {xmax} bounding-box
|
||||
Returns right side x of @@var@{bounding-box@}
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-xmin.texinfo
Normal file
5
doc/include/fun-xft-xmin.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex xmin
|
||||
@anchor{Function xmin}
|
||||
@deffn {Function} {xmin} bounding-box
|
||||
Returns left side x of @@var@{bounding-box@}
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-ymax.texinfo
Normal file
5
doc/include/fun-xft-ymax.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex ymax
|
||||
@anchor{Function ymax}
|
||||
@deffn {Function} {ymax} bounding-box
|
||||
Returns top side y of @@var@{bounding-box@}
|
||||
@end deffn
|
||||
5
doc/include/fun-xft-ymin.texinfo
Normal file
5
doc/include/fun-xft-ymin.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@findex ymin
|
||||
@anchor{Function ymin}
|
||||
@deffn {Function} {ymin} bounding-box
|
||||
Returns bottom side y of @@var@{bounding-box@}
|
||||
@end deffn
|
||||
4
doc/include/package-xft.texinfo
Normal file
4
doc/include/package-xft.texinfo
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
@anchor{Package xft}
|
||||
@defvr {Package} {xft}
|
||||
Package contains @code{api} for TrueType text rendering using @code{clx}, XRender. Glyphs information is obtained by @code{zpb-ttf}. Font rasterization is made by @code{cl-vectors}.
|
||||
@end defvr
|
||||
97
doc/include/sb-texinfo.texinfo
Normal file
97
doc/include/sb-texinfo.texinfo
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
|
||||
@c MACHINE GENERATED FILE! Do not edit by hand!
|
||||
@c See SB-TEXINFO for details.
|
||||
|
||||
@ifnottex
|
||||
@macro &allow-other-keys
|
||||
&allow-other-keys
|
||||
@end macro
|
||||
@macro &optional
|
||||
&optional
|
||||
@end macro
|
||||
@macro &rest
|
||||
&rest
|
||||
@end macro
|
||||
@macro &key
|
||||
&key
|
||||
@end macro
|
||||
@macro &body
|
||||
&body
|
||||
@end macro
|
||||
@end ifnottex
|
||||
|
||||
@macro earmuffs{name}
|
||||
*\name\*
|
||||
@end macro
|
||||
@macro setf{name}
|
||||
(setf \name\)
|
||||
@end macro
|
||||
|
||||
@iftex
|
||||
@tex
|
||||
\newif\ifdash
|
||||
\long\def\dashp#1{\expandafter\setnext#1-\dashphelper}
|
||||
\long\def\setnext#1-{\futurelet\next\dashphelper}
|
||||
\long\def\dashphelper#1\dashphelper{
|
||||
\ifx\dashphelper\next\dashfalse\else\dashtrue\fi
|
||||
}
|
||||
\def\lw#1{\leavevmode\dashp{#1}\ifdash#1\else\hbox{#1}\fi}
|
||||
@end tex
|
||||
@end iftex
|
||||
|
||||
@macro lw{word}
|
||||
@iftex
|
||||
@tex
|
||||
\\lw{\word\}%
|
||||
@end tex
|
||||
@end iftex
|
||||
@ifnottex
|
||||
\word\@c
|
||||
@end ifnottex
|
||||
@end macro
|
||||
|
||||
@macro refvar{name}
|
||||
@ref{Variable \name\, @code{\name\}}
|
||||
@end macro
|
||||
|
||||
@macro refmacro{name}
|
||||
@ref{Macro \name\, @code{\name\}}
|
||||
@end macro
|
||||
|
||||
@macro reffun{name}
|
||||
@ref{Function \name\, @code{\name\}}
|
||||
@end macro
|
||||
@iftex
|
||||
@macro NIL{name}
|
||||
{@smallertt@phantom{concurrency:}}\name\
|
||||
@end macro
|
||||
@end iftex
|
||||
@ifinfo
|
||||
@macro NIL{name}
|
||||
\name\
|
||||
@end macro
|
||||
@end ifinfo
|
||||
@ifnottex
|
||||
@ifnotinfo
|
||||
@macro NIL{name}
|
||||
\name\
|
||||
@end macro
|
||||
@end ifnotinfo
|
||||
@end ifnottex
|
||||
@iftex
|
||||
@macro nopkg{name}
|
||||
{@smallertt@phantom{concurrency:}}\name\
|
||||
@end macro
|
||||
@end iftex
|
||||
@ifinfo
|
||||
@macro nopkg{name}
|
||||
\name\
|
||||
@end macro
|
||||
@end ifinfo
|
||||
@ifnottex
|
||||
@ifnotinfo
|
||||
@macro nopkg{name}
|
||||
\name\
|
||||
@end macro
|
||||
@end ifnotinfo
|
||||
@end ifnottex
|
||||
21
doc/include/short-backmatter.texinfo
Normal file
21
doc/include/short-backmatter.texinfo
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
@node Function Index
|
||||
@comment node-name, next, previous, up
|
||||
@appendix Function Index
|
||||
|
||||
@printindex fn
|
||||
|
||||
|
||||
@node Variable Index
|
||||
@comment node-name, next, previous, up
|
||||
@appendix Variable Index
|
||||
|
||||
@printindex vr
|
||||
|
||||
|
||||
@node Type Index
|
||||
@comment node-name, next, previous, up
|
||||
@appendix Type Index
|
||||
|
||||
@printindex tp
|
||||
|
||||
5
doc/include/var-xft-star-font-dirs-star.texinfo
Normal file
5
doc/include/var-xft-star-font-dirs-star.texinfo
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@vindex @earmuffs{font-dirs}
|
||||
@anchor{Variable *font-dirs*}
|
||||
@defvr {Variable} {@earmuffs{font-dirs}}
|
||||
List of directories, which contain TrueType fonts.
|
||||
@end defvr
|
||||
14
doc/style.css
Normal file
14
doc/style.css
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
.node { visibility:hidden; height: 0px; }
|
||||
.menu { visibility:hidden; height: 0px; }
|
||||
.appendix { background-color:#d3d3d3; padding: 0.2em; }
|
||||
.chapter { background-color:#d3d3d3; padding: 0.2em; }
|
||||
.section { background-color:#d3d3d3; padding: 0.2em; }
|
||||
.settitle { background-color:#d3d3d3; }
|
||||
.contents { border: 2px solid black;
|
||||
margin: 1cm 1cm 1cm 1cm;
|
||||
padding-left: 3mm; }
|
||||
.lisp { padding: 0; margin: 0em; }
|
||||
body { padding: 2em 8em; font-family: sans-serif; }
|
||||
h1 { padding: 1em; text-align: center; }
|
||||
li { margin: 1em; }
|
||||
|
||||
BIN
doc/ttf-metrics.png
Normal file
BIN
doc/ttf-metrics.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
740
doc/ttf-metrics.svg
Normal file
740
doc/ttf-metrics.svg
Normal file
|
|
@ -0,0 +1,740 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="744.09448819"
|
||||
height="1052.3622047"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.3.1 r9886"
|
||||
sodipodi:docname="ttf-metrics.svg"
|
||||
inkscape:export-filename="/home/michael/webspace/clx-truetype/doc/ttf-metrics.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs4">
|
||||
<marker
|
||||
inkscape:stockid="Tail"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Tail"
|
||||
style="overflow:visible">
|
||||
<g
|
||||
id="g5732"
|
||||
transform="scale(-1.2)">
|
||||
<path
|
||||
id="path5734"
|
||||
d="M -3.8048674,-3.9585227 L 0.54352094,0"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.8;stroke-linecap:round" />
|
||||
<path
|
||||
id="path5736"
|
||||
d="M -1.2866832,-3.9585227 L 3.0617053,0"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.8;stroke-linecap:round" />
|
||||
<path
|
||||
id="path5738"
|
||||
d="M 1.3053582,-3.9585227 L 5.6537466,0"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.8;stroke-linecap:round" />
|
||||
<path
|
||||
id="path5740"
|
||||
d="M -3.8048674,4.1775838 L 0.54352094,0.21974226"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.8;stroke-linecap:round" />
|
||||
<path
|
||||
id="path5742"
|
||||
d="M -1.2866832,4.1775838 L 3.0617053,0.21974226"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.8;stroke-linecap:round" />
|
||||
<path
|
||||
id="path5744"
|
||||
d="M 1.3053582,4.1775838 L 5.6537466,0.21974226"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.8;stroke-linecap:round" />
|
||||
</g>
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Lstart"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow2Lstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path5714"
|
||||
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
transform="scale(1.1) translate(1,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow2Mend"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow2Mend"
|
||||
style="overflow:visible;">
|
||||
<path
|
||||
id="path5723"
|
||||
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
|
||||
transform="scale(0.6) rotate(180) translate(0,0)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Sstart"
|
||||
orient="auto"
|
||||
refY="0.0"
|
||||
refX="0.0"
|
||||
id="Arrow1Sstart"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
id="path5708"
|
||||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
|
||||
transform="scale(0.2) translate(6,0)" />
|
||||
</marker>
|
||||
<linearGradient
|
||||
id="linearGradient4237"
|
||||
osb:paint="solid">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4239" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4"
|
||||
inkscape:cx="342.07407"
|
||||
inkscape:cy="699.43094"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:snap-page="false"
|
||||
inkscape:snap-grids="true"
|
||||
showguides="false"
|
||||
inkscape:window-width="1614"
|
||||
inkscape:window-height="976"
|
||||
inkscape:window-x="100"
|
||||
inkscape:window-y="43"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:snap-global="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3013" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:#eeeeee;fill-opacity:1;fill-rule:evenodd;stroke:#eeeeee;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect8248"
|
||||
width="740"
|
||||
height="660"
|
||||
x="1.2512646"
|
||||
y="2.0081191"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:229.0243988px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="70"
|
||||
y="262.36218"
|
||||
id="text2985"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="70"
|
||||
y="262.36218"
|
||||
id="tspan2989">Li</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="70"
|
||||
y="548.6427"
|
||||
id="tspan2993">Sp</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 35,262.36218 580,0"
|
||||
id="path3005"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<rect
|
||||
style="fill:#ffe5e3;fill-opacity:0.48627451;fill-rule:evenodd;stroke:#ff6457;stroke-width:1;stroke-miterlimit:15;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect8079"
|
||||
width="118"
|
||||
height="174"
|
||||
x="85"
|
||||
y="378.36218"
|
||||
ry="0" />
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot2995"
|
||||
style="fill:black;stroke:none;stroke-opacity:1;stroke-width:1px;stroke-linejoin:miter;stroke-linecap:butt;fill-opacity:1;font-family:Sans;font-style:normal;font-weight:normal;font-size:40px;line-height:125%;letter-spacing:0px;word-spacing:0px"><flowRegion
|
||||
id="flowRegion2997"><rect
|
||||
id="rect2999"
|
||||
width="87.88327"
|
||||
height="79.802048"
|
||||
x="288.90363"
|
||||
y="174.53963" /></flowRegion><flowPara
|
||||
id="flowPara3001"></flowPara></flowRoot> <text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="630"
|
||||
y="264.36218"
|
||||
id="text3015"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="630"
|
||||
y="264.36218"
|
||||
id="tspan3041"
|
||||
style="font-size:24px">baseline</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="558"
|
||||
y="554.36218"
|
||||
id="text3019"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3021"
|
||||
x="558"
|
||||
y="554.36218"
|
||||
style="font-size:24px">baseline</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 35,552.36218 505,0"
|
||||
id="path3005-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:4.5,1.5;stroke-dashoffset:0"
|
||||
d="m 60,312.36218 480,0"
|
||||
id="path3005-25"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:6,3,1.5,3;stroke-dashoffset:0"
|
||||
d="m 60,342.36218 480,0"
|
||||
id="path3005-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:6,3,1.5,3;stroke-dashoffset:0"
|
||||
d="m 60,52.362183 480,0"
|
||||
id="path3005-3-4"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:#0169c9;stroke:#0169c9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 402,52.362183 0,209.999997"
|
||||
id="path3097-7"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#0169c9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 412,62.362183 -10,-10 -10,10"
|
||||
id="path3905"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#0169c9;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 412,252.36218 -10,10 -10,-10"
|
||||
id="path3907"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#0169c9;fill-opacity:1;stroke:#364e59;font-family:Sans"
|
||||
x="422"
|
||||
y="222.36218"
|
||||
id="text3909"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="422"
|
||||
y="222.36218"
|
||||
id="tspan3913"
|
||||
style="font-size:24px;fill:#0169c9;stroke:#364e59">ascender</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#ff8000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:15;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-mid:none;marker-end:none"
|
||||
d="m 402,262.36219 0,49.99999"
|
||||
id="path3097-7-6"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff8000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:12.39999962;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 412,272.36218 -10,-10 -10,10"
|
||||
id="path3905-5"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff8000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:12.39999962;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 412,302.36218 -10,10 -10,-10"
|
||||
id="path3907-0"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ff8000;fill-opacity:1;stroke:#ff8000;stroke-width:1;stroke-miterlimit:12.39999962;stroke-opacity:1;stroke-dasharray:none;font-family:Sans"
|
||||
x="422"
|
||||
y="302.36218"
|
||||
id="text3976"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3978"
|
||||
x="422"
|
||||
y="302.36218"
|
||||
style="font-size:24px;fill:#ff8000;fill-opacity:1;stroke:#ff8000;stroke-width:1;stroke-miterlimit:12.39999962;stroke-opacity:1;stroke-dasharray:none">descender</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#015a01;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 412,332.36218 -10,10 -10,-10"
|
||||
id="path3907-7"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#f44800;stroke:#015a01;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 402,342.36218 0,-30"
|
||||
id="path4056"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#015a01;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 412,322.36218 -10,-10 -10,10"
|
||||
id="path3905-1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#015a01;fill-opacity:1;stroke:#015a01;font-family:Sans"
|
||||
x="420"
|
||||
y="336.36218"
|
||||
id="text4058"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4060"
|
||||
x="420"
|
||||
y="336.36218"
|
||||
style="font-size:24px;fill:#015a01;stroke:#015a01">line gap</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 60,32.362183 60,632.36218"
|
||||
id="path4131"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="40"
|
||||
y="292.36218"
|
||||
id="text4133"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4135"
|
||||
x="40"
|
||||
y="292.36218"
|
||||
style="font-size:24px">0</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="40"
|
||||
y="62.362183"
|
||||
id="text4137"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4139"
|
||||
x="40"
|
||||
y="62.362183"
|
||||
style="font-size:24px">y</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="593"
|
||||
y="282.36218"
|
||||
id="text4141"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4143"
|
||||
x="593"
|
||||
y="282.36218"
|
||||
style="font-size:24px">x</tspan></text>
|
||||
<path
|
||||
style="fill:#000000;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
|
||||
d="m 60,32.362183 5,10 -10,0 z"
|
||||
id="path4145"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 625,262.36218 -10,5 0,-10 z"
|
||||
id="path4145-7"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 540,552.36218 -10,5 0,-10 z"
|
||||
id="path4145-7-3"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:transform-center-y="-90.000003" />
|
||||
<path
|
||||
style="fill:none;stroke:#980101;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 370,262.36218 0,290"
|
||||
id="path3097-7-1"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#980101;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 380,272.36218 -10,-10 -10,10"
|
||||
id="path3905-0"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#980101;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 380,542.36218 -10,10 -10,-10"
|
||||
id="path3907-71"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 85,542.36218 0,20"
|
||||
id="path8085"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 60,557.36218 25,0"
|
||||
id="path8087"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 82,554.36218 3,3 -3,4"
|
||||
id="path8089"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 63,554.36218 -3,3 3,3"
|
||||
id="path8091"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="88.571426"
|
||||
y="795.21936"
|
||||
id="text8097"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan8099"
|
||||
x="88.571426"
|
||||
y="795.21936" /></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 203,542.36218 0,20"
|
||||
id="path8101"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 220,527.36218 0,70"
|
||||
id="path8103"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 203,557.36218 17,0"
|
||||
id="path8087-4"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 217,554.36218 3,3 -3,4"
|
||||
id="path8089-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 206,554.36218 -3,3 3,3"
|
||||
id="path8091-3"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#6600cc;stroke:#6600cc;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 60,587.36218 160,0"
|
||||
id="path8162"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#6600cc;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 210,577.36218 10,10 -10,10"
|
||||
id="path8164"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#6600cc;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 70,577.36218 -10,10 10,10"
|
||||
id="path8166"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#6600cc;fill-opacity:1;stroke:#6600cc;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="100"
|
||||
y="597.36218"
|
||||
id="text8168"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan8170"
|
||||
x="100"
|
||||
y="597.36218"
|
||||
style="font-size:12px;fill:#6600cc;stroke:#6600cc">advance width</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#980101;fill-opacity:1;stroke:#980101;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="378"
|
||||
y="462.36218"
|
||||
id="text8172"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan8174"
|
||||
x="378"
|
||||
y="462.36218">baseline to baseline</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="378"
|
||||
y="492.36218"
|
||||
id="tspan8176" /></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="40"
|
||||
y="582.36218"
|
||||
id="text4133-9"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4135-5"
|
||||
x="40"
|
||||
y="582.36218"
|
||||
style="font-size:24px">0</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="510"
|
||||
y="572.36218"
|
||||
id="text4141-6"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4143-1"
|
||||
x="510"
|
||||
y="572.36218"
|
||||
style="font-size:24px">x</tspan></text>
|
||||
<rect
|
||||
style="fill:#cff2ff;fill-opacity:0.48627451;fill-rule:evenodd;stroke:#00baff;stroke-width:1.63299322;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect8231"
|
||||
width="220"
|
||||
height="260"
|
||||
x="60"
|
||||
y="52.362183"
|
||||
ry="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:#00baff;stroke-opacity:1;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="92"
|
||||
y="76.362183"
|
||||
id="text8233"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan8235"
|
||||
x="92"
|
||||
y="76.362183">text line bbox</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:#ff6457;stroke-opacity:1;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="134"
|
||||
y="424.36218"
|
||||
id="text8237"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan8239"
|
||||
x="134"
|
||||
y="424.36218">glyph bbox</tspan></text>
|
||||
<rect
|
||||
style="fill:#c4ffe1;fill-opacity:0.48627451;fill-rule:evenodd;stroke:#00fe8f;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect8250"
|
||||
width="148"
|
||||
height="175"
|
||||
x="92"
|
||||
y="87.362183" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:#00fe8f;stroke-opacity:1;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="110.28571"
|
||||
y="132.36218"
|
||||
id="text8252"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan8254"
|
||||
x="110.28571"
|
||||
y="132.36218">text bbox</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="65"
|
||||
y="567.36218"
|
||||
id="text8093"
|
||||
sodipodi:linespacing="100%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan8095"
|
||||
x="65"
|
||||
y="567.36218"
|
||||
style="font-size:8px;line-height:100%">left </tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="65"
|
||||
y="575.36218"
|
||||
style="font-size:8px;line-height:100%"
|
||||
id="tspan8129">side </tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="65"
|
||||
y="583.36218"
|
||||
style="font-size:8px;line-height:100%"
|
||||
id="tspan8131">bearing</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="205"
|
||||
y="567.36218"
|
||||
id="text8093-2"
|
||||
sodipodi:linespacing="100%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan8095-4"
|
||||
x="205"
|
||||
y="567.36218"
|
||||
style="font-size:8px;line-height:100%">right </tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="205"
|
||||
y="575.36218"
|
||||
style="font-size:8px;line-height:100%"
|
||||
id="tspan8129-4">side </tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="205"
|
||||
y="583.36218"
|
||||
style="font-size:8px;line-height:100%"
|
||||
id="tspan8131-7">bearing</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#015a01;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 92,242.36218 0,35"
|
||||
id="path8256"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#015a01;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 240,242.36218 0,35"
|
||||
id="path8256-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:#6600cc;stroke:#015a01;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 92,272.36218 148,0"
|
||||
id="path8162-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#015a01;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 235,267.36218 5,5 -5,5"
|
||||
id="path8164-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#015a01;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 97,267.36218 -5,5 5,5"
|
||||
id="path8166-4"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#015a01;fill-opacity:1;stroke:#015a01;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="105"
|
||||
y="292.36218"
|
||||
id="text8300"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan8302"
|
||||
x="105"
|
||||
y="292.36218">text width</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#013397;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 60,297.36218 0,35"
|
||||
id="path8256-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#013397;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 280,297.36218 0,35"
|
||||
id="path8256-5-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:#6600cc;stroke:#013397;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 60,322.36218 220,0"
|
||||
id="path8162-2-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#013397;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 275,317.36218 5,5 -5,5"
|
||||
id="path8164-7-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#013397;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 65,317.36218 -5,5 5,5"
|
||||
id="path8166-4-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#013397;fill-opacity:1;stroke:#013397;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="90"
|
||||
y="337.36218"
|
||||
id="text8334"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan8336"
|
||||
x="90"
|
||||
y="337.36218">text line width</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4.5, 1.5;stroke-dashoffset:0"
|
||||
d="m 60,602.36218 480,0"
|
||||
id="path3005-25-8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff8000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:15;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-mid:none;marker-end:none"
|
||||
d="m 275,552.36218 0,49.99999"
|
||||
id="path3097-7-6-4"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff8000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:12.39999962;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 285,562.36218 -10,-10 -10,10"
|
||||
id="path3905-5-5"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#ff8000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:12.39999962;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 285,592.36218 -10,10 -10,-10"
|
||||
id="path3907-0-5"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ff8000;fill-opacity:1;stroke:#ff8000;stroke-width:1;stroke-miterlimit:12.39999962;stroke-opacity:1;stroke-dasharray:none;font-family:Sans"
|
||||
x="290"
|
||||
y="587.36218"
|
||||
id="text3976-7"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3978-7"
|
||||
x="290"
|
||||
y="587.36218"
|
||||
style="font-size:24px;fill:#ff8000;fill-opacity:1;stroke:#ff8000;stroke-width:1;stroke-miterlimit:12.39999962;stroke-opacity:1;stroke-dasharray:none">descender</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 31 KiB |
66
font-cache.lisp
Normal file
66
font-cache.lisp
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
|
||||
(in-package #:clx-truetype)
|
||||
|
||||
(defvar *font-dirs* #+unix (list "/usr/share/fonts/TTF/"
|
||||
(namestring (merge-pathnames ".fonts/" (user-homedir-pathname))))
|
||||
#+macos (list "/Library/Fonts/")
|
||||
"List of directories, which contain TrueType fonts.")
|
||||
|
||||
;;(pushnew (xlib:font-path *display*) *font-dirs*)
|
||||
(defun cache-font-file (pathname)
|
||||
"Caches font file into hashmap."
|
||||
(ignore-errors
|
||||
(zpb-ttf:with-font-loader (font pathname)
|
||||
(multiple-value-bind (hash-table exists-p)
|
||||
(gethash (zpb-ttf:family-name font) *font-cache*
|
||||
(make-hash-table :test 'equal))
|
||||
(setf (gethash (zpb-ttf:subfamily-name font) hash-table)
|
||||
pathname)
|
||||
(unless exists-p
|
||||
(setf (gethash (zpb-ttf:family-name font) *font-cache*)
|
||||
hash-table))))))
|
||||
|
||||
(defun ttf-pathname-test (pathname)
|
||||
(string-equal "ttf" (pathname-type pathname)))
|
||||
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(defparameter +font-cache-filename+
|
||||
#.(merge-pathnames "font-cache.sexp"
|
||||
(merge-pathnames ".fonts/" (user-homedir-pathname)))))
|
||||
|
||||
(defun cache-fonts ()
|
||||
"Caches fonts from *font-dirs* directories."
|
||||
(clrhash *font-cache*)
|
||||
(dolist (font-dir *font-dirs*)
|
||||
(fad:walk-directory font-dir #'cache-font-file :if-does-not-exist :ignore
|
||||
:test #'ttf-pathname-test))
|
||||
(cl-store:store *font-cache* +font-cache-filename+))
|
||||
|
||||
(defun get-font-families ()
|
||||
"Returns cached font families."
|
||||
(let ((result (list)))
|
||||
(maphash (lambda (key value)
|
||||
(declare (ignorable value))
|
||||
(push key result)) *font-cache*)
|
||||
(nreverse result)))
|
||||
|
||||
(defun get-font-subfamilies (font-family)
|
||||
"Returns font subfamilies for current. For e.g. regular, italic, bold, etc."
|
||||
(let ((result (list)))
|
||||
(maphash (lambda (family value)
|
||||
(declare (ignorable family))
|
||||
(when (string-equal font-family family)
|
||||
(maphash (lambda (subfamily pathname)
|
||||
(declare (ignorable pathname))
|
||||
(push subfamily result)) value)
|
||||
(return-from get-font-subfamilies
|
||||
(nreverse result)))) *font-cache*)
|
||||
(nreverse result)))
|
||||
|
||||
;; family ->
|
||||
;; subfamily -> filename
|
||||
;; subfamily -> filename
|
||||
(defvar *font-cache*
|
||||
#.(cl-store:restore +font-cache-filename+)
|
||||
"Hashmap for caching font families, subfamilies and files.")
|
||||
|
||||
43
package.lisp
Normal file
43
package.lisp
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
;;;; package.lisp
|
||||
|
||||
(defpackage #:clx-truetype
|
||||
(:nicknames #:xft)
|
||||
(:use #:cl)
|
||||
(:export
|
||||
:font
|
||||
:font-family
|
||||
:font-subfamily
|
||||
:font-size
|
||||
:font-underline
|
||||
:font-strikethrough
|
||||
:font-overline
|
||||
:font-background
|
||||
:font-foregroung
|
||||
:font-overwrite-gcontext
|
||||
:cache-font-file
|
||||
:*font-dirs*
|
||||
:drawable-screen
|
||||
:font-ascent
|
||||
:font-descent
|
||||
:text-bounding-box
|
||||
:xmin
|
||||
:ymin
|
||||
:xmax
|
||||
:ymax
|
||||
:screen-default-dpi
|
||||
:screen-dpi
|
||||
:draw-text
|
||||
:draw-text-line
|
||||
:get-font-families
|
||||
:get-font-subfamilies
|
||||
:text-height
|
||||
:text-width
|
||||
:text-line-bounding-box
|
||||
:text-line-width
|
||||
:text-line-height
|
||||
:font-line-gap
|
||||
:baseline-to-baseline
|
||||
:font-antialiased
|
||||
:font-lines-height
|
||||
:cache-fonts)
|
||||
(:documentation "Package contains API for TrueType text rendering using CLX, XRender. Glyphs information is obtained by ZPB-TTF. Font rasterization is made by CL-VECTORS."))
|
||||
55
test/hello-world.lisp
Normal file
55
test/hello-world.lisp
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
;;;;
|
||||
;;;; REPL playing
|
||||
|
||||
(defpackage #:clx-truetype-test
|
||||
(:nicknames :xft-test)
|
||||
(:use #:cl #:xft)
|
||||
(:export show-window))
|
||||
|
||||
(in-package :clx-truetype-test)
|
||||
|
||||
(defvar *display* (xlib:open-default-display))
|
||||
|
||||
(defvar *screen* (xlib:display-default-screen *display*))
|
||||
(defvar *root* (xlib:screen-root *screen*))
|
||||
|
||||
(defun show-window ()
|
||||
(let* ((black (xlib:screen-black-pixel *screen*))
|
||||
(white (xlib:screen-white-pixel *screen*))
|
||||
(window
|
||||
(xlib:create-window :parent *root* :x 0 :y 0 :width 640 :height 480
|
||||
:class :input-output
|
||||
:background white
|
||||
:event-mask '(:key-press :key-release :exposure :button-press
|
||||
:structure-notify)))
|
||||
(grackon (xlib:create-gcontext
|
||||
:drawable window
|
||||
:foreground black
|
||||
:background white))
|
||||
(font (make-instance 'font :family "Times New Roman" :subfamily "Bold Italic"
|
||||
:size 36 :antialiased t)))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(xlib:map-window window)
|
||||
(setf (xlib:gcontext-foreground grackon) black)
|
||||
(xlib:event-case (*display* :force-output-p t
|
||||
:discard-p t)
|
||||
(:exposure ()
|
||||
(xlib:clear-area window :width (xlib:drawable-width window)
|
||||
:height (xlib:drawable-height window))
|
||||
(draw-text window grackon font "The quick brown fox jumps over the lazy dog." 100 100)
|
||||
(when (= 0 (random 2))
|
||||
(rotatef (xlib:gcontext-foreground grackon) (xlib:gcontext-background grackon)))
|
||||
(draw-text window grackon font "Съешь же ещё этих мягких французских булок, да выпей чаю." 100 (+ 100 (baseline-to-baseline window font)))
|
||||
(setf (font-antialiased font) (= 0 (random 2)))
|
||||
(if (= 0 (random 2))
|
||||
(setf (font-subfamily font) "Regular")
|
||||
(setf (font-subfamily font) "Italic"))
|
||||
(draw-text window grackon font "Жебракують філософи при ґанку церкви в Гадячі, ще й шатро їхнє п’яне знаємо." 100 (+ 100 (* 2 (baseline-to-baseline window font))))
|
||||
(draw-text window grackon font "Press space to exit. Нажмите пробел для выхода." 100 (+ 100 (* 3 (baseline-to-baseline window font)))))
|
||||
(:button-press () t)
|
||||
(:key-press (code state) (char= #\Space (xlib:keycode->character *display* code state)))))
|
||||
(progn
|
||||
(xlib:free-gcontext grackon)
|
||||
(xlib:destroy-window window)
|
||||
(xlib:display-force-output *display*)))))
|
||||
353
test/stumpwm-patch.lisp
Normal file
353
test/stumpwm-patch.lisp
Normal file
|
|
@ -0,0 +1,353 @@
|
|||
|
||||
(require :asdf)
|
||||
(asdf:load-systems :clx-truetype)
|
||||
|
||||
(in-package :stumpwm)
|
||||
|
||||
(defparameter +base-font+ (make-instance 'xft:font :family "Consolas" :subfamily "Regular" :size 13))
|
||||
;;(setf +base-font+ (make-instance 'xft:font :family "Consolas" :subfamily "Regular" :size 16))
|
||||
|
||||
;;; primitives.lisp
|
||||
(defun truetype-font-height (drawable font)
|
||||
(+ (xft:font-ascent drawable font)
|
||||
(- (xft:font-descent drawable font))))
|
||||
|
||||
(defun truetype-font-height-lines (drawable font lines-count)
|
||||
(if (> lines-count 0)
|
||||
(+ (+ (xft:font-ascent drawable font)
|
||||
(- (xft:font-descent drawable font)))
|
||||
(* (1- lines-count) (+ (xft:font-ascent drawable font)
|
||||
(- (xft:font-descent drawable font))
|
||||
(xft:font-line-gap drawable font))))
|
||||
0))
|
||||
|
||||
|
||||
;;; help.lisp
|
||||
(defvar old-display-bindings-for-keymaps (symbol-function 'display-bindings-for-keymaps))a
|
||||
(defun display-bindings-for-keymaps (key-seq &rest keymaps)
|
||||
(let* ((screen (current-screen))
|
||||
(data (mapcan (lambda (map)
|
||||
(mapcar (lambda (b) (format nil "^5*~5a^n ~a" (print-key (binding-key b)) (binding-command b))) (kmap-bindings map)))
|
||||
keymaps))
|
||||
(cols (ceiling (1+ (length data))
|
||||
(truncate (- (head-height (current-head)) (* 2 (screen-msg-border-width screen)))
|
||||
(truetype-font-height (screen-number screen) +base-font+)))))
|
||||
(message-no-timeout "Prefix: ~a~%~{~a~^~%~}"
|
||||
(print-key-seq key-seq)
|
||||
(columnize data cols))))
|
||||
|
||||
(defcommand commands () ()
|
||||
"List all available commands."
|
||||
(let* ((screen (current-screen))
|
||||
(data (all-commands))
|
||||
(cols (ceiling (length data)
|
||||
(truncate (- (head-height (current-head)) (* 2 (screen-msg-border-width screen)))
|
||||
(truetype-font-height (screen-number screen) +base-font+)))))
|
||||
(message-no-timeout "~{~a~^~%~}"
|
||||
(columnize data cols))))
|
||||
|
||||
;;; message-window.lisp
|
||||
(defvar old-show-frame-indicator (symbol-function 'show-frame-indicator))
|
||||
(defun show-frame-indicator (group &optional force)
|
||||
(show-frame-outline group)
|
||||
;; FIXME: Arg, these tests are already done in show-frame-outline
|
||||
(when (find group (mapcar 'screen-current-group *screen-list*))
|
||||
(when (or force
|
||||
(and (or (> (length (tile-group-frame-tree group)) 1)
|
||||
(not (atom (first (tile-group-frame-tree group)))))
|
||||
(not *suppress-frame-indicator*)))
|
||||
(let ((frame (tile-group-current-frame group))
|
||||
(w (screen-frame-window (current-screen)))
|
||||
(string (if (stringp *frame-indicator-text*)
|
||||
*frame-indicator-text*
|
||||
(prin1-to-string *frame-indicator-text*)))
|
||||
(font (screen-font (current-screen))))
|
||||
;; If it's already mapped it'll appear briefly in the wrong
|
||||
;; place, so unmap it first.
|
||||
(xlib:unmap-window w)
|
||||
(xlib:with-state (w)
|
||||
(setf (xlib:drawable-x w) (+ (frame-x frame)
|
||||
(truncate (- (frame-width frame)
|
||||
(xft:text-line-width w +base-font+ string)) 2))
|
||||
(xlib:drawable-y w) (+ (frame-display-y group frame)
|
||||
(truncate (- (frame-height frame)
|
||||
(truetype-font-height w +base-font+)) 2))
|
||||
(xlib:window-priority w) :above))
|
||||
(xlib:map-window w)
|
||||
(echo-in-window w font (screen-fg-color (current-screen)) (screen-bg-color (current-screen)) string)
|
||||
(reset-frame-indicator-timer)))))
|
||||
|
||||
|
||||
(defvar old-echo-in-window (symbol-function 'echo-in-window))
|
||||
(defun echo-in-window (win font fg bg string)
|
||||
(let* ((gcontext (xlib:create-gcontext :drawable win
|
||||
:font font
|
||||
:foreground fg
|
||||
:background bg))
|
||||
(height (truetype-font-height win font))
|
||||
(width (xft:text-line-width win font string)))
|
||||
(xlib:with-state (win)
|
||||
(setf (xlib:drawable-height win) height
|
||||
(xlib:drawable-width win) width))
|
||||
(xlib:clear-area win)
|
||||
(xlib:display-finish-output *display*)
|
||||
(xft:draw-text-line win gcontext +base-font+ string 0 (xft:font-ascent win +base-font+))
|
||||
;; (xlib:draw-image-glyphs win gcontext 0 (xlib:font-ascent font) string :translate #'translate-id :size 16)
|
||||
))
|
||||
|
||||
(defvar old-echo-string-list (symbol-function 'echo-string-list))
|
||||
(defun echo-string-list (screen strings &rest highlights)
|
||||
"Draw each string in l in the screen's message window. HIGHLIGHT is
|
||||
the nth entry to highlight."
|
||||
(when strings
|
||||
(unless *executing-stumpwm-command*
|
||||
(let ((width
|
||||
(render-antialiased-strings
|
||||
screen (screen-message-cc screen) *message-window-padding* 0 strings '() nil)))
|
||||
(setup-message-window screen (length strings) width)
|
||||
(render-antialiased-strings
|
||||
screen (screen-message-cc screen) *message-window-padding* 0 strings highlights))
|
||||
(setf (screen-current-msg screen)
|
||||
strings
|
||||
(screen-current-msg-highlights screen)
|
||||
highlights)
|
||||
;; Set a timer to hide the message after a number of seconds
|
||||
(if *suppress-echo-timeout*
|
||||
;; any left over timers need to be canceled.
|
||||
(when (timer-p *message-window-timer*)
|
||||
(cancel-timer *message-window-timer*)
|
||||
(setf *message-window-timer* nil))
|
||||
(reset-message-window-timer)))
|
||||
(push-last-message screen strings highlights)
|
||||
(xlib:display-finish-output *display*)
|
||||
(dformat 5 "Outputting a message:~%~{ ~a~%~}" strings)
|
||||
(apply 'run-hook-with-args *message-hook* strings)))
|
||||
|
||||
(defvar old-setup-message-window (symbol-function 'setup-message-window))
|
||||
(defun setup-message-window (screen lines width)
|
||||
(let ((height (truetype-font-height-lines (screen-number screen) +base-font+ lines))
|
||||
(win (screen-message-window screen)))
|
||||
;; Now that we know the dimensions, raise and resize it.
|
||||
(xlib:with-state (win)
|
||||
(setf (xlib:drawable-height win) height
|
||||
(xlib:drawable-width win) (+ width (* *message-window-padding* 2))
|
||||
(xlib:window-priority win) :above)
|
||||
(setup-win-gravity screen win *message-window-gravity*))
|
||||
(xlib:map-window win)
|
||||
(incf (screen-ignore-msg-expose screen))
|
||||
;; Have to flush this or the window might get cleared
|
||||
;; after we've already started drawing it.
|
||||
(xlib:display-finish-output *display*)))
|
||||
|
||||
|
||||
;;; input.lisp
|
||||
(defvar old-setup-input-window (symbol-function 'setup-input-window))
|
||||
(defun setup-input-window (screen prompt input)
|
||||
"Set the input window up to read input"
|
||||
(let* ((win (screen-input-window screen))
|
||||
(height (truetype-font-height win +base-font+)))
|
||||
;; Window dimensions
|
||||
(xlib:with-state (win)
|
||||
(setf (xlib:window-priority win) :above
|
||||
(xlib:drawable-height win) height))
|
||||
(xlib:map-window win)
|
||||
;; Draw the prompt
|
||||
(draw-input-bucket screen prompt input)))
|
||||
;; Ready to recieve input
|
||||
|
||||
(defvar old-draw-input-bucket (symbol-function 'draw-input-bucket))
|
||||
(defun draw-input-bucket (screen prompt input &optional (tail "") errorp)
|
||||
"Draw to the screen's input window the contents of input."
|
||||
(let* ((gcontext (screen-message-gc screen))
|
||||
(win (screen-input-window screen))
|
||||
(prompt-width (xft:text-line-width win +base-font+ prompt)
|
||||
;; (xlib:text-width (screen-font screen) prompt :translate #'translate-id)
|
||||
)
|
||||
(line-content (input-line-string input))
|
||||
(string (if (input-line-password input)
|
||||
(make-string (length line-content) :initial-element #\*)
|
||||
line-content))
|
||||
(text-width (xft:text-line-width win +base-font+ string)
|
||||
;; (xlib:text-width (screen-font screen) string :translate #'translate-id)
|
||||
)
|
||||
(space-width (xft:text-line-width win +base-font+ " ")
|
||||
;;(xlib:text-width (screen-font screen) " " :translate #'translate-id)
|
||||
)
|
||||
(tail-width (xft:text-line-width win +base-font+ tail)
|
||||
;;(xlib:text-width (screen-font screen) tail :translate #'translate-id)
|
||||
)
|
||||
(full-text-width (+ text-width space-width))
|
||||
(pos (input-line-position input))
|
||||
(width (+ prompt-width
|
||||
(max 100 (+ full-text-width space-width tail-width)))))
|
||||
(xlib:with-state (win)
|
||||
(xlib:clear-area win :x (+ *message-window-padding*
|
||||
prompt-width
|
||||
text-width))
|
||||
(setf (xlib:drawable-width win) (+ width (* *message-window-padding* 2)))
|
||||
(setup-win-gravity screen win *input-window-gravity*))
|
||||
(xlib:with-state (win)
|
||||
(xft:draw-text-line win gcontext +base-font+
|
||||
prompt *message-window-padding* (xft:font-ascent win +base-font+))
|
||||
;; (xlib:draw-image-glyphs win gcontext
|
||||
;; *message-window-padding*
|
||||
;; (xlib:font-ascent (screen-font screen))
|
||||
;; prompt
|
||||
;; :translate #'translate-id
|
||||
;; :size 16)
|
||||
(xft:draw-text-line win gcontext +base-font+
|
||||
string (+ *message-window-padding* prompt-width)
|
||||
(xft:font-ascent win +base-font+))
|
||||
;; (xlib:draw-image-glyphs win gcontext
|
||||
;; (+ *message-window-padding* prompt-width)
|
||||
;; (xlib:font-ascent (screen-font screen))
|
||||
;; string
|
||||
;; :translate #'translate-id
|
||||
;; :size 16)
|
||||
(xft:draw-text-line win gcontext +base-font+
|
||||
tail (+ *message-window-padding* prompt-width full-text-width space-width)
|
||||
(xft:font-ascent win +base-font+))
|
||||
;; (xlib:draw-image-glyphs win gcontext
|
||||
;; (+ *message-window-padding* prompt-width full-text-width space-width)
|
||||
;; (xlib:font-ascent (screen-font screen))
|
||||
;; tail
|
||||
;; :translate #'translate-id
|
||||
;; :size 16)
|
||||
;; draw a block cursor
|
||||
(invert-rect screen win
|
||||
(+ *message-window-padding*
|
||||
prompt-width
|
||||
(xft:text-line-width win +base-font+ (subseq string 0 pos))
|
||||
;; (xlib:text-width (screen-font screen) (subseq string 0 pos) :translate #'translate-id)
|
||||
)
|
||||
0
|
||||
(xft:text-line-width win +base-font+ (if (>= pos (length string))
|
||||
" "
|
||||
(string (char string pos))))
|
||||
;; (xlib:text-width (screen-font screen) (if (>= pos (length string))
|
||||
;; " "
|
||||
;; (string (char string pos)))
|
||||
;; :translate #'translate-id)
|
||||
(truetype-font-height win +base-font+)
|
||||
;; (+ (xlib:font-descent (screen-font screen))
|
||||
;; (xlib:font-ascent (screen-font screen)))
|
||||
)
|
||||
;; draw the error
|
||||
(when errorp
|
||||
(invert-rect screen win 0 0 (xlib:drawable-width win) (xlib:drawable-height win))
|
||||
(xlib:display-force-output *display*)
|
||||
(sleep 0.05)
|
||||
(invert-rect screen win 0 0 (xlib:drawable-width win) (xlib:drawable-height win))))))
|
||||
|
||||
|
||||
;;; mode-line.lisp
|
||||
(defvar old-resize-mode-line (symbol-function 'resize-mode-line))
|
||||
(defun resize-mode-line (ml)
|
||||
(when (eq (mode-line-mode ml) :stump)
|
||||
;; This is a StumpWM mode-line
|
||||
(setf (xlib:drawable-height (mode-line-window ml))
|
||||
(+ (* (1+ (count #\Newline (mode-line-contents ml) :test #'equal))
|
||||
(truetype-font-height (mode-line-window ml) +base-font+)
|
||||
;;(font-height (xlib:gcontext-font (mode-line-gc ml)))
|
||||
)
|
||||
(* *mode-line-pad-y* 2))))
|
||||
(setf (xlib:drawable-width (mode-line-window ml)) (- (frame-width (mode-line-head ml))
|
||||
(* 2 (xlib:drawable-border-width (mode-line-window ml))))
|
||||
(xlib:drawable-height (mode-line-window ml)) (min (xlib:drawable-height (mode-line-window ml))
|
||||
(truncate (head-height (mode-line-head ml)) 4))
|
||||
(mode-line-height ml) (+ (xlib:drawable-height (mode-line-window ml))
|
||||
(* 2 (xlib:drawable-border-width (mode-line-window ml))))
|
||||
(mode-line-factor ml) (- 1 (/ (mode-line-height ml)
|
||||
(head-height (mode-line-head ml))))
|
||||
(xlib:drawable-x (mode-line-window ml)) (head-x (mode-line-head ml))
|
||||
(xlib:drawable-y (mode-line-window ml)) (if (eq (mode-line-position ml) :top)
|
||||
(head-y (mode-line-head ml))
|
||||
(- (+ (head-y (mode-line-head ml))
|
||||
(head-height (mode-line-head ml)))
|
||||
(mode-line-height ml)))))
|
||||
|
||||
(defvar old-redraw-mode-line (symbol-function 'redraw-mode-line))
|
||||
(defun redraw-mode-line (ml &optional force)
|
||||
(when (eq (mode-line-mode ml) :stump)
|
||||
(let* ((*current-mode-line-formatters* *screen-mode-line-formatters*)
|
||||
(*current-mode-line-formatter-args* (list ml))
|
||||
(string (mode-line-format-string ml)))
|
||||
(when (or force (not (string= (mode-line-contents ml) string)))
|
||||
(setf (mode-line-contents ml) string)
|
||||
(resize-mode-line ml)
|
||||
(render-antialiased-strings (mode-line-screen ml) (mode-line-cc ml)
|
||||
*mode-line-pad-x* *mode-line-pad-y*
|
||||
(split-string string (string #\Newline)) '())))))
|
||||
|
||||
|
||||
;;; color.lisp
|
||||
(defun render-antialiased-strings (screen cc padx pady strings highlights &optional (draw t))
|
||||
(let* ((height (xft:baseline-to-baseline (screen-number screen) +base-font+))
|
||||
(width 0)
|
||||
(gc (ccontext-gc cc))
|
||||
(win (ccontext-win cc))
|
||||
(px (ccontext-px cc))
|
||||
(*foreground* nil)
|
||||
(*background* nil)
|
||||
(*reverse* nil)
|
||||
(*color-stack* '())
|
||||
(*color-map* (screen-color-map-normal screen)))
|
||||
(when draw
|
||||
(when (or (not px)
|
||||
(/= (xlib:drawable-width px) (xlib:drawable-width win))
|
||||
(/= (xlib:drawable-height px) (xlib:drawable-height win)))
|
||||
(when px (xlib:free-pixmap px))
|
||||
(setf px (xlib:create-pixmap :drawable win
|
||||
:width (xlib:drawable-width win)
|
||||
:height (xlib:drawable-height win)
|
||||
:depth (xlib:drawable-depth win))
|
||||
(ccontext-px cc) px))
|
||||
(xlib:with-gcontext (gc :foreground (xlib:gcontext-background gc))
|
||||
(xlib:draw-rectangle px gc 0 0 (xlib:drawable-width px) (xlib:drawable-height px) t)))
|
||||
(loop for s in strings
|
||||
;; We need this so we can track the row for each element
|
||||
for i from 0 to (length strings)
|
||||
do (let ((x 0) (off 0) (len (length s)))
|
||||
(loop
|
||||
for st = 0 then (+ en (1+ off))
|
||||
as en = (position #\^ s :start st)
|
||||
do (progn
|
||||
(let ((en (cond ((and en (= (1+ en) len)) nil)
|
||||
((and en (char= #\^ (char s (1+ en)))) (1+ en))
|
||||
(t en))))
|
||||
(when draw
|
||||
(xft:draw-text-line px gc
|
||||
+base-font+
|
||||
(subseq s st en)
|
||||
(+ padx x)
|
||||
(+ pady (* i height)
|
||||
(xft:font-ascent px +base-font+))))
|
||||
(setf x
|
||||
(+ x
|
||||
(xft:text-line-width
|
||||
(screen-number screen) +base-font+ (subseq s st en)))
|
||||
width (max width x)))
|
||||
(when (and en (< (1+ en) len))
|
||||
;; right-align rest of string?
|
||||
(if (char= #\> (char s (1+ en)))
|
||||
(progn
|
||||
(when draw
|
||||
(setf x (- (xlib:drawable-width px) (* 2 padx)
|
||||
;; get width of rest of s
|
||||
(render-antialiased-strings
|
||||
(screen-number screen) cc padx pady
|
||||
(list (subseq s (+ en 2)))
|
||||
'() nil))
|
||||
width (- (xlib:drawable-width px) (* 2 padx))))
|
||||
(setf off 1))
|
||||
(setf off (set-color screen cc s (1+ en))))))
|
||||
while en))
|
||||
when (find i highlights :test 'eql)
|
||||
do (when draw (invert-rect screen px
|
||||
0 (* i height)
|
||||
(xlib:drawable-width px)
|
||||
height)))
|
||||
(when draw
|
||||
(xlib:copy-area px gc 0 0 (xlib:drawable-width px) (xlib:drawable-height px) win 0 0))
|
||||
(set-color screen cc "n" 0)
|
||||
width))
|
||||
Loading…
Reference in a new issue