New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Font autoconfigure #97

Merged
merged 61 commits into from Oct 22, 2016

Conversation

Projects
None yet
6 participants
@dkochmanski
Collaborator

dkochmanski commented Oct 3, 2016

Refactor CLX fonts and TTF extension

dkochmanski and others added some commits Aug 31, 2016

refactor: remove unreachable cond branch
We remove a whole `cond' from the code block, because size is never
NIL (it is preset a few lines earlier). We leave a comment to remember
that during the further refactoring.
refactor: move the setf statement earlier
Setting size doesn't require lexical scope containing display, so we can
move it earlier.
refactor: split local function into two
Separate `find-font' into two smaller functions.
bugfix: be smart on absolute/relatvie pathnames
Our autodetection facilities rely either on looking for TTF/ directory
or on fc-match. They return relative and absolute pathnames
accordingly. This commit fixes handling of them. Related to #75.
missing-font: improve condition message
Add text-style to the message, so the user may verify which font can't
be found (NIL filename doesn't give us much information).
invoke-with-truetype-path-restart: use *query-io*
We've used `T', which isn't the right thing to use here.
refactor: add font abstraction to clx backend
Abstract `font-acent', `font-descent', `font-glyph-width',
`font-text-extents' and `font-draw-glphs' so we can work on both
truetype fonts and the ordinary fonts provided by X server (extension
specializes on different font type).

Font access will be wrapped in a protocol for truetype (and possibly
other) extensions.
refactor: text-bounding-rectanble*: unify
Now that we have unified `font-text-extents', so there is no need to
redefine the method `text-bounding-rectangle' (body is exactly the
same).
refactor: text-size: unify method
Both implementations from truetype and clx/ugly were practically the
same (except a few optimizations to the former). Backported
optimizations and removed truetype one.
refactor: medium-draw-text*: unify
Both implementations now are thread-safe (we have lock around the
drawing function) and have additional optimizations. Except that they
are should behave same as before.
refactor: reduce nesting in text-size (clx)
Move the dummy case one level up and use return-from there.
Make mcclim-truetype fallback to x native fonts
If we can't find requested style in our registered TTF fonts, we try to
find them among CLX native fonts.
Error if the text-style X font can't be found
If the fallback returns NIL (so we don't have such mapping), signal a
MISSING-FONT condition.
cleanup: remove code not referenced anywhere
I think it might be used in the past, or was planned to be used in the
future, but for now it's just a non-exported interface which isn't used
whoatsoever.
cleanup: remove duplicated variable *sizes*
Variable *clx-text-sizes* from clim-clx was duplicated in ttf extensions
under the name *sizes*. Remove the duplication.
clx cleanup: unify (setf text-style-mapping)
native clx backend text-style-mapping stored (font-name . font) in the
text-style unnecessarily, while xrender-ttf extension just holds there
font-value. Unify that.
clx cleanup: unify text-style-mapping
native clx backend text-style-mapping was searching for the requested
font and this was used by text-style-to-X-font. On the other hand ttf
extension was searching for the font in text-style-to-X-font. We have
unified that and text-style-mapping is the same thing for both
implementations now.
remove unnecessary abstraction from xrender-font
We did triple-checking, first in the hashtable, the second one in the
lookaside variable and the third one in the second hashtable. Unify
behaviour with clx backend which does only one check now.
cleanup of clx's text-style-to-X-font
Use similar pattern as used in text-style-to-X-font in xrender-fonts ttf
extension.

dkochmanski added some commits Sep 30, 2016

cleanup: pull alexandria dependency
use ensure-gethash idiom
fontconfig: major cleanup
Separate font configuration from xrender-fonts. Also add default path
search which doesn't require shelling out.
clx-port: font-families has :initform NIL
Previously slot was unbound on creation.
text-style: cache extended text styles
Previously we only cached basic text-styles. We cache it to ensure
EQL on the same extended styles (family/face designators may be strings
or other kinds of objects).
rename class truetype-face to truetype-font
This class has slots for size and other details, hence it is a font not
a face, which only denotes how it looks like.

Next commits will introduce truetype-face as a separate class.
@jorams

This comment has been minimized.

Show comment
Hide comment
@jorams

jorams Oct 3, 2016

There is another library, clx-truetype, that does antialiased TTF font rendering for CLX. Was this looked at?

Rendering using that library tends to perform terribly, so I wonder how the implementation here compares.

jorams commented Oct 3, 2016

There is another library, clx-truetype, that does antialiased TTF font rendering for CLX. Was this looked at?

Rendering using that library tends to perform terribly, so I wonder how the implementation here compares.

dkochmanski added some commits Oct 3, 2016

decouple ttf representation from clx details
xrender-fonts takes care of glueing it, but mcclim-native-ttf is
now reusable.
truetype-font: move some computations to initialize-instance
We have calculated some parameters in make-truetype-font while they
could be (and should) initialized during object creation.
port-all-find-families: register available fonts
add register-ttf-fonts function to fontconfig which registers all *.ttf
files which may be read by zpb
port-all-find-families: register available fonts
move register-ttf-fonts function to xrender-fonts, because it is indeed
xrender-fonts specific at the moment.
@stacksmith

This comment has been minimized.

Show comment
Hide comment
@stacksmith

stacksmith Oct 4, 2016

dkochmanski:
I may be doing something stupid, but I checked out your branch to take a look. Loading via (ql:quickload :mcclim) craps out (sbcl 1.3.8):

The name "ALEXANDRIA" does not designate any package.
   [Condition of type SB-KERNEL:SIMPLE-PACKAGE-ERROR]

Restarts:
 0: [TRY-RECOMPILING] Recompile package and try loading it again
 1: [RETRY] Retry loading FASL for #<CL-SOURCE-FILE "clim-lisp" "package">.
 2: [ACCEPT] Continue, treating loading FASL for #<CL-SOURCE-FILE "clim-lisp" "package"> as having been successful.
 3: [RETRY] Retry ASDF operation.
 4: [CLEAR-CONFIGURATION-AND-RETRY] Retry ASDF operation after resetting the configuration.
 5: [ABORT] Give up on "mcclim"
 --more--

Backtrace:
  0: (SB-INT:FIND-UNDELETED-PACKAGE-OR-LOSE "ALEXANDRIA")
  1: (SB-IMPL::IMPORT-LIST-SYMBOLS (("ALEXANDRIA" "ENSURE-GETHASH")))
  2: ((FLET SB-IMPL::THUNK :IN SB-IMPL::%DEFPACKAGE))
  3: ((FLET #:WITHOUT-INTERRUPTS-BODY-387 :IN SB-THREAD::CALL-WITH-RECURSIVE-LOCK))
  4: (SB-THREAD::CALL-WITH-RECURSIVE-LOCK #<CLOSURE (FLET SB-THREAD::WITH-RECURSIVE-LOCK-THUNK :IN SB-IMPL::CALL-WITH-PACKAGE-GRAPH) {7FFFE4244B1B}> #<SB-THREAD:MUTEX "Package Graph Lock" owner: #<SB-THREA..
  5: (SB-IMPL::CALL-WITH-PACKAGE-GRAPH #<CLOSURE (FLET SB-IMPL::THUNK :IN SB-IMPL::%DEFPACKAGE) {7FFFE4244B6B}>)
  6: (SB-IMPL::%DEFPACKAGE "CLIM-INTERNALS" ("CLIMI") NIL NIL NIL ("CLIM" "CLIM-SYS" "CLIM-EXTENSIONS" "CLIM-BACKEND" "CLIM-LISP") (("ALEXANDRIA" "ENSURE-GETHASH")) ("LETF") NIL ("CLIM-INTERNALS") NIL NIL ..
  7: (SB-FASL::LOAD-FASL-GROUP #S(SB-FASL::FASL-INPUT :STREAM #<SB-SYS:FD-STREAM for "file /home/stacksmith/.cache/common-lisp/sbcl-1.3.8-linux-x64/home/stacksmith/2016/lisp/McCLIM/package.fasl" {100DDE958..
  8: (SB-FASL::LOAD-AS-FASL #<SB-SYS:FD-STREAM for "file /home/stacksmith/.cache/common-lisp/sbcl-1.3.8-linux-x64/home/stacksmith/2016/lisp/McCLIM/package.fasl" {100DDE9583}> NIL NIL)
  9: ((FLET SB-FASL::LOAD-STREAM :IN LOAD) #<SB-SYS:FD-STREAM for "file /home/stacksmith/.cache/common-lisp/sbcl-1.3.8-linux-x64/home/stacksmith/2016/lisp/McCLIM/package.fasl" {100DDE9583}> T)
 10: (LOAD #P"/home/stacksmith/.cache/common-lisp/sbcl-1.3.8-linux-x64/home/stacksmith/2016/lisp/McCLIM/package.fasl" :VERBOSE NIL :PRINT NIL :IF-DOES-NOT-EXIST T :EXTERNAL-FORMAT :DEFAULT)
 11: (UIOP/UTILITY:CALL-WITH-MUFFLED-CONDITIONS #<CLOSURE (LAMBDA NIL :IN UIOP/LISP-BUILD:LOAD*) {100DDE716B}> ("Overwriting already existing readtable ~S." #(#:FINALIZERS-OFF-WARNING :ASDF-FINALIZERS)))
 12: ((SB-PCL::EMF ASDF/ACTION:PERFORM) #<unavailable argument> #<unavailable argument> #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/LISP-ACTION:CL-SOURCE-FILE "clim-lisp" "package">)
 13: ((:METHOD ASDF/ACTION:PERFORM-WITH-RESTARTS (ASDF/LISP-ACTION:LOAD-OP ASDF/LISP-ACTION:CL-SOURCE-FILE)) #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/LISP-ACTION:CL-SOURCE-FILE "clim-lisp" "package">) [fast-met..
 14: ((:METHOD ASDF/ACTION:PERFORM-WITH-RESTARTS :AROUND (T T)) #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/LISP-ACTION:CL-SOURCE-FILE "clim-lisp" "package">) [fast-method]
 15: ((:METHOD ASDF/PLAN:PERFORM-PLAN (LIST)) ((#1=#<ASDF/LISP-ACTION:PREPARE-OP > . #2=#<ASDF/SYSTEM:SYSTEM #3="trivial-gray-streams">) (#1# . #4=#<ASDF/LISP-ACTION:CL-SOURCE-FILE #3# "package">) (#5=#<AS..
 16: ((FLET SB-C::WITH-IT :IN SB-C::%WITH-COMPILATION-UNIT))
 17: ((:METHOD ASDF/PLAN:PERFORM-PLAN :AROUND (T)) ((#1=#<ASDF/LISP-ACTION:PREPARE-OP > . #2=#<ASDF/SYSTEM:SYSTEM #3="trivial-gray-streams">) (#1# . #4=#<ASDF/LISP-ACTION:CL-SOURCE-FILE #3# "package">) (#5..
 18: ((FLET SB-C::WITH-IT :IN SB-C::%WITH-COMPILATION-UNIT))
 19: ((:METHOD ASDF/PLAN:PERFORM-PLAN :AROUND (T)) #<ASDF/PLAN:SEQUENTIAL-PLAN {100AB45593}> :VERBOSE NIL) [fast-method]
 --more--

stacksmith commented Oct 4, 2016

dkochmanski:
I may be doing something stupid, but I checked out your branch to take a look. Loading via (ql:quickload :mcclim) craps out (sbcl 1.3.8):

The name "ALEXANDRIA" does not designate any package.
   [Condition of type SB-KERNEL:SIMPLE-PACKAGE-ERROR]

Restarts:
 0: [TRY-RECOMPILING] Recompile package and try loading it again
 1: [RETRY] Retry loading FASL for #<CL-SOURCE-FILE "clim-lisp" "package">.
 2: [ACCEPT] Continue, treating loading FASL for #<CL-SOURCE-FILE "clim-lisp" "package"> as having been successful.
 3: [RETRY] Retry ASDF operation.
 4: [CLEAR-CONFIGURATION-AND-RETRY] Retry ASDF operation after resetting the configuration.
 5: [ABORT] Give up on "mcclim"
 --more--

Backtrace:
  0: (SB-INT:FIND-UNDELETED-PACKAGE-OR-LOSE "ALEXANDRIA")
  1: (SB-IMPL::IMPORT-LIST-SYMBOLS (("ALEXANDRIA" "ENSURE-GETHASH")))
  2: ((FLET SB-IMPL::THUNK :IN SB-IMPL::%DEFPACKAGE))
  3: ((FLET #:WITHOUT-INTERRUPTS-BODY-387 :IN SB-THREAD::CALL-WITH-RECURSIVE-LOCK))
  4: (SB-THREAD::CALL-WITH-RECURSIVE-LOCK #<CLOSURE (FLET SB-THREAD::WITH-RECURSIVE-LOCK-THUNK :IN SB-IMPL::CALL-WITH-PACKAGE-GRAPH) {7FFFE4244B1B}> #<SB-THREAD:MUTEX "Package Graph Lock" owner: #<SB-THREA..
  5: (SB-IMPL::CALL-WITH-PACKAGE-GRAPH #<CLOSURE (FLET SB-IMPL::THUNK :IN SB-IMPL::%DEFPACKAGE) {7FFFE4244B6B}>)
  6: (SB-IMPL::%DEFPACKAGE "CLIM-INTERNALS" ("CLIMI") NIL NIL NIL ("CLIM" "CLIM-SYS" "CLIM-EXTENSIONS" "CLIM-BACKEND" "CLIM-LISP") (("ALEXANDRIA" "ENSURE-GETHASH")) ("LETF") NIL ("CLIM-INTERNALS") NIL NIL ..
  7: (SB-FASL::LOAD-FASL-GROUP #S(SB-FASL::FASL-INPUT :STREAM #<SB-SYS:FD-STREAM for "file /home/stacksmith/.cache/common-lisp/sbcl-1.3.8-linux-x64/home/stacksmith/2016/lisp/McCLIM/package.fasl" {100DDE958..
  8: (SB-FASL::LOAD-AS-FASL #<SB-SYS:FD-STREAM for "file /home/stacksmith/.cache/common-lisp/sbcl-1.3.8-linux-x64/home/stacksmith/2016/lisp/McCLIM/package.fasl" {100DDE9583}> NIL NIL)
  9: ((FLET SB-FASL::LOAD-STREAM :IN LOAD) #<SB-SYS:FD-STREAM for "file /home/stacksmith/.cache/common-lisp/sbcl-1.3.8-linux-x64/home/stacksmith/2016/lisp/McCLIM/package.fasl" {100DDE9583}> T)
 10: (LOAD #P"/home/stacksmith/.cache/common-lisp/sbcl-1.3.8-linux-x64/home/stacksmith/2016/lisp/McCLIM/package.fasl" :VERBOSE NIL :PRINT NIL :IF-DOES-NOT-EXIST T :EXTERNAL-FORMAT :DEFAULT)
 11: (UIOP/UTILITY:CALL-WITH-MUFFLED-CONDITIONS #<CLOSURE (LAMBDA NIL :IN UIOP/LISP-BUILD:LOAD*) {100DDE716B}> ("Overwriting already existing readtable ~S." #(#:FINALIZERS-OFF-WARNING :ASDF-FINALIZERS)))
 12: ((SB-PCL::EMF ASDF/ACTION:PERFORM) #<unavailable argument> #<unavailable argument> #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/LISP-ACTION:CL-SOURCE-FILE "clim-lisp" "package">)
 13: ((:METHOD ASDF/ACTION:PERFORM-WITH-RESTARTS (ASDF/LISP-ACTION:LOAD-OP ASDF/LISP-ACTION:CL-SOURCE-FILE)) #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/LISP-ACTION:CL-SOURCE-FILE "clim-lisp" "package">) [fast-met..
 14: ((:METHOD ASDF/ACTION:PERFORM-WITH-RESTARTS :AROUND (T T)) #<ASDF/LISP-ACTION:LOAD-OP > #<ASDF/LISP-ACTION:CL-SOURCE-FILE "clim-lisp" "package">) [fast-method]
 15: ((:METHOD ASDF/PLAN:PERFORM-PLAN (LIST)) ((#1=#<ASDF/LISP-ACTION:PREPARE-OP > . #2=#<ASDF/SYSTEM:SYSTEM #3="trivial-gray-streams">) (#1# . #4=#<ASDF/LISP-ACTION:CL-SOURCE-FILE #3# "package">) (#5=#<AS..
 16: ((FLET SB-C::WITH-IT :IN SB-C::%WITH-COMPILATION-UNIT))
 17: ((:METHOD ASDF/PLAN:PERFORM-PLAN :AROUND (T)) ((#1=#<ASDF/LISP-ACTION:PREPARE-OP > . #2=#<ASDF/SYSTEM:SYSTEM #3="trivial-gray-streams">) (#1# . #4=#<ASDF/LISP-ACTION:CL-SOURCE-FILE #3# "package">) (#5..
 18: ((FLET SB-C::WITH-IT :IN SB-C::%WITH-COMPILATION-UNIT))
 19: ((:METHOD ASDF/PLAN:PERFORM-PLAN :AROUND (T)) #<ASDF/PLAN:SEQUENTIAL-PLAN {100AB45593}> :VERBOSE NIL) [fast-method]
 --more--
@TeMPOraL

This comment has been minimized.

Show comment
Hide comment
@TeMPOraL

TeMPOraL Oct 5, 2016

Looks to me that Alexandria is referenced in package.lisp in an :import-from clause, but it's not loaded anywhere; in particular, it's not present in :depends-on clause in the mcclim.asd file.

TeMPOraL commented Oct 5, 2016

Looks to me that Alexandria is referenced in package.lisp in an :import-from clause, but it's not loaded anywhere; in particular, it's not present in :depends-on clause in the mcclim.asd file.

@dkochmanski

This comment has been minimized.

Show comment
Hide comment
@dkochmanski

dkochmanski Oct 5, 2016

Collaborator

yes, that was me being sloppy, thanks! (last commit fixes this)

Collaborator

dkochmanski commented Oct 5, 2016

yes, that was me being sloppy, thanks! (last commit fixes this)

@dkochmanski

This comment has been minimized.

Show comment
Hide comment
@dkochmanski

dkochmanski Oct 5, 2016

Collaborator

@jorams I wasn't aware about that, will check it for sure. Thanks.

Collaborator

dkochmanski commented Oct 5, 2016

@jorams I wasn't aware about that, will check it for sure. Thanks.

@stacksmith

This comment has been minimized.

Show comment
Hide comment
@stacksmith

stacksmith Oct 6, 2016

@jorams, @dkochmanski - it seems that neither McCLIM nor clx-truetype render fonts using sub-pixel antialiasing that makes all the difference visually. This compares McCLIM's font selector demo font with my emacs font (Make sure your browser is not zooming - in firefox, C-0)

here

and magnified

here

Note the top pixel line of the non-rgb antialiased font makes it look really unfortunate...

I am trying to figure it out... xrender supports it...

OK, CLX-TRUETYPE officially does not support it:

TrueType hints are not supported.
RGB antialiasing is not supported.
Text rendering do not use XRender glyph sets. 

CL-CAIRO2 does not seem to do RGB subpixel, or at least I could not coax it to do so.

stacksmith commented Oct 6, 2016

@jorams, @dkochmanski - it seems that neither McCLIM nor clx-truetype render fonts using sub-pixel antialiasing that makes all the difference visually. This compares McCLIM's font selector demo font with my emacs font (Make sure your browser is not zooming - in firefox, C-0)

here

and magnified

here

Note the top pixel line of the non-rgb antialiased font makes it look really unfortunate...

I am trying to figure it out... xrender supports it...

OK, CLX-TRUETYPE officially does not support it:

TrueType hints are not supported.
RGB antialiasing is not supported.
Text rendering do not use XRender glyph sets. 

CL-CAIRO2 does not seem to do RGB subpixel, or at least I could not coax it to do so.

@dkochmanski

This comment has been minimized.

Show comment
Hide comment
@dkochmanski

dkochmanski Oct 6, 2016

Collaborator

XRender is an extension which we use to draw fonts ourself (using cl-vectors etc.).

Excerpt from the McCLIM truetype extension readme:

TODO

  • Kerning (we didn't do this with Freetype, either. Oops.)
  • Implement fixed-font-width-p for zpb-ttf.
  • Boxes for missing glyphs.
  • Make certain left/right bearings and text-bounding-rectangle are
    correct. (I doubt they are..)

Wish-list

  • Subpixel antialiasing. It would be straightforward to generate the
    glyphs by tripling the width as passed to cl-vectors and compressing
    triplets of pixels together ourselves. I'm not certain how to draw
    the result through xrender. I've seen hints on Google that there is
    subpixel AA support in xrender, which isn't obvious from CLX or the
    spec. Failing that, we could use a 24bpp mask with component-alpha.
    That might even be how you're supposed to do it. I'm skeptical as to
    whether this would be accelerated for most people.
  • Subpixel positioning. Not hard in principle - render multiple versions
    of each glyph, offset by fractions of a pixel. Horizontal positioning
    is more important than vertical, so 1/4 pixel horizontal resolution
    and 1 pixel vertical resolution should suffice. Given how ugly most
    CLIM apps are, and the lack of WYSIWYG document editors crying out
    for perfect text spacing in small fonts, we don't really need this.
Collaborator

dkochmanski commented Oct 6, 2016

XRender is an extension which we use to draw fonts ourself (using cl-vectors etc.).

Excerpt from the McCLIM truetype extension readme:

TODO

  • Kerning (we didn't do this with Freetype, either. Oops.)
  • Implement fixed-font-width-p for zpb-ttf.
  • Boxes for missing glyphs.
  • Make certain left/right bearings and text-bounding-rectangle are
    correct. (I doubt they are..)

Wish-list

  • Subpixel antialiasing. It would be straightforward to generate the
    glyphs by tripling the width as passed to cl-vectors and compressing
    triplets of pixels together ourselves. I'm not certain how to draw
    the result through xrender. I've seen hints on Google that there is
    subpixel AA support in xrender, which isn't obvious from CLX or the
    spec. Failing that, we could use a 24bpp mask with component-alpha.
    That might even be how you're supposed to do it. I'm skeptical as to
    whether this would be accelerated for most people.
  • Subpixel positioning. Not hard in principle - render multiple versions
    of each glyph, offset by fractions of a pixel. Horizontal positioning
    is more important than vertical, so 1/4 pixel horizontal resolution
    and 1 pixel vertical resolution should suffice. Given how ugly most
    CLIM apps are, and the lack of WYSIWYG document editors crying out
    for perfect text spacing in small fonts, we don't really need this.

@dkochmanski dkochmanski merged commit f7faabe into master Oct 22, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment