From 5b6856798509ef9c3e10b1d600196e3842d5dca2 Mon Sep 17 00:00:00 2001 From: Kibum Kim Date: Sat, 7 Jan 2012 00:49:18 +0900 Subject: [PATCH] Git init --- AUTHORS | 7 + COPYING | 262 +++ ChangeLog | 1768 ++++++++++++++++++ Makefile.am | 56 + README | 25 + autogen.sh | 12 + configure.ac | 213 +++ debian/README.source | 73 + debian/changelog | 300 +++ debian/compat | 1 + debian/control | 69 + debian/copyright | 265 +++ debian/libxfont-dev.install | 5 + debian/libxfont1-udeb.install | 2 + debian/libxfont1.install | 2 + debian/rules | 104 ++ debian/watch | 2 + debian/xsfbs/repack.sh | 32 + debian/xsfbs/xsfbs.mk | 276 +++ debian/xsfbs/xsfbs.sh | 622 +++++++ doc/Makefile.am | 66 + doc/fontlib.css | 41 + doc/fontlib.xml | 659 +++++++ doc/fontlib.xsl | 32 + include/X11/fonts/bdfint.h | 87 + include/X11/fonts/bitmap.h | 101 + include/X11/fonts/bufio.h | 83 + include/X11/fonts/fntfil.h | 179 ++ include/X11/fonts/fntfilio.h | 53 + include/X11/fonts/fntfilst.h | 193 ++ include/X11/fonts/fontconf.h.in | 49 + include/X11/fonts/fontencc.h | 35 + include/X11/fonts/fontmisc.h | 100 + include/X11/fonts/fontshow.h | 35 + include/X11/fonts/fontutil.h | 24 + include/X11/fonts/fontxlfd.h | 97 + include/X11/fonts/pcf.h | 97 + packaging/libXfont.spec | 93 + src/FreeType/Makefile.am | 15 + src/FreeType/ft.h | 87 + src/FreeType/ftenc.c | 239 +++ src/FreeType/ftfuncs.c | 3924 +++++++++++++++++++++++++++++++++++++++ src/FreeType/ftfuncs.h | 189 ++ src/FreeType/fttools.c | 140 ++ src/FreeType/xttcap.c | 705 +++++++ src/FreeType/xttcap.h | 130 ++ src/Makefile.am | 68 + src/bitmap/Makefile.am | 19 + src/bitmap/bdfread.c | 955 ++++++++++ src/bitmap/bdfutils.c | 336 ++++ src/bitmap/bitmap.c | 157 ++ src/bitmap/bitmapfunc.c | 254 +++ src/bitmap/bitmaputil.c | 229 +++ src/bitmap/bitscale.c | 1691 +++++++++++++++++ src/bitmap/fontink.c | 216 +++ src/bitmap/pcfread.c | 780 ++++++++ src/bitmap/pcfwrite.c | 466 +++++ src/bitmap/snfread.c | 508 +++++ src/bitmap/snfstr.h | 182 ++ src/builtins/Makefile.am | 17 + src/builtins/buildfont | 14 + src/builtins/builtin.h | 62 + src/builtins/dir.c | 208 +++ src/builtins/file.c | 130 ++ src/builtins/fonts.c | 1252 +++++++++++++ src/builtins/fpe.c | 91 + src/builtins/render.c | 132 ++ src/dummy.c | 0 src/fc/Makefile.am | 16 + src/fc/fsconvert.c | 719 +++++++ src/fc/fserve.c | 3198 +++++++++++++++++++++++++++++++ src/fc/fserve.h | 91 + src/fc/fservestr.h | 200 ++ src/fc/fsio.c | 451 +++++ src/fc/fsio.h | 178 ++ src/fc/fslibos.h | 218 +++ src/fc/fstrans.c | 28 + src/fontfile/Makefile.am | 29 + src/fontfile/bitsource.c | 171 ++ src/fontfile/bufio.c | 203 ++ src/fontfile/bunzip2.c | 174 ++ src/fontfile/catalogue.c | 476 +++++ src/fontfile/decompress.c | 408 ++++ src/fontfile/defaults.c | 74 + src/fontfile/dirfile.c | 492 +++++ src/fontfile/fileio.c | 91 + src/fontfile/filewr.c | 62 + src/fontfile/fontdir.c | 825 ++++++++ src/fontfile/fontencc.c | 76 + src/fontfile/fontfile.c | 1136 ++++++++++++ src/fontfile/fontscale.c | 437 +++++ src/fontfile/gunzip.c | 225 +++ src/fontfile/register.c | 62 + src/fontfile/renderers.c | 114 ++ src/stubs/Makefile.am | 25 + src/stubs/cauthgen.c | 14 + src/stubs/csignal.c | 14 + src/stubs/delfntcid.c | 13 + src/stubs/errorf.c | 13 + src/stubs/fatalerror.c | 13 + src/stubs/findoldfnt.c | 14 + src/stubs/getcres.c | 14 + src/stubs/getdefptsize.c | 14 + src/stubs/getnewfntcid.c | 14 + src/stubs/gettime.c | 14 + src/stubs/initfshdl.c | 15 + src/stubs/regfpefunc.c | 28 + src/stubs/rmfshdl.c | 15 + src/stubs/servclient.c | 10 + src/stubs/setfntauth.c | 14 + src/stubs/stfntcfnt.c | 14 + src/stubs/stubs.h | 41 + src/util/Makefile.am | 19 + src/util/atom.c | 242 +++ src/util/fontaccel.c | 104 ++ src/util/fontnames.c | 119 ++ src/util/fontutil.c | 410 ++++ src/util/fontxlfd.c | 632 +++++++ src/util/format.c | 124 ++ src/util/miscutil.c | 61 + src/util/patcache.c | 218 +++ src/util/private.c | 105 ++ src/util/utilbitmap.c | 185 ++ xfont.pc.in | 13 + 124 files changed, 32001 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100755 ChangeLog create mode 100755 Makefile.am create mode 100644 README create mode 100644 autogen.sh create mode 100755 configure.ac create mode 100644 debian/README.source create mode 100755 debian/changelog create mode 100644 debian/compat create mode 100755 debian/control create mode 100644 debian/copyright create mode 100755 debian/libxfont-dev.install create mode 100644 debian/libxfont1-udeb.install create mode 100644 debian/libxfont1.install create mode 100755 debian/rules create mode 100644 debian/watch create mode 100644 debian/xsfbs/repack.sh create mode 100644 debian/xsfbs/xsfbs.mk create mode 100644 debian/xsfbs/xsfbs.sh create mode 100755 doc/Makefile.am create mode 100644 doc/fontlib.css create mode 100755 doc/fontlib.xml create mode 100644 doc/fontlib.xsl create mode 100755 include/X11/fonts/bdfint.h create mode 100755 include/X11/fonts/bitmap.h create mode 100755 include/X11/fonts/bufio.h create mode 100755 include/X11/fonts/fntfil.h create mode 100755 include/X11/fonts/fntfilio.h create mode 100755 include/X11/fonts/fntfilst.h create mode 100755 include/X11/fonts/fontconf.h.in create mode 100755 include/X11/fonts/fontencc.h create mode 100755 include/X11/fonts/fontmisc.h create mode 100755 include/X11/fonts/fontshow.h create mode 100755 include/X11/fonts/fontutil.h create mode 100755 include/X11/fonts/fontxlfd.h create mode 100755 include/X11/fonts/pcf.h create mode 100644 packaging/libXfont.spec create mode 100644 src/FreeType/Makefile.am create mode 100755 src/FreeType/ft.h create mode 100755 src/FreeType/ftenc.c create mode 100755 src/FreeType/ftfuncs.c create mode 100755 src/FreeType/ftfuncs.h create mode 100755 src/FreeType/fttools.c create mode 100755 src/FreeType/xttcap.c create mode 100755 src/FreeType/xttcap.h create mode 100755 src/Makefile.am create mode 100755 src/bitmap/Makefile.am create mode 100755 src/bitmap/bdfread.c create mode 100755 src/bitmap/bdfutils.c create mode 100755 src/bitmap/bitmap.c create mode 100755 src/bitmap/bitmapfunc.c create mode 100755 src/bitmap/bitmaputil.c create mode 100755 src/bitmap/bitscale.c create mode 100755 src/bitmap/fontink.c create mode 100755 src/bitmap/pcfread.c create mode 100755 src/bitmap/pcfwrite.c create mode 100755 src/bitmap/snfread.c create mode 100755 src/bitmap/snfstr.h create mode 100644 src/builtins/Makefile.am create mode 100644 src/builtins/buildfont create mode 100755 src/builtins/builtin.h create mode 100644 src/builtins/dir.c create mode 100755 src/builtins/file.c create mode 100755 src/builtins/fonts.c create mode 100755 src/builtins/fpe.c create mode 100755 src/builtins/render.c create mode 100644 src/dummy.c create mode 100644 src/fc/Makefile.am create mode 100755 src/fc/fsconvert.c create mode 100755 src/fc/fserve.c create mode 100755 src/fc/fserve.h create mode 100755 src/fc/fservestr.h create mode 100755 src/fc/fsio.c create mode 100755 src/fc/fsio.h create mode 100755 src/fc/fslibos.h create mode 100644 src/fc/fstrans.c create mode 100644 src/fontfile/Makefile.am create mode 100755 src/fontfile/bitsource.c create mode 100755 src/fontfile/bufio.c create mode 100755 src/fontfile/bunzip2.c create mode 100755 src/fontfile/catalogue.c create mode 100755 src/fontfile/decompress.c create mode 100755 src/fontfile/defaults.c create mode 100755 src/fontfile/dirfile.c create mode 100755 src/fontfile/fileio.c create mode 100755 src/fontfile/filewr.c create mode 100755 src/fontfile/fontdir.c create mode 100755 src/fontfile/fontencc.c create mode 100755 src/fontfile/fontfile.c create mode 100755 src/fontfile/fontscale.c create mode 100755 src/fontfile/gunzip.c create mode 100644 src/fontfile/register.c create mode 100755 src/fontfile/renderers.c create mode 100644 src/stubs/Makefile.am create mode 100644 src/stubs/cauthgen.c create mode 100644 src/stubs/csignal.c create mode 100644 src/stubs/delfntcid.c create mode 100644 src/stubs/errorf.c create mode 100644 src/stubs/fatalerror.c create mode 100644 src/stubs/findoldfnt.c create mode 100644 src/stubs/getcres.c create mode 100644 src/stubs/getdefptsize.c create mode 100644 src/stubs/getnewfntcid.c create mode 100644 src/stubs/gettime.c create mode 100644 src/stubs/initfshdl.c create mode 100644 src/stubs/regfpefunc.c create mode 100644 src/stubs/rmfshdl.c create mode 100644 src/stubs/servclient.c create mode 100644 src/stubs/setfntauth.c create mode 100644 src/stubs/stfntcfnt.c create mode 100755 src/stubs/stubs.h create mode 100644 src/util/Makefile.am create mode 100755 src/util/atom.c create mode 100755 src/util/fontaccel.c create mode 100755 src/util/fontnames.c create mode 100755 src/util/fontutil.c create mode 100755 src/util/fontxlfd.c create mode 100755 src/util/format.c create mode 100755 src/util/miscutil.c create mode 100755 src/util/patcache.c create mode 100755 src/util/private.c create mode 100755 src/util/utilbitmap.c create mode 100644 xfont.pc.in diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..05edf1e --- /dev/null +++ b/AUTHORS @@ -0,0 +1,7 @@ +Keith Packard, MIT X Consortium and SuSE, Inc. +Dave Lemke, Network Computing Devices (font server) +Mark Leisher, Juliusz Chroboczek, (Freetype) +Digital Equipment Corporation (bitmap) (Phil Karlton or Susan Angebrandt???) +Shunsuke Akiyama (TrueType) + +Our apologies if anyone has been missed. diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..b271bf3 --- /dev/null +++ b/COPYING @@ -0,0 +1,262 @@ +Copyright © 2007 Red Hat, Inc +Copyright © 2008,2009 Sun Microsystems, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +Copyright (c) 1997 by Mark Leisher +Copyright (c) 1998-2003 by Juliusz Chroboczek +Copyright (c) 1998 Go Watanabe, All rights reserved. +Copyright (c) 1998 Kazushi (Jam) Marukawa, All rights reserved. +Copyright (c) 1998 Takuya SHIOZAKI, All rights reserved. +Copyright (c) 1998 X-TrueType Server Project, All rights reserved. +Copyright (c) 2003-2004 After X-TT Project, All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + + +Copyright 1999 SuSE, Inc. + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the name of SuSE not be used in advertising or +publicity pertaining to distribution of the software without specific, +written prior permission. SuSE makes no representations about the +suitability of this software for any purpose. It is provided "as is" +without express or implied warranty. + +SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE +BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +Copyright 1990 Network Computing Devices + +Permission to use, copy, modify, distribute, and sell this software and +its documentation for any purpose is hereby granted without fee, provided +that the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the name of Network Computing Devices not be used +in advertising or publicity pertaining to distribution of the software +without specific, written prior permission. Network Computing Devices +makes no representations about the suitability of this software for any +purpose. It is provided "as is" without express or implied warranty. + +NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, +IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE +OR PERFORMANCE OF THIS SOFTWARE. + + +Copyright 1990 Network Computing Devices + +Permission to use, copy, modify, distribute, and sell this software and +its documentation for any purpose is hereby granted without fee, provided +that the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the names of Network Computing Devices, or Digital +not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +NETWORK COMPUTING DEVICES, AND DIGITAL AND DISCLAIM ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, +OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + + +[Note: clause 3 in the following license, the "advertising clause", was +rescinded by Berkeley in 1999. See +] + +Copyright (c) 1991, 1993 + The Regents of the University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by the University of + California, Berkeley and its contributors. +4. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + + +Copyright (c) 1998-1999 Shunsuke Akiyama . +All rights reserved. +Copyright (c) 1998-1999 X-TrueType Server Project, All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + + +Copyright © 2004 Keith Packard + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the name of Keith Packard not be used in +advertising or publicity pertaining to distribution of the software without +specific, written prior permission. Keith Packard makes no +representations about the suitability of this software for any purpose. It +is provided "as is" without express or implied warranty. + +KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + + +/* lib/font/fontfile/gunzip.c + written by Mark Eichin September 1996. + intended for inclusion in X11 public releases. */ + + +Copyright (c) 1999 The XFree86 Project Inc. + +All Rights Reserved. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The XFree86 Project +Inc. shall not be used in advertising or otherwise to promote the +sale, use or other dealings in this Software without prior written +authorization from The XFree86 Project Inc.. diff --git a/ChangeLog b/ChangeLog new file mode 100755 index 0000000..b734a4a --- /dev/null +++ b/ChangeLog @@ -0,0 +1,1768 @@ +commit 12157fbebc35c2d039df2df4fc5ac2b299eeec03 +Author: Alan Coopersmith +Date: Thu Oct 28 20:43:27 2010 -0700 + + libXfont 1.4.3 + + Signed-off-by: Alan Coopersmith + +commit f29f1d68d7eca96e45ba3758686be07993d82e03 +Author: Jesse Adkins +Date: Tue Sep 28 13:30:02 2010 -0700 + + Purge cvs tags. + + Signed-off-by: Jesse Adkins + Signed-off-by: Alan Coopersmith + +commit 6628b4d82426cf9ac240da363cd8a8252e6f71ef +Author: Jeremy Huddleston +Date: Mon Sep 27 12:31:50 2010 -0700 + + FreeType: Cleanup MUMBLE and fix printing of XLFD in debug spew. + + Signed-off-by: Jeremy Huddleston + +commit c482a2c104aa5cd1a265c2ca310a308dcc418fe7 +Author: Yaakov Selkowitz +Date: Wed Apr 14 05:58:28 2010 -0500 + + Revert "Bug #6247: Fix build on Cygwin" + + libtool requires the '-no-undefined' flag in order to create shared + libraries on PE/COFF platforms (Cygwin/MinGW); on other platforms this + flag has no effect. + + The problem with libXfont is that PE weak symbols do not behave exactly + as they do on ELF platforms. Since PE binaries (both executables and + libraries) must have all symbols resolved at link time, there is no way + for the real symbols in xserver to "displace" those in libXfont at + runtime, so the result is that libXfont uses its stubs, which do + nothing, and xserver ends up unable to find its fonts. + + Solving this will require either significant changes to libXfont or some + major improvement to the toolchain to handle this case. Until that + happens, removing '-no-undefined' will result in a static-only library + on these platforms, which is the only currently working solution. + + http://sourceware.org/bugzilla/show_bug.cgi?id=11306 + http://cygwin.com/ml/cygwin/2010-04/msg00281.html + + This reverts commit 69c4ae1e3e14a58bc2eb9b9b8820dc7183b82a67. + + Conflicts: + + ChangeLog + + Signed-off-by: Yaakov Selkowitz + +commit 455ec66e82e3c4bedd9e789d2ab33030b8e64ffa +Author: Alan Coopersmith +Date: Sun Aug 8 00:19:36 2010 -0700 + + Fix builds with Sun compilers + + Sun compilers use #pragma weak in the *.c files to declare weak symbols, + so should have weak defined to empty, but not define NO_WEAK_SYMBOLS + + Signed-off-by: Alan Coopersmith + +commit 0386fa77367a305deea3cc27f8a3865cc3c467c0 +Author: Jeremy Huddleston +Date: Sat Jul 10 10:08:21 2010 -0700 + + darwin: Fix build regression introduced by previous patch + + Signed-off-by: Jeremy Huddleston + +commit 8f75706901da0141590d46f0f898e5678feac953 +Author: Jon TURNEY +Date: Mon Jun 28 17:56:07 2010 +0100 + + Build fix for platforms which don't have weak linkage + + Since we fix this by removing the serverGeneration symbol, assuming + an external definition will be provided, this means on Windows libXfont + can only be built as a static library (since PE shared libraries cannot + contain undefined symbols). This produces a libXfont which might only + be useful to the xserver, but the only other users we might care about + are xfs, which is obsolete, and bdftopcf, which fortunately doesn't + pull in any objects which reference serverGeneration from libXfont. + + Signed-off-by: Jon TURNEY + Reviewed-by: Colin Harrison + +commit 5c49c956e9c85d89f6b2e719eb9b6fbde62c2f72 +Author: Gaetan Nadon +Date: Mon Jun 28 13:18:22 2010 -0400 + + doc: use xorg-docs xorg.css stylesheet + + Use latest DocBook XML util-macros infrastructure + + Signed-off-by: Gaetan Nadon + +commit 27270de56f7da5e047784434f3b29fa672f97ffd +Author: Tiago Vignatti +Date: Thu Jun 10 16:29:37 2010 +0300 + + libXfont 1.4.2 + + Signed-off-by: Tiago Vignatti + Reviewed-by: Mikhail Gusarov + Reviewed-by: Alex Deucher + Reviewed-by: Daniel Stone + +commit a85f4fc6142349517aaa4cf6bc8049e2d85c1006 +Author: Tiago Vignatti +Date: Thu Jun 10 16:18:05 2010 +0300 + + Use one single function to register fpe functions + + X server doesn't need to understand fpe internals, so let it transparent + turning all registration functions in a single one. For that, fill the already + existent register_fpe_functions(). + + Some X servers don't want font server support, so this patch also sets font + server support to be configured in build time. + + In my machine, I see 20kB of RSS being saved in libXfont mapped in Xorg + process when I disabled font server support and other kind of fonts in the + library (--disable-pcfformat --disable-bdfformat --disable-snfformat + --disable-freetype --disable-fc). + + The default library built was taking: + text data bss dec hex filename + 261847 4484 1536 267867 4165b ./lib/libXfont.so + + and with these flags, it jumps to: + text data bss dec hex filename + 157764 2428 1188 161380 27664 ./lib/libXfont.so + + Signed-off-by: Tiago Vignatti + Reviewed-by: Mikhail Gusarov + Reviewed-by: Alex Deucher + Reviewed-by: Daniel Stone + +commit d137c81b83e0a6f68989c37035d0c950bb43fcc5 +Author: Gaetan Nadon +Date: Thu Apr 1 14:12:47 2010 -0400 + + config: fontconf.h.in is redundant in EXTRA_DIST + + Output files listed in AC_CONFIG_HEADERS or AC_OUTPUT have + their input files (typically .in) included in the tarball. + + Reviewed-by: Dan Nicholson + Signed-off-by: Gaetan Nadon + +commit d8d901323776599c8392f9b973ba129c3af45a4b +Author: Gaetan Nadon +Date: Tue Mar 30 09:26:13 2010 -0400 + + config: replace obsolete AM_CONFIG_HEADER with AC_CONFIG_HEADERS + + There are 2 headers to generate. The first one (config.h) + is picked up by autoheader to generate the familiar config.h.in + input file. The others in the list (or in subsequent AC_CONFIG_HEADERS + macro calls) are generated from their existing matching template, + e.g. fontconf.h.in. + + When multiple headers are listed in the same macro call, + they cannot be separated by a new line like we do in AC_OUTPUT. + + Reviewed-by: Dan Nicholson + Signed-off-by: Gaetan Nadon + +commit df94cb141f02f123a64b0ef7abf5f593c1b27e13 +Author: Gaetan Nadon +Date: Wed Mar 31 20:21:47 2010 -0400 + + Revert "config: replace obsolete AM_CONFIG_HEADER with AC_CONFIG_HEADERS" + + This reverts commit 8e84687b26be6e8f5da4fce173c0a134eb07f4f3. + + Until the issue is resolved on MAC O/S + http://tinderbox.x.org/builds/2010-03-31-0030/logs/libXfont/ + +commit 8e84687b26be6e8f5da4fce173c0a134eb07f4f3 +Author: Gaetan Nadon +Date: Tue Mar 30 09:26:13 2010 -0400 + + config: replace obsolete AM_CONFIG_HEADER with AC_CONFIG_HEADERS + + Both headers end up created by the same macro. + + Reviewed-by: Dan Nicholson + Signed-off-by: Gaetan Nadon + +commit a7b7bc72b9ad061ed164601d2d18dbffd6ec1f4f +Author: Gaetan Nadon +Date: Mon Mar 29 14:53:48 2010 -0400 + + config: remove the pkgconfig pc.in file from EXTRA_DIST + + Automake always includes it in the tarball. + + Signed-off-by: Gaetan Nadon + +commit f77258d0b286c2fd2a2fee36e42280016e310b10 +Author: Gaetan Nadon +Date: Sat Mar 27 17:06:34 2010 -0400 + + config: remove protection for AS_HELP_STRING for old autoconf + + No longer needed as modules will not configure with 2.57. + AS_HELP_STRING was introduced in 2.58. The minimum level + is now 2.60. + + Reviewed-by: Jeremy Huddleston + Signed-off-by: Gaetan Nadon + +commit a79a22bfcb344c47f2659e4178fd79f8555fbcfd +Author: Gaetan Nadon +Date: Thu Mar 11 10:11:23 2010 -0500 + + doc: specify 0.0.20 as the minimum version for xmlto + + Older versions do not have fop backend. + + Signed-off-by: Gaetan Nadon + +commit a76488f75f23b8e08763e28b2fa56352e7b04e19 +Author: Gaetan Nadon +Date: Sat Jan 30 13:13:33 2010 -0500 + + doc: use new macros to control doc generation + + Namely XORG_WITH_FOP for the fop backend (pdf) and + XORG_ENABLE_DEVEL_DOCS for the generation of all docs + + Signed-off-by: Gaetan Nadon + +commit 360f10333ac19f033ea64a8360c4886fbb657890 +Author: Gaetan Nadon +Date: Wed Jan 20 11:46:21 2010 -0500 + + config: replace custom code with reusable macro XORG_WITH_XMLTO + + XORG_WITH_XMLTO provides additional functions like a configure + option which allow platform builders to control the usage of + the xmlto program. + + This is a requirement from platforms that do not have such doc tool. + + Signed-off-by: Gaetan Nadon + +commit 24a257ca5b70e168564f0c6527e60bb06b61be8c +Author: Alan Coopersmith +Date: Thu Jan 14 21:39:11 2010 -0800 + + Update Sun license notices to current X.Org standard form + + Signed-off-by: Alan Coopersmith + +commit d1c9028a410a10ef1b27c990f55de836eb948887 +Author: Gaetan Nadon +Date: Fri Nov 27 20:56:04 2009 -0500 + + Makefile.am: add ChangeLog and INSTALL on MAINTAINERCLEANFILES + + Now that the INSTALL file is generated. + Allows running make maintainer-clean. + +commit 72353a449e8dbf82a53a1d7958755198e989d892 +Author: Gaetan Nadon +Date: Wed Oct 28 15:28:32 2009 -0400 + + configure.ac: AM_MAINTAINER_MODE missing #24238 + + This turns off maintainer mode build rules in tarballs. + Works in conjunction with autogen.sh --enable-maintainer-mode + For all X.Org components. + +commit 489e7b2cb3371042552489385902a98dc1cd976a +Author: Gaetan Nadon +Date: Wed Oct 28 14:09:10 2009 -0400 + + INSTALL, NEWS, README or AUTHORS files are missing/incorrect #24206 + + Add missing INSTALL file. Use standard GNU file on building tarball + README may have been updated + Remove AUTHORS file as it is empty and no content available yet. + Remove NEWS file as it is empty and no content available yet. + +commit c22d67cc78c27d19bb6eaba5bf71b66444ed4a40 +Author: Gaetan Nadon +Date: Tue Oct 27 15:07:25 2009 -0400 + + Deploy the new XORG_DEFAULT_OPTIONS #24242 + + This macro aggregate a number of existing macros that sets commmon + X.Org components configuration options. It shields the configuration file from + future changes. + +commit 271382b01995469eb60035d38880f9d3665d4c4c +Author: Gaetan Nadon +Date: Mon Oct 26 22:08:43 2009 -0400 + + Makefile.am: ChangeLog not required: EXTRA_DIST or *CLEANFILES #24432 + + ChangeLog filename is known to Automake and requires no further + coding in the makefile. + +commit 9be83ae94cd82b447ed59ba0869f9e94ed9018f7 +Author: Gaetan Nadon +Date: Thu Oct 22 15:34:34 2009 -0400 + + .gitignore: use common defaults with custom section # 24239 + + Using common defaults will reduce errors and maintenance. + Only the very small or inexistent custom section need periodic maintenance + when the structure of the component changes. Do not edit defaults. + +commit 489924bfb693a844f8f8ad6023fc78e4a212bef6 +Author: Yaakov Selkowitz +Date: Wed Oct 14 11:31:59 2009 -0500 + + Add -lbz2 to Libs.private if bzip2 is enabled + + This is required on Cygwin, which must link the xservers with a static + libXfont due to poor weak-symbol support. Z_LIBS includes -lz and, if + bzip2 support is enabled, -lbz2. + + Signed-off-by: Yaakov Selkowitz + Acked-by: Julien Cristau + +commit 64f21944c5f374b0da63657f01e289b34d00904c +Author: Alan Coopersmith +Date: Fri Oct 9 17:38:33 2009 -0700 + + libXfont 1.4.1 + + Signed-off-by: Alan Coopersmith + +commit 947d3162f5edaaa05bbbfcfe2303d0c8b796f9ca +Author: Alan Coopersmith +Date: Wed Oct 7 13:05:26 2009 -0700 + + Remove unused setting of ENCODINGSDIR + + Seems to have been a leftover from before the encoding code was split + out into libfontenc by XFree86 + + Signed-off-by: Alan Coopersmith + +commit 18053ffbf92473ffce23a3c5182de92b608b9cdf +Author: Alan Coopersmith +Date: Wed Oct 7 10:44:27 2009 -0700 + + Convert documentation from troff to DocBook/XML + + Signed-off-by: Alan Coopersmith + +commit 96a4daad7097ce94d4340a4e9ce779e378f9b83c +Author: Alan Coopersmith +Date: Wed Oct 7 08:31:54 2009 -0700 + + Move fontlib.ms from xorg-docs + + Signed-off-by: Alan Coopersmith + +commit b7be4a976a59f3149590cf62a2ea8144aa729c2a +Author: Alan Coopersmith +Date: Tue Oct 6 13:03:25 2009 -0700 + + Migrate to xorg macros 1.3 & XORG_DEFAULT_OPTIONS + + Signed-off-by: Alan Coopersmith + +commit 18c5e2ff1097880e8dea951079ae49a93ec315b0 +Author: Bob Ham +Date: Tue Sep 15 14:28:12 2009 +1000 + + Fixed int(*)()->double cast warning + + Signed-off-by: Peter Hutterer + +commit 0045b2555b288099c90b65f97bd4b4a5ebc8c688 +Author: Adam Jackson +Date: Wed Feb 18 13:53:14 2009 -0500 + + libXfont 1.4.0 + +commit 04ced93e997b185b5d9124cacc96fa39a77b2ab7 +Author: Peter Astrand +Date: Wed Feb 4 22:09:25 2009 +0100 + + Avoid sending uninitialized padding data over the network. + + Besides cluttering Valgrind output, this might also be an information leak. + + Signed-off-by: Peter Astrand + Signed-off-by: Alan Coopersmith + +commit e15dca77fa76252dd8499f8585d8ce922ac3b869 +Author: Paulo Cesar Pereira de Andrade +Date: Thu Jan 29 18:02:34 2009 -0200 + + Janitor: make distcheck and .gitignore + + Distribute ChangeLog but not autogen.sh. + Use a single toplevel .gitignore file, instead of one per subdirectory. + +commit 38bac54519a67ab1a276b66dbaa84a3327ccf827 +Author: Adam Jackson +Date: Sat Sep 27 02:06:27 2008 -0400 + + Remove some strcasecmp silliness + +commit f431b4eb4dc743ccdf94b1b2ed858cc21f63c091 +Author: Adam Jackson +Date: Tue Jan 20 23:23:40 2009 -0500 + + Allow case insensitive filename matching in fontfile. + + Simplify the freetype renderer list to match. + +commit 903d39aeea73a973fb8b05ca1ac147c2cca146cb +Author: Adam Jackson +Date: Tue Jan 20 23:21:29 2009 -0500 + + Delete some dead ifdefs + +commit daa7af2bb2326de363aa5ea51c29616e3634343a +Author: Adam Jackson +Date: Tue Jan 20 23:20:20 2009 -0500 + + Move the copy of CopyISOLatin1Lowered near its user, and un-weak it. + +commit 6c29007756301f513c0151e2b63af073f310af66 +Author: Adam Jackson +Date: Tue Jan 20 23:17:55 2009 -0500 + + Drop OS/2 support + +commit 0cdc9b8f850342d50b72a57507db3413eacc6fb8 +Author: Adam Jackson +Date: Tue Jan 20 23:16:35 2009 -0500 + + xalloc -> malloc, etc. + +commit 632a2e90a4b209facc84d7a18873f19a720ea7df +Author: Adam Jackson +Date: Sat Sep 27 01:30:13 2008 -0400 + + Remove PMF support. + + .pmf files are printer font metrics; they have no glyphs, just boxes for + layout. They can't possibly be useful in a post-Xprint world. + +commit e1927f80deabe0268dc18b4a9f3ceda1325171f5 +Author: Adam Jackson +Date: Tue Jan 20 22:57:35 2009 -0500 + + Remove printer font support. + + Xprint is just insidious, isn't it. + +commit 732191d5d6ad58caab25e24df16fb89efaea2e9a +Author: Adam Jackson +Date: Tue Jan 20 22:42:22 2009 -0500 + + Remove loadable renderer support. + +commit 423d0a2c1dfad969f4a238618811937bc5f49776 +Author: Adam Jackson +Date: Sat Sep 27 01:55:47 2008 -0400 + + Remove useless #define + +commit 50bca6dd881c2d787b3afa4d98a2c2667f767614 +Author: Adam Jackson +Date: Tue Jan 20 22:33:06 2009 -0500 + + Get rid of a useless array + +commit 6ba0565362ba9c8d1037c0e4725cb31faa141656 +Author: Adam Jackson +Date: Tue Jan 20 22:29:10 2009 -0500 + + const cleanup + +commit 1247f01ee36f80222e30c1678f940329aadb8335 +Author: Adam Jackson +Date: Tue Jan 20 01:13:08 2009 -0500 + + Delete Type1 + + Yes, these are still real fonts, but freetype can handle them just fine. + +commit 85b66b8a7f3095f10437c8ecb3dcbfe68c9cfced +Author: Adam Jackson +Date: Tue Jan 20 01:03:16 2009 -0500 + + Delete speedo + + OUT OUT OUT + +commit 1559d8086e8063c692aae008006578b88e1368fe +Author: Jeremy Huddleston +Date: Sun Dec 28 12:35:37 2008 -0800 + + Added missing AM_CFLAGS for -Wl,-flat_namespace + + Fixes commit f859a76b0f325b07952ad1c5c818318307c589b0 + +commit 99bad52b592f4f11887bf9033590b61880c3c976 +Author: Paulo Cesar Pereira de Andrade +Date: Sat Mar 1 16:45:55 2008 -0300 + + Disable some fun stdio wrapping. + + The code is still there but no magic with macros is attempted anymore + to handle files. + This should really be changed to just use stdio, and properly adapt + functions like T1Decript, T1eexec, etc. + +commit 95760fbe45a700ea4cc118daa536604393721a59 +Author: Alan Coopersmith +Date: Fri Dec 19 16:24:39 2008 -0800 + + Restore comment deleted by b6f793d7d5 + +commit b6f793d7d5c7f7c55911e6524dede41b92dcbc22 +Author: Paulo Cesar Pereira de Andrade +Date: Fri Mar 14 01:30:24 2008 -0300 + + libXfont ansification and removal of xf86_ansic.h dependency + + Basically the code is now compiled as if FONTMODULE was never defined, + but also removed some "magic" defining _XOPEN_SOURCE before including + math.h. + Also removed some #if 0'ed code instead of fixing prototypes inside + the "dead code". + Changes to spdo_prv.h were due to defines like: + define foo() sp_foo() + that would not compile with the ansification in the format: + type foo(void) + due to the macro receiving "void" as an argument. + +commit 282ac4226195d58e3818e7ac97093e396aa78086 +Author: Alan Coopersmith +Date: Fri Dec 19 15:07:21 2008 -0800 + + Version bump: 1.3.4 + +commit 5c631ad798fcdea4f2b7d0b012ac94182fad4184 +Author: Alan Coopersmith +Date: Fri Dec 19 14:01:28 2008 -0800 + + miscutil.c:108: warning: old-style parameter declaration + +commit d21d6c5b23a23f120f32b483ec6b86cf88cb3a98 +Author: Alan Coopersmith +Date: Fri Dec 19 13:47:48 2008 -0800 + + Add simple README with pointers to bugzilla/git/mailing list + +commit d3be1261d29b7d8eda124add3497a93ebe34712c +Author: Alan Coopersmith +Date: Fri Dec 19 13:47:27 2008 -0800 + + Update COPYING file with additional copyrights/licenses + +commit b5cc4a10c0fe365b40be19613777f192a1ada0db +Author: Alan Coopersmith +Date: Fri Dec 19 13:05:32 2008 -0800 + + Use XORG_CWARNFLAGS & XORG_CHANGELOG macros from xorg-macros 1.2 + +commit 377584bb71ccb2cc380c3a8f71f0acd7e755ad33 +Author: Alan Coopersmith +Date: Thu Dec 18 21:22:31 2008 -0800 + + Always scan catalogue dirs at startup, even if their mtime < 0 + + Works around bug in VMWare that caused the Solaris kernel to fail to read + the time-of-day chip on boot, and start with a time < 0 (i.e. back to the + 1960's) - when the system was then installed from this mode, Xorg wouldn't + start after reboot, since the mtime would be < 0 and the catalogue dir was + then skipped as not changed since reading at the 0 initially set in the + cat->mtime. + + Fixes OpenSolaris bug #4780 + + +commit 9ad7f24fafe876851b89190732034da6fb640788 +Author: Benjamin Close +Date: Thu Dec 11 15:26:13 2008 +1030 + + Make sure font names/font alias names are null terminated + + This fixes a crash upon server restart where the saved fonts were + being restored however strlen(font_name) was incorrect hence memory + was being clobbered. + +commit d93cc906d4a2f42d11629e245fb13a2d08cf2a61 +Author: Alan Coopersmith +Date: Thu Dec 4 16:56:56 2008 -0800 + + Pad CreateAC packets with 0 auths to workaround xfs bug + + Versions of xfs before commit 3fe28a31a2974287acc182c7c9bfd68d94ea6292 + will reject CreateAC packets with 0 auths unless they claim to have at + least 4 bytes of authentication data that isn't actually read. + +commit f859a76b0f325b07952ad1c5c818318307c589b0 +Author: Julien Cristau +Date: Tue Nov 4 19:24:29 2008 +0100 + + Don't clobber CFLAGS in configure + + This lets the user set CFLAGS when running make. + +commit 6bf52de1fb84d61b227daf7a7077af9ea3ec27a3 +Author: Peter Breitenlohner +Date: Mon Oct 20 19:32:23 2008 -0700 + + X.Org Bug 17945: avoid gcc warnings for libXfont + + + + Avoid two gcc warnings + src/fontfile/ffcheck.c:150: warning: initialization discards qualifiers from pointer target type + src/fontfile/register.c:98: warning: initialization discards qualifiers from pointer target type + +commit b012dcf65b1f0e41def2f595f1b1e7b06a49d275 +Author: Adam Jackson +Date: Thu Aug 28 15:36:06 2008 -0400 + + Retry font server connections faster. + +commit 8a6df69750a2d350074715fb31d9d20195d00b4c +Author: Adam Jackson +Date: Thu Aug 28 15:35:16 2008 -0400 + + Nuke fontcache. + + Hasn't been relevant since the X-TT merge ages ago. + +commit 5d5587a36453d731e9a7353a98fa391dbb51b57d +Author: Alan Coopersmith +Date: Thu Aug 21 19:58:06 2008 -0700 + + Add support for bzip2 bitmap font compression + + Code originally written for Solaris Xsun in 2003, ported now to current Xorg + + +commit 624b7a507cdea25cec0728b4679610df3fb3097c +Author: Derek Wang +Date: Thu Aug 21 16:06:51 2008 -0700 + + Sun bug 4510977: dtremote fails to start session + + + +commit 684c000e57f30344777cf763f2f1b540ef008b38 +Author: Adam Jackson +Date: Wed Jul 2 15:30:03 2008 -0400 + + libXfont 1.3.3 + +commit 11edbc3a818e15ea2b622b31e6f87159ee68ae4a +Author: Maarten ter Huurne +Date: Sat Jun 28 15:34:50 2008 -0400 + + Do not call FT_Get_BDF_Charset_ID() if configured with --disable-bdfformat + + When I configure libXfont-1.3.2 with --disable-bdfformat and link it against + FreeType that is built without BDF support, I get the following link error: + + libXfont.so: undefined reference to ‘FT_Get_BDF_Charset_ID’ + + I fixed it by checking XFONT_BDFFORMAT and if BDF support is disabled, the call + to FT_Get_BDF_Charset_ID() is omitted and the result code is set as if the call + had failed. + + Signed-off-by: James Cloos + +commit 1ab07ce0eec4f6c7ed66c7aba3edf8c4315dd907 +Author: Alan Coopersmith +Date: Tue May 13 17:26:57 2008 -0700 + + FontFileDirectoryChanged: check length of "fonts.alias" as well as "fonts.dir" + +commit 0f9db4aa7de6e0644ac9c5811b949e5f936c9d61 +Author: Alan Coopersmith +Date: Fri May 9 12:36:30 2008 -0700 + + Don't allow a font alias to point to itself and create a loop + + Part of fix for Sun bug 4258475 + + +commit 67311922a2e02d8a763831831b65bb4833db58b5 +Author: Colin Harrison +Date: Mon May 5 22:17:55 2008 +0100 + + Fix build for WIN32 + +commit 6ba408c956ca8e241d10d463c45b4e987b757333 +Author: Matthieu Herrb +Date: Sun Mar 9 08:21:34 2008 +0100 + + nuke RCS Ids + +commit 754cabe62e91b9ad50c3027c063f4269775f7add +Author: Julien Cristau +Date: Fri Mar 7 12:19:22 2008 +0100 + + Add missing include in src/FreeType/ftfuncs.c + + Fixes compiler warning: + ../../../src/FreeType/ftfuncs.c: In function 'restrict_code_range_by_str': + ../../../src/FreeType/ftfuncs.c:2081: warning: implicit declaration of function 'isspace' + +commit 0fd2a1428df56d8b29e148b08dcec2dfed9302fa +Author: Adam Jackson +Date: Wed Mar 5 22:04:06 2008 -0500 + + libXfont 1.3.2 + +commit b76df66d2c507898472bba0f9986ef5700029a36 +Author: Matthieu Herrb +Date: Thu Jan 17 15:30:37 2008 +0100 + + Fix for CVE-2008-0006 - PCF Font parser buffer overflow. + +commit 2297c6390a1609fe810c2cd5b3443f3722610944 +Author: Matthieu Herrb +Date: Thu Oct 18 21:46:49 2007 +0200 + + ftsystem.c is not needed anymore. + +commit 5bf703700ee4a5d6eae20da07cb7a29369667aef +Author: Matthieu Herrb +Date: Fri Sep 28 08:17:57 2007 +0200 + + catalogue.c: prevent a one character overflow + + this occurs if readlink writes a result that's exactly the + size of the buffer that's passed to it. Reported by + Joerg Sonnenberger. + + Re + +commit fd8a03fbbd74f5cbaa740e5d50fccdf5c1f78b5b +Author: Jens Granseuer +Date: Thu Sep 27 23:12:00 2007 +0200 + + fix build with gcc 2.95. + + In addition to fixing the C89 issue, the patch also flags a few functions as + static to avoid "no previous prototype" warnings. + +commit 268f1bb1859e97944e8b63a5bb12677e874ed144 +Author: Tilman Sauerbeck +Date: Thu Sep 13 20:40:26 2007 +0200 + + Replaced one instance of bcopy() with memcpy(). + + f->buffer cannot overlap with io->file->bits, so it's safe to + use memcpy() rather than memmove(). + Compile-tested only. + +commit f2725a5c9da771fb610d503ebfda3b4d1553bac4 +Author: Eric Anholt +Date: Wed Sep 5 13:10:43 2007 -0700 + + Bump version to 1.3.1. + +commit aca95d12a8b35de7ae914632fc9e8a723d58a860 +Author: Matthieu Herrb +Date: Sat Aug 25 23:32:54 2007 +0200 + + Kill unused macro definition. + +commit 3c3b47bf6f080ddb700886de3e5bfa42c2f0774e +Merge: 9f86614 32d2d33 +Author: Dodji Seketeli +Date: Sat Aug 11 23:09:50 2007 +0200 + + Merge branch 'master' of ssh://dodji@git.freedesktop.org/git/xorg/lib/libXfont + +commit 9f86614394af81bc484cf00f3e9996510d3718cb +Author: Ademar de Souza Reis Jr +Date: Mon Jul 30 14:36:21 2007 -0400 + + Fix dirfd leak on CatalogueRescan(). + +commit 87f50267181887ed9214536608bd2035d2dd70f7 +Author: Ademar de Souza Reis Jr +Date: Mon Jul 30 14:35:01 2007 -0400 + + Support relative paths in catalogue: symlinks. + + Relative symlinks are common inside the catalogue directory and + should be supported as well. + +commit 32d2d335eacd1b55980323a71ef35cdf7c22366d +Author: Ademar de Souza Reis Jr +Date: Mon Jul 30 14:36:21 2007 -0400 + + Fix dirfd leak on CatalogueRescan(). + +commit 0a5b31a40c4933f4c69157c61d4d4890af2205b1 +Author: Ademar de Souza Reis Jr +Date: Mon Jul 30 14:35:01 2007 -0400 + + Support relative paths in catalogue: symlinks. + + Relative symlinks are common inside the catalogue directory and + should be supported as well. + +commit 7670d4a2720c61fbc7b989fed14c676f04ac3ad1 +Author: Dodji Seketeli +Date: Mon Jul 16 12:24:34 2007 +0200 + + Remove side effects from BuiltinReadDirectory() + + The first time BuiltinReadDirectory() is called, + save the content of builtin_dir and builtin_alias, + before calling FontFileAddFontFile(), because that fonction + will modify those. + + Then, in subsequent calls to BuiltinReadDirectory(), restore + builtin_dir and builtin_alias so that the side effect incurred + by the first call disappears. + +commit e3642d9b2c0819a607d4cce413b9f0541285545b +Author: Kristian Høgsberg +Date: Mon Jul 2 15:01:05 2007 -0400 + + Bump version to 1.3.0. + +commit f33f9361086db3cf1d09cec067f38fe751ed22eb +Author: Kristian Høgsberg +Date: Mon Jul 2 14:59:11 2007 -0400 + + Fix crash when no attributes are present for symlink. + +commit 8d47483711be6076e7bfefab14aa890c5f37e1aa +Author: Kristian Høgsberg +Date: Thu Jun 21 21:44:02 2007 -0400 + + Bump version to 1.2.9. + +commit c5ab59762c4ad5def68436d55937a2bd558d5c99 +Author: Kristian Høgsberg +Date: Tue Jun 19 10:38:02 2007 -0400 + + Add a new 'catalogue' FPE, which takes font paths from symlinks in a dir. + + This patch adds a new FPE type, which will match font path elements of the + form + + catalogue: + + The dir specified after the catalogue: prefix will be scanned for symlinks + and each symlink destination will be added as a local fontfile FPE. + The symlink can be suffixed by attributes, such as 'unscaled', which + will be passed through to the underlying fontfile FPE. Except the new + attribute 'pri' which will be used for ordering the fontfile FPEs. + + An example configuration: + + 75dpi:unscaled:pri=20 -> /usr/share/X11/fonts/75dpi + ghostscript:pri=60 -> /usr/share/fonts/default/ghostscript + misc:unscaled:pri=10 -> /usr/share/X11/fonts/misc + type1:pri=40 -> /usr/share/X11/fonts/Type1 + type1:pri=50 -> /usr/share/fonts/default/Type1 + + will add /usr/share/X11/fonts/misc as the first FPE with the attribute + 'unscaled', second FPE will be /usr/share/X11/fonts/75dpi, also with + the attribute unscaled etc. This is functionally equivalent to setting + the following font path: + + /usr/share/X11/fonts/misc:unscaled, + /usr/share/X11/fonts/75dpi:unscaled, + /usr/share/X11/fonts/Type1, + /usr/share/fonts/default/Type1, + /usr/share/fonts/default/ghostscript + + The motivation is to let font packages add a symlink to the new font + directory they provide instead of rewriting either the Xorg config file + or the xfs config file. + +commit 1a690feaf7c416da9b01861af381d15a661e5f52 +Author: Adam Jackson +Date: Thu Jun 7 16:01:03 2007 -0400 + + Minor fontfile cleanup. + +commit 3b1bcd7676fe810ce60d6a4758067b571796cceb +Author: Adam Jackson +Date: Thu Jun 7 15:54:51 2007 -0400 + + Dead code cull from fontserver code. + +commit 6257af0e547095483331b8c8ed588e5467852671 +Author: Adam Jackson +Date: Thu Jun 7 15:41:19 2007 -0400 + + Static markup over bitmap and builtins. + +commit 8c31fadabd706af63381007d666e685a66b58fd9 +Author: Adam Jackson +Date: Thu Jun 7 15:28:09 2007 -0400 + + Dead code cull from FreeType. + +commit fabf5458f1acbfc967bdaea3b89d707c22b97364 +Author: Adam Jackson +Date: Thu Jun 7 15:17:16 2007 -0400 + + Death to open-coded strcasecmp. + + Seriously, if you don't already have this, you've already lost. + +commit d50de26430c1a114a22597de40a3e5ac3c8e1ab7 +Author: Adam Jackson +Date: Thu Jun 7 15:13:44 2007 -0400 + + Dead code cull from Speedo. + +commit 3fd7a510b5467479d6e2559819b96b222c7328e8 +Author: Adam Jackson +Date: Thu Jun 7 14:39:03 2007 -0400 + + One more missed static in Type1 + +commit 440166a027b78eb53d7686937148b755ad51f7f9 +Author: Adam Jackson +Date: Thu Jun 7 14:24:46 2007 -0400 + + Dead code removal and static markup for Type1. + +commit 9739e750a7ca4b86ddb89674b104e9b9a8b61014 +Author: Adam Jackson +Date: Thu Jun 7 14:20:27 2007 -0400 + + Warning cleanup. + +commit 87db45f5eb7880395735f7bf3a8ee2d89b7e0122 +Author: Alan Coopersmith +Date: Wed Apr 4 17:05:13 2007 -0700 + + Version bump: 1.2.8 + +commit 224fb6403a328e70b370540cc5cefd74421fafac +Merge: e7a59cf 0fbb37c +Author: Matthieu Herrb +Date: Tue Apr 3 16:05:48 2007 +0200 + + Merge branch 'master' of git+ssh://herrb@git.freedesktop.org/git/xorg/lib/libXfont + +commit e7a59cfb5d442d2965cfcffeff405a4b05591190 +Author: Matthieu Herrb +Date: Tue Apr 3 15:45:21 2007 +0200 + + Integer overflow vulnerabilities + + CVE-2007-1351: BDFFont Parsing Integer Overflow + CVE-2007-1352: fonts.dir File Parsing Integer Overflow + +commit 0fbb37ccc630ced42d6a973c81d947870cca7637 +Author: Alan Coopersmith +Date: Mon Apr 2 17:40:19 2007 -0700 + + Add #pragma weak for Sun cc where needed + +commit cc824e4f2c9a53a00b36a6f83bf065c363027087 +Author: Alan Coopersmith +Date: Fri Mar 23 15:57:29 2007 -0700 + + Actually use loadable font modules + + Loadable font modules were not being initialized, and all font renderers + known at build time were always being initialized, regardless of Xorg + module configuration. + +commit fc6e22f238d34918156ded34148730075b7b9cc2 +Author: Ben Byer +Date: Tue Feb 20 00:20:23 2007 -0800 + + added -flat_namespace to CFLAGS for Darwin + +commit 9509d5c7ee5d5e78c6eef54e8faceede5ca5f24e +Author: Kristian Høgsberg +Date: Mon Jan 22 18:24:19 2007 -0500 + + Bump to 1.2.7. + +commit 63af35b908b51690a6c12fd42b54cf4ee08c762a +Author: Simon Law +Date: Fri Jan 19 08:50:39 2007 +1100 + + fontfile: accept empty (but valid) font paths (bug #3091) + If a path has a valid fonts.dir or fonts.alias, but does not contain any + fonts (either fonts.dir specifies zero fonts, or fonts could not be + loaded), load it as a valid font path anyway. + +commit 931b777108526dd0761f948dcd9f1603ac02efc8 +Author: Kristian Høgsberg +Date: Wed Jan 17 17:19:53 2007 -0500 + + Add stubs for the scalable renderer callbacks. + + Trying to scale a bitmap font provided by the built-in backend will + crash the X server as it calls into a NULL pointer. This patch + adds "return BadFont;" stubs to prevent the crash. + +commit 2e4ae1b524a0149479c46f3f12a9ce2413092442 +Author: Daniel Stone +Date: Sat Dec 16 00:53:43 2006 +0200 + + bump to 1.2.6 + +commit facc7ce4892eab4353fff0f45d2d3fd6be7d3e3d +Author: Daniel Stone +Date: Sat Dec 16 00:53:32 2006 +0200 + + build Type1 by default + Build Type1 by default, instead of needing to explicitly enable it. + +commit 257db35656d5bf9385080e1d173260f0076f849c +Author: Daniel Stone +Date: Sat Dec 16 00:53:07 2006 +0200 + + don't distribute fontconf.h + Since fontconf.h is a generated file, don't distribute it. + +commit ab0f05dcfb5537ba5aec7e48ddb713d4fdba7e75 +Author: Daniel Stone +Date: Wed Dec 6 18:53:54 2006 +0200 + + Makefile.am: make ChangeLog hook safer + Make ChangeLog hook as safe as possible. + +commit da20e256b786eaa6357e3d55baa9e90e38f14614 +Author: Daniel Stone +Date: Fri Dec 1 01:05:59 2006 +0200 + + bump to 1.2.5 + +commit 16a0c282a673136c0bbb116f35e6e89d8b43a877 +Author: Daniel Stone +Date: Fri Dec 1 01:05:40 2006 +0200 + + post-CID fixes + Curiously, make distcheck succeeded ... go figure. + +commit e47fb944a8f485c4ad6be9c2cf6a4866eff7a07f +Author: Daniel Stone +Date: Fri Dec 1 00:35:48 2006 +0200 + + bump to 1.2.4 + +commit 47084ba39920068030c3e59523701d1205161a9f +Author: Daniel Stone +Date: Fri Dec 1 00:35:04 2006 +0200 + + remove CID font support (bug #5553) + Remove non-free CID font support, which was unused anyway. + +commit c4741cdd83bcdedcc6f7a072a73b16668fc905eb +Author: Adam Jackson +Date: Fri Oct 13 16:17:26 2006 -0400 + + Bump to 1.2.3 + +commit 5dfff0eb0f532edb1f4a25daa5529e08dd832ecb +Author: Alan Coopersmith +Date: Thu Oct 5 18:12:50 2006 -0700 + + --disable-builtins should not force off all bitmap support + +commit 264df52d24f585915e0d9823d5f087cf23e3fc75 +Merge: 0fb55cb d896c3e +Author: Alan Coopersmith +Date: Fri Sep 22 11:36:43 2006 -0700 + + Merge branch 'master' of git+ssh://git.freedesktop.org/git/xorg/lib/libXfont + +commit d896c3eaeafdb8831ed0833af46250c36f82502f +Author: Adam Jackson +Date: Tue Sep 12 11:11:12 2006 -0400 + + Fix distcheck. + +commit 1bb49c77c321fab1f5c268404ea0ec622fa083ed +Author: Adam Jackson +Date: Tue Sep 12 11:01:13 2006 -0400 + + Bump to 1.2.2. + +commit 8c8203ca2760105aca4e0b6ec5909355a061f0b3 +Author: Matthieu Herrb +Date: Tue Sep 12 13:50:31 2006 +0200 + + Fixes for integer overflows in CID encoded fonts parsing reported by iDefense + CVE-ID 2006-3739, 2006-3740, bugzilla #8000, #8001. + +commit 0fb55cb86e2ec5dbfbf27a01ceafb77c72fe9f40 +Author: Alan Coopersmith +Date: Wed Aug 30 15:53:14 2006 -0700 + + Fix typo in comment (alreadt -> already) + +commit aa7f3107d5aad41cb3f7b1bb3a4723014314289c +Author: Alan Coopersmith +Date: Fri Aug 25 17:51:46 2006 -0700 + + Add *~ to .gitignore to skip emacs droppings + +commit cd09f4d54045b957d728d853398d62543d687d03 +Author: Alan Coopersmith +Date: Fri Aug 25 17:51:04 2006 -0700 + + Replace static ChangeLog with dist-hook to generate from git log + +commit 8d171fe61e564d8ed8f75034d4191062cecf190b +Author: Matthieu Herrb +Date: Sun Jul 23 22:42:43 2006 +0200 + + More check on PCF file reading. Bugzilla #7535 + +commit fead0fa3bae0ba5a4744d6a2aee1caa08019f344 +Author: Daniel Stone +Date: Wed Jul 19 18:03:58 2006 -0400 + + use OpenBitmap when available + Don't just use OpenScalable unconditionally. Fixes builtin fonts. + +commit 13422d0e0468f2ddf7cb74cbf925e5bcf4551ae7 +Author: Daniel Stone +Date: Wed Jul 19 18:03:26 2006 -0400 + + move builtin fonts to gzip + Use gzip, rather than compress, for builtin fonts. + +commit 47ca9941396a375f5e22c220327b6bd513350996 +Author: Alan Coopersmith +Date: Thu Jul 13 14:58:56 2006 -0700 + + renamed: .cvsignore -> .gitignore + +commit 1bf657186d19887a0916340b544b5534e29da081 +Author: Matthieu Herrb +Date: Thu Jul 13 10:18:38 2006 -0400 + + Bug #7397: Fix a buffer overflow in Freetype font support. + +commit 5d39f5fd3048fc413cb07afeffec0c4daa0cc5a4 +Author: Adam Jackson +Date: Thu Jul 6 16:13:14 2006 -0400 + + Bump to 1.2.0 + +commit d9e83ea0ab1cc3bafcdca04812dcbfe541ce1473 +Author: Jie Luo +Date: Thu Jul 6 15:59:31 2006 -0400 + + Bug #6918: remove dependencies on Freetype internal headers. As of 2.2 + Freetype no longer installs them. + +commit 2a564715e6d01bafdf4b701e125e45a77c2c404b +Author: Alan Coopersmith +Date: Sat Jun 3 06:25:05 2006 +0000 + + Coverity #1541: Double free of pointer "ranges" in call to "Xfree" + +commit ddd281e6b9408c786cdc759cf7d1ec8972048658 +Author: Adam Jackson +Date: Thu Jun 1 21:49:51 2006 +0000 + + For the 20-odd symbols defined both in libXfont and the X server, emit them + as weak symbols so that the linker will prefer the server's definition + when present. + +commit e9357d6670fc2e8ccf8d8770bac4c31994d6cc2f +Author: Adam Jackson +Date: Sat Apr 1 23:05:40 2006 +0000 + + Add ft.h and ftfuncs.h to the install set for Xprint's benefit. Bump to 1.1 + for new header files and bugfixes. + +commit 7ecd09a15c30770ed6e70d80fb67f88819471c20 +Author: Daniel Stone +Date: Fri Mar 31 07:17:16 2006 +0000 + + Change BUILD_* to XFONT_* (Drew Parsons). Remove random #ifndef CRAY. + +commit 69c4ae1e3e14a58bc2eb9b9b8820dc7183b82a67 +Author: Adam Jackson +Date: Mon Mar 20 19:44:26 2006 +0000 + + Bug #6247: Fix build on Cygwin. (Yaakov Selkowitz) + +commit bfb8a71f4f7e5c5ed4278cb3ee271bf9990d276d +Author: Daniel Stone +Date: Tue Feb 21 21:35:32 2006 +0000 + + Don't crash when we receive an FS_Error from the font server (Guillem + Jover). + +commit 784838e88ea205c4457f41335b4ce7876833dffc +Author: Kevin E Martin +Date: Thu Dec 15 00:24:29 2005 +0000 + + Update package version number for final X11R7 release candidate. + +commit e2e5839417ac4d635781508e48ab1838218f4a77 +Author: Kevin E Martin +Date: Fri Dec 9 06:55:27 2005 +0000 + + Bug #5175: Make encodingsdir configurable. + +commit 9a7909e80a8b436aa7aad84c8aceba7df2ffc95c +Author: Kevin E Martin +Date: Sat Dec 3 05:49:43 2005 +0000 + + Update package version number for X11R7 RC3 release. + +commit ad001bd8823594fed860e070b278748fe2b7c3aa +Author: Eric Anholt +Date: Sun Nov 20 23:17:40 2005 +0000 + + Add/improve libs .cvsignores. + +commit d48bfbaf52598d89b4b1d97b230924874175e068 +Author: Kevin E Martin +Date: Sat Nov 19 07:15:41 2005 +0000 + + Update pkgconfig files to separate library build-time dependencies from + application build-time dependencies, and update package deps to work + with separate build roots. + +commit 70a8aeb19223cc6db9ff6fc1335e3ef94bbb9253 +Author: Adam Jackson +Date: Mon Nov 14 20:40:42 2005 +0000 + + Bug #5047: Make font directory attribs work in modular. + +commit 659b2a75a690838dc37ae488d0295c4c594978ce +Author: Kevin E Martin +Date: Wed Nov 9 21:19:13 2005 +0000 + + Update package version number for X11R7 RC2 release. + +commit fc82a56858e26674e83cc9429fa0eae24d97a530 +Author: Kean Johnson +Date: Tue Nov 8 06:33:26 2005 +0000 + + See ChangeLog entry 2005-11-07 for details. + +commit fb3d726bbff1fad62a3d6dbbcf1c397872aadef3 +Author: Adam Jackson +Date: Sun Oct 23 18:32:05 2005 +0000 + + Bug #4721: Fix crash when using Freetype 2.1.10. (Michael Gor) + +commit 0f006d82f8edd15e0125800fa3166a147e79b9f5 +Author: Kevin E Martin +Date: Wed Oct 19 02:48:10 2005 +0000 + + Update package version number for RC1 release. + +commit 70dfb55c0390cd8698a77baad5e9fbb07aab272d +Author: Kevin E Martin +Date: Wed Oct 5 19:39:06 2005 +0000 + + Include missing files + +commit 01f5840009b23cc504359219a6fbab3c150d4656 +Author: Adam Jackson +Date: Tue Oct 4 00:24:47 2005 +0000 + + Bug #4677: Don't install libfontcache.so + +commit 30f912cd14e8b7272a95586dc0af429a0fa4c84f +Author: Daniel Stone +Date: Fri Sep 9 05:32:58 2005 +0000 + + AC_DEFINE FONTCACHE rather than XFONT_FONTCACHE, as the former is used in + the code, and the latter in Makefile.ams for an AM_CONDITIONAL. + +commit 4a2f7ae2f3317e53d99daf15ad362230388949d4 +Author: Alan Coopersmith +Date: Thu Aug 4 16:15:46 2005 +0000 + + If --with-freetype-config is not specified, try pkgconfig freetype2, then + fall back to freetype-config if pkgconfig fails. + +commit 0c52dd6f8816a72d8309f0b059afb0c3393f17cf +Author: Alan Coopersmith +Date: Sat Jul 30 18:56:32 2005 +0000 + + Clear compiler warnings. (Stefan Dirsch) + +commit 8520fa13d35e42da7352772b499beef258723d43 +Author: Kevin E Martin +Date: Fri Jul 29 21:22:51 2005 +0000 + + Various changes preparing packages for RC0: + - Verify and update package version numbers as needed + - Implement versioning scheme + - Change bug address to point to bugzilla bug entry form + - Disable loadable i18n in libX11 by default (use --enable-loadable-i18n to + reenable it) + - Fix makedepend to use pkgconfig and pass distcheck + - Update build script to build macros first + - Update modular Xorg version + +commit d0c5d54d2c7f0bb9364414620df869e3c7615cd5 +Author: Kevin E Martin +Date: Sat Jul 23 05:27:00 2005 +0000 + + Fix distchecks + +commit 561a45751e4c553f1e0887b73abcc724828f03b0 +Author: Daniel Stone +Date: Sat Jul 16 07:55:12 2005 +0000 + + Set soversion to 1.0.0 using -version-number. + +commit 054dd01fd5793cff89f7c536c04fd8d904aca4a3 +Author: Adam Jackson +Date: Thu Jul 14 14:56:13 2005 +0000 + + Add a dummy source file to avoid link failures. + +commit 740cfa83024ce5d3f131cdc2f52dd5bf26f945b3 +Author: Kevin E Martin +Date: Sun Jul 10 21:35:08 2005 +0000 + + Change include dir now that public headers are referenced by + + +commit cd24fcabc449bbc701a25e3cad279009dec69032 +Author: Keith Packard +Date: Sat Jul 9 23:31:40 2005 +0000 + + Switch from monolithic configuration symbols to modular ones, add backward + compatibility for monolithic symbols + +commit 428dd333c1c1a96d205d8236c6ecee32dbf7cac9 +Author: Keith Packard +Date: Sat Jul 9 23:30:07 2005 +0000 + + Switch from monolithic configuration symbols to modular ones, add backward + compatibility for monolithic symbols + +commit 99cde389c331616f22dd6aab395c488f3a798e2e +Author: Keith Packard +Date: Sat Jul 9 23:15:37 2005 +0000 + + Rearrange configuration options so that individual font file formats drive + combined options, and so that the default matches the monolithic + defaults + Extent fontconf.h to cover all formats + Typo in src/Makefile.am failed to link in Type1 library + Missing xttcap.c from FreeType shim library. + +commit 3c4ac0b9f5b7aced60a763bcaca7b32cd53a7fec +Author: Keith Packard +Date: Sat Jul 9 06:36:13 2005 +0000 + + Include config.h in every source file to make sure necessary options are + found when building in the modular tree + +commit 712140dadd20c7d2024d7b75f7033fff407e57e6 +Author: Keith Packard +Date: Sat Jul 9 06:20:37 2005 +0000 + + Add .cvsignore files Switch _la_CFLAGS for AM_CFLAGS to clean up directory + +commit ef504c5311dfd441dcb73be64e90f6e7a530b61c +Author: Adam Jackson +Date: Fri Jul 8 20:47:12 2005 +0000 + + add -D_XOPEN_SOURCE for linux builds; others might need it too + +commit 3ff8db61b901a4d6236a0e4fa40fe5f1b7afcf78 +Author: Adam Jackson +Date: Fri Jul 8 20:16:12 2005 +0000 + + disable the poll detection momentarily, it's not correct + +commit 830d29e5cb0a8c46cd366adefbf3a291c65bd3ac +Author: Adam Jackson +Date: Fri Jul 8 20:08:12 2005 +0000 + + silence a warning + +commit 75bbb2d461957902258223a9f8f7f8490132e75d +Author: Adam Jackson +Date: Fri Jul 8 19:53:05 2005 +0000 + + config.h includes to fix modular build. + +commit f068c478d0966be93f9e984c1e9ce2600819a6a1 +Author: Adam Jackson +Date: Fri Jul 8 18:29:58 2005 +0000 + + Properly test for the existance of poll(3). Default to using it if it + exists; add a flag to disable it if you like going slow. + Also s/BULITIN/BUILTIN/. + +commit e5f35e324548994f2d6df89d6bd0a4eb913f7414 +Author: Alan Coopersmith +Date: Thu Jul 7 14:59:47 2005 +0000 + + Bug #2901 Patch #2332 + This patch avoids + 79 gcc-3.4.3 warnings 'xxx' declared `static' but never defined mostly + due to including "ftfuncs.h" with the declaration of static functions + defined in "ftfuncs.c". (Peter Breitenlohner) + +commit c073ce34164a9872688ce619cc0b3fedbdc76f83 +Author: Alexander Gottwald +Date: Mon Jul 4 22:26:15 2005 +0000 + + Test for xtrans connection flags + +commit a0dc7d02bfcaea8c8a60dcbd00795999bd7f8e0a +Author: Kevin E Martin +Date: Sun Jul 3 21:43:32 2005 +0000 + + Undo previous change to add ${includedir}/X11/fonts to CFLAGS. Instead, + require all apps to include font headers explicitly -- i.e., from + instead of "*.h" or <*.h>. + +commit b15a03de6b1897d7c8292e154d0e927f43e3cde0 +Author: Kevin E Martin +Date: Sun Jul 3 21:38:42 2005 +0000 + + Install publicly used headers in X11/fonts. + Change source files that use these headers to get them via . + +commit bf4070d02196cab1de62d5fe19be9a1aa74a87c7 +Author: Kevin E Martin +Date: Sun Jul 3 16:10:05 2005 +0000 + + Change include dir now that public headers are referenced by + + +commit 932edb23b47440397447265bf72ad7932fd80070 +Author: Daniel Stone +Date: Sun Jul 3 07:01:01 2005 +0000 + + Add Xtrans definitions (FONT_t, TRANS_CLIENT) to clean up warnings. + Add XSERV_t, TRANS_SERVER, TRANS_REOPEN to quash warnings. + Add #include or , as appropriate, to all + source files in the xserver/xorg tree, predicated on defines of + HAVE_{DIX,XORG}_CONFIG_H. Change all Xfont includes to + . + +commit b03d67fd1612a0df5132b10dd0bd9b2cec053a39 +Author: Keith Packard +Date: Sat Jul 2 23:03:05 2005 +0000 + + Add suitable .cvsignore files + +commit 69ee19fc4131ce168c9bad2602ff2da176a86715 +Author: Kevin E Martin +Date: Sat Jul 2 21:39:23 2005 +0000 + + Make headers needed by bdftopcf public + Set CFLAGS to make public interface actually public + Fix distcheck problem + +commit 0ea9f882abb9ad56de2bb8b569e21728e13a1ea7 +Author: Keith Packard +Date: Sat Jul 2 21:22:31 2005 +0000 + + Build libXfont.la in the 'src' directory as my version of automake really + didn't like sub-subdirs in SUBDIRS. + +commit 6abcfa406de44d726f550fe7e9b04e4168fce265 +Author: Daniel Stone +Date: Sat Jul 2 18:02:19 2005 +0000 + + Remove -I${includedir}/X11/fonts from CFLAGS. + +commit 58edcd0de115e23030955493e88afb25b57668e9 +Author: Daniel Stone +Date: Fri Jul 1 22:21:43 2005 +0000 + + Add Xtrans definitions (FONT_t, TRANS_CLIENT) to clean up warnings. + +commit 12cca25eea410bfd536ada44e252d79e0896ffa2 +Author: Daniel Stone +Date: Fri Jul 1 21:24:31 2005 +0000 + + Default --enable-fc to yes; minor formatting changes. + +commit 4534fa0c8adb77b7db47101318e0e863edb186ce +Author: Søren Sandmann Pedersen +Date: Mon Jun 27 16:09:14 2005 +0000 + + - Remove fontenc from Xfont + - Add a dependency from Xfont on libfontenc + - Add build system for lib/fontenc + - xc/lib/font: Change #include "fontenc.h" to #include + in some places. + - Remove dpsinfo and dpsexec from the app section of symlink.sh + - Fix xp.pc.in to add XPRINT_LIBS/CFLAGS instead of X_LIBS/CFLAGS + +commit fda7215c0783ad170eb14f7dda078fac3f134470 +Author: Søren Sandmann Pedersen +Date: Tue Jun 21 21:29:40 2005 +0000 + + Add fontenc directory, update buildsystem + +commit db8fd7e670cbd901116344212217bee8001ab460 +Author: Søren Sandmann Pedersen +Date: Fri Jun 17 20:33:33 2005 +0000 + + Add lbxutil to symlink.sh Add back accidentally removed include in Type1 + directory Disable Speedo by default + +commit e5525d268c6165318894f326be445b22a2523558 +Author: Søren Sandmann Pedersen +Date: Thu Jun 16 21:35:26 2005 +0000 + + Add Speedo directory to Xfont + +commit b96f539005da57273dc7e2bee13651de4eedf087 +Author: Søren Sandmann Pedersen +Date: Thu Jun 16 20:50:12 2005 +0000 + + Add Type1 subdirectory to lib/Xfonts, update build system accordingly. + +commit 01c8cee1736be252348306412ab56b2e03bf2678 +Author: Alexander Gottwald +Date: Thu Jun 9 15:56:05 2005 +0000 + + Replace with + +commit 3a46316e5f21e28402babdc95871317bd7013809 +Author: Alexander Gottwald +Date: Thu Jun 9 15:52:03 2005 +0000 + + Replace with + Copy Xtrans.h to exports/include/X11/Xtrans only + +commit 175bbc2e58f7dbe5c1f097ef36eadc3f6fe4b5e6 +Author: Josh Triplett +Date: Fri May 27 17:44:08 2005 +0000 + + Reference X11/fonts header files using X11/fonts/ prefix. + +commit fd884a4dbe3f1be8919426da3ebd177fa474a59e +Author: Josh Triplett +Date: Fri May 27 05:17:52 2005 +0000 + + Add Xfont. + +commit 73c3c1850bc5ba1b0d42b2a9d4f3f5593bfbfd02 +Author: Adam Jackson +Date: Fri Apr 22 20:49:49 2005 +0000 + + Bug #3069: Drop the BuildLowMem hack, it doesn't compile and isn't useful. + +commit dd695cb666d6912f615b264eaabbad63592588c1 +Author: Alexander Gottwald +Date: Mon Nov 15 15:06:56 2004 +0000 + + Bufzilla #1802, http://freedesktop.org/bugzilla/show_bug.cgi?id=1802 Added + mingw (Win32) port + +commit 8cb3bec3667fa6ee57277956d3be71671915a73b +Author: Roland Mainz +Date: Wed Nov 10 07:46:26 2004 +0000 + + xc/lib/font/util/Imakefile + //freedesktop.org/bugzilla/show_bug.cgi?id=1804): Fix build failure (caused + by missing symbols such as |TwoByteSwap|) when linking the FreeType + module and the FreeType library both statically info the Xserver. + +commit 69e87288b14a9f28caf0ed5e4ccf5a52767b22eb +Author: Roland Mainz +Date: Wed Nov 3 19:43:57 2004 +0000 + + //freedesktop.org/bugzilla/show_bug.cgi?id=1767): Fixing build bustage in + xc/programs/bdftopcf/ due missing `FT_STREAM_SEEK'/`FT_STREAM_POS' + symbols. + +commit 29b00ebfebf9811d0940c164a4fcff1b2fc5f2a0 +Author: Egbert Eich +Date: Tue Nov 2 08:54:52 2004 +0000 + + Removing unneeded private FreeType2 symbol. + Updating to EDID 1.3. (Bugzilla# 1490, Jay Cotton, Egbert Eich). + Removing unneeded code. + Fixed KGA handling for i810. KGA handling for chips derived from C&T chips + is slightly different. The changes make the code consistent with the + C&T (chips) and i740 drivers. + +commit e521b8425894ae62ebe225af80e8b6f820df6ff8 +Author: Egbert Eich +Date: Wed Aug 4 12:21:48 2004 +0000 + + Optimization of CJK rendering when using versions of freetype prior to + 2.1.8 (Chisato Yamauchi). + A small backward compatibility fix to make the freetype module build with + freetype version < 2.1.7. + Fixed/added some debugging code. + +commit 0cbe4e38042a21ee193b2fda42fa647e23f61758 +Author: Egbert Eich +Date: Tue Aug 3 16:12:53 2004 +0000 + + fixed typo + +commit 3ebaa297368aaf4c49caf179d2032c1678066663 +Author: Egbert Eich +Date: Tue Aug 3 09:02:17 2004 +0000 + + Bugzilla #925: Simpler version of backward compatibility fix (Chisato + Yamauchi). Fix to support older versions of gcc (Matthieu Herrb). + +commit 96a97b8f86982ece612aa72865b737820d88105b +Author: Egbert Eich +Date: Mon Aug 2 19:35:07 2004 +0000 + + Removed distro specific stuff. + Fixed FreeType module to build with FreeType versions older than 2.1.7. + Fixed typo. + Added vtSema to protect call of driver DPMS function. + removed unneeded variable + Modified RandR driver hook to reduce the number of function calls to one. + Function is sufficiently generic to be extended in the future. + +commit d1054db0eec3af6a7c322b262cfc1bf5a3992805 +Author: Egbert Eich +Date: Mon May 24 19:06:59 2004 +0000 + + Fix build glitches when building modules independently using Imake. + +commit 2a7109894f4dcfaba70135e19fb6d595332522c7 +Author: Egbert Eich +Date: Wed May 5 17:24:40 2004 +0000 + + BugZilla #601: fixed missing symbols in Xserver freetype module due to + using isdigit instead of ft_isdigit, missing or faulty defines for + digit and string functions in ftstdlib.h (now myftstdlib.h). Reverted + freetype2 to upstream version, fixed CHAR_BIT in myftstdlib.h and made + the use of a copy of ftconfig.h in lib/font/FreeType obsolete (Egbert + Eich). + +commit b096ed91beaa09eb06b07ef948eeb6207bd3c5e4 +Author: Roland Mainz +Date: Tue May 4 22:59:15 2004 +0000 + + Fix for http://pdx.freedesktop.org/cgi-bin/bugzilla/show_bug.cgi?id=595 - + RFE: Retire XTT font module and FreeType1 from xorg tree. The + functionality of XTT has been integrated into the FreeType font module + and the old XTT1.x code (incl. FreeType1 in xc/extras/) is no longer + needed anymore. + +commit ca5602cde91fc78f54ebe9f08c11a44a9372a652 +Author: Roland Mainz +Date: Tue May 4 18:47:31 2004 +0000 + + Fix for http://pdx.freedesktop.org/cgi-bin/bugzilla/show_bug.cgi?id=307 - + Restore optimization heuristics on CJK fonts in the FreeType font + module which were broken in X11R6.7. Patch by Chisato Yamauchi + . + +commit 3d75ea33ecf80c3539b38a993092cd16325a9525 +Author: Egbert Eich +Date: Fri Apr 23 18:44:23 2004 +0000 + + Merging XORG-CURRENT into trunk + +commit 8ee2a19ff0295d625baf0b42e0a8bb7f4ad575fd +Author: Egbert Eich +Date: Sun Mar 14 08:32:37 2004 +0000 + + Importing vendor version xf86-4_4_99_1 on Sun Mar 14 00:26:39 PST 2004 + +commit 4986cabb22d133aeb37b53514471ff7d5bf999fe +Author: Egbert Eich +Date: Wed Mar 3 12:11:44 2004 +0000 + + Importing vendor version xf86-4_4_0 on Wed Mar 3 04:09:24 PST 2004 + +commit f827ecf1e0c4289b5020256f9bf5b8d563b202c7 +Author: Egbert Eich +Date: Thu Feb 26 13:35:35 2004 +0000 + + readding XFree86's cvs IDs + +commit 90614769a00fbdaf6ef2e313b480e1f0857425f3 +Author: Egbert Eich +Date: Thu Feb 26 09:22:53 2004 +0000 + + Importing vendor version xf86-4_3_99_903 on Wed Feb 26 01:21:00 PST 2004 + +commit 45fc57ae316da51b2f9abab2aee303456730ab54 +Author: Kaleb Keithley +Date: Mon Feb 23 20:34:43 2004 +0000 + + Import most of XFree86 4.4RC3. This import excludes files which have the + new license. If we want to, later we can import 4.4RC3 again and pick + up the files that have the new license, but for now the vendor branch + is "pure." + +commit d7467b679ccff6fb2025f963b9bcea5dbe72fa15 +Author: Egbert Eich +Date: Thu Jan 29 08:08:15 2004 +0000 + + Importing vendor version xf86-012804-2330 on Thu Jan 29 00:06:33 PST 2004 + +commit a0e93cace89c3da8df33d8626a486afe6840d530 +Author: Kaleb Keithley +Date: Fri Dec 19 20:54:40 2003 +0000 + + XFree86 4.3.99.902 (RC 2) + +commit d82accff22e36919479b3ac1de72de6115688138 +Author: Kaleb Keithley +Date: Thu Dec 4 22:03:04 2003 +0000 + + XFree86 4.3.99.901 (RC 1) + +commit fb0cbe6e7287d635a5f368e055cc0aae6ed50125 +Author: Kaleb Keithley +Date: Tue Nov 25 19:28:20 2003 +0000 + + XFree86 4.3.99.16 Bring the tree up to date for the Cygwin folks + +commit ca219ad2fc4f392505d378dfa5a2b34d33de6d61 +Author: Kaleb Keithley +Date: Tue Nov 25 19:28:16 2003 +0000 + + Initial revision + +commit 4349bf0fa125e2a1c32b0b49c974ff5fa588cdbe +Author: Kaleb Keithley +Date: Fri Nov 14 16:48:50 2003 +0000 + + XFree86 4.3.0.1 + +commit 3795e9702b3b3a6fe0594d09cdd110adeb5e42f9 +Author: Kaleb Keithley +Date: Fri Nov 14 16:48:50 2003 +0000 + + Initial revision + +commit 153e8da44452905ae04a0e20ad0d85f40399b4ca +Author: Kaleb Keithley +Date: Fri Nov 14 15:54:40 2003 +0000 + + R6.6 is the Xorg base-line diff --git a/Makefile.am b/Makefile.am new file mode 100755 index 0000000..9153e98 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,56 @@ +# +# Copyright © 2003 Keith Packard, Noah Levitt +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of Keith Packard not be used in +# advertising or publicity pertaining to distribution of the software without +# specific, written prior permission. Keith Packard makes no +# representations about the suitability of this software for any purpose. It +# is provided "as is" without express or implied warranty. +# +# KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +SUBDIRS=doc src + +libXfontincludedir = $(includedir)/X11/fonts +libXfontinclude_HEADERS = \ + include/X11/fonts/bdfint.h \ + include/X11/fonts/bitmap.h \ + include/X11/fonts/bufio.h \ + include/X11/fonts/fntfil.h \ + include/X11/fonts/fntfilio.h \ + include/X11/fonts/fntfilst.h \ + include/X11/fonts/fontencc.h \ + include/X11/fonts/fontmisc.h \ + include/X11/fonts/fontshow.h \ + include/X11/fonts/fontutil.h \ + include/X11/fonts/fontxlfd.h \ + include/X11/fonts/pcf.h \ + src/FreeType/ft.h \ + src/FreeType/ftfuncs.h +nodist_libXfontinclude_HEADERS = \ + include/X11/fonts/fontconf.h + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = xfont.pc + +MAINTAINERCLEANFILES = ChangeLog INSTALL + +.PHONY: ChangeLog INSTALL + +INSTALL: + $(INSTALL_CMD) + +ChangeLog: + $(CHANGELOG_CMD) + +dist-hook: ChangeLog INSTALL diff --git a/README b/README new file mode 100644 index 0000000..97a9e8a --- /dev/null +++ b/README @@ -0,0 +1,25 @@ +libXfont provides the core of the legacy X11 font system, handling the +index files (fonts.dir, fonts.alias, fonts.scale), the various font file +formats, and rasterizing them. It is used by the X servers, the +X Font Server (xfs), and some font utilities (bdftopcf for instance), +but should not be used by normal X11 clients. X11 clients access fonts +via either the new API's in libXft, or the legacy API's in libX11. + +Please submit bugs & patches to the Xorg bugzilla: + + https://bugs.freedesktop.org/enter_bug.cgi?product=xorg + +All questions regarding this software should be directed at the +Xorg mailing list: + + http://lists.freedesktop.org/mailman/listinfo/xorg + +The master development code repository can be found at: + + git://anongit.freedesktop.org/git/xorg/lib/libXfont + + http://cgit.freedesktop.org/xorg/lib/libXfont + +For more information on the git code manager, see: + + http://wiki.x.org/wiki/GitPage diff --git a/autogen.sh b/autogen.sh new file mode 100644 index 0000000..904cd67 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,12 @@ +#! /bin/sh + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd $srcdir + +autoreconf -v --install || exit 1 +cd $ORIGDIR || exit $? + +$srcdir/configure --enable-maintainer-mode "$@" diff --git a/configure.ac b/configure.ac new file mode 100755 index 0000000..8389dfc --- /dev/null +++ b/configure.ac @@ -0,0 +1,213 @@ +dnl Copyright © 2003 Keith Packard +dnl +dnl Permission to use, copy, modify, distribute, and sell this software and its +dnl documentation for any purpose is hereby granted without fee, provided that +dnl the above copyright notice appear in all copies and that both that +dnl copyright notice and this permission notice appear in supporting +dnl documentation, and that the name of Keith Packard not be used in +dnl advertising or publicity pertaining to distribution of the software without +dnl specific, written prior permission. Keith Packard makes no +dnl representations about the suitability of this software for any purpose. It +dnl is provided "as is" without express or implied warranty. +dnl +dnl KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +dnl INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +dnl EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR +dnl CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +dnl DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +dnl TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +dnl PERFORMANCE OF THIS SOFTWARE. +dnl +dnl Process this file with autoconf to create configure. + +AC_PREREQ([2.60]) + +AC_INIT([libXfont], + [1.4.3], + [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], + libXfont) +# Autoheader generates config.h.in. No new lines allowed in the list. +AC_CONFIG_HEADERS([config.h include/X11/fonts/fontconf.h]) +dnl +dnl This is the package version number, not the shared library +dnl version. This same version number must appear in Xfont.h +dnl Yes, it is a pain to synchronize version numbers. Unfortunately, it's +dnl not possible to extract the version number here from Xfont.h +dnl +AM_INIT_AUTOMAKE([foreign dist-bzip2]) +AM_MAINTAINER_MODE + +# Require xorg-macros minimum of 1.10 for DocBook XML documentation +m4_ifndef([XORG_MACROS_VERSION], + [m4_fatal([must install xorg-macros 1.10 or later before running autoconf/autogen])]) +XORG_MACROS_VERSION(1.10) +XORG_DEFAULT_OPTIONS +XORG_ENABLE_DEVEL_DOCS +XORG_WITH_XMLTO(0.0.20) +XORG_WITH_FOP +XORG_CHECK_SGML_DOCTOOLS(1.5) + +# Check for progs +AC_PROG_CC +AC_PROG_LIBTOOL +dnl If the first PKG_CHECK_MODULES appears inside a conditional, pkg-config +dnl must first be located explicitly. +PKG_PROG_PKG_CONFIG + +# Look for headers +AC_CHECK_HEADERS([endian.h poll.h sys/poll.h]) +AC_CHECK_FUNCS([poll]) + +# +# select libraries to include +# + +XFONT_FONTFILE=no + +# +# Scalable fonts in files: +# FreeType +# Bitstream Speedo rasterizer +# +AC_ARG_ENABLE(freetype, [ --disable-freetype],[XFONT_FREETYPE=$enableval],[XFONT_FREETYPE=yes]) +AM_CONDITIONAL(XFONT_FREETYPE, [test x$XFONT_FREETYPE = xyes]) +if test x$XFONT_FREETYPE = xyes; then + AC_DEFINE(XFONT_FREETYPE,1,[Support FreeType rasterizer for nearly all font file formats]) + AC_ARG_WITH(freetype-config, [ --with-freetype-config=PROG Use FreeType configuration program PROG], freetype_config=$withval, freetype_config=auto) + + if test "$freetype_config" = "auto" ; then + PKG_CHECK_MODULES(FREETYPE, freetype2, + freetype_config=no, freetype_config=yes) + fi + + if test "$freetype_config" = "yes"; then + AC_PATH_PROG(ft_config,freetype-config,no) + if test "$ft_config" = "no"; then + AC_MSG_ERROR([You must have freetype installed; see http://www.freetype.org/]) + fi + else + ft_config="$freetype_config" + fi + + if test "$freetype_config" != "no"; then + FREETYPE_CFLAGS="`$ft_config --cflags`" + FREETYPE_LIBS="`$ft_config --libs`" + fi + FREETYPE_REQUIRES="freetype2" + XFONT_FONTFILE=yes +else + FREETYPE_CFLAGS="" + FREETYPE_LIBS="" + FREETYPE_REQUIRES="" +fi +AC_SUBST(FREETYPE_LIBS) +AC_SUBST(FREETYPE_CFLAGS) +AC_SUBST(FREETYPE_REQUIRES) + +# +# Bitmap fonts in files: +# Builtins (gzipped pcf format in .text segment) +# PCF +# BDF +# SNF +# + +AC_DEFINE(X_GZIP_FONT_COMPRESSION,1,[Support gzip for bitmap fonts]) +X_GZIP_FONT_COMPRESSION=1 +AC_SUBST(X_GZIP_FONT_COMPRESSION) +AC_CHECK_LIB(z, gzopen, [Z_LIBS=-lz], AC_MSG_ERROR([*** zlib is required])) + +AC_ARG_WITH(bzip2, + AS_HELP_STRING([--with-bzip2], + [Support bzip2 compressed bitmap fonts]), + [], [with_bzip2=no]) +if test "x$with_bzip2" = xyes; then + AC_CHECK_LIB(bz2, BZ2_bzopen, [Z_LIBS="$Z_LIBS -lbz2"], + AC_MSG_ERROR([*** libbz2 is required for bzip2 support])) + AC_DEFINE(X_BZIP2_FONT_COMPRESSION,1,[Support bzip2 for bitmap fonts]) +fi +AM_CONDITIONAL(X_BZIP2_FONT_COMPRESSION, [test "x$with_bzip2" = xyes ]) +AC_SUBST(Z_LIBS) + +AC_ARG_ENABLE(builtins, [ --disable-builtins ], [XFONT_BUILTINS=$enableval], [XFONT_BUILTINS=yes]) +AM_CONDITIONAL(XFONT_BUILTINS, [test "x$XFONT_BUILTINS" = xyes ]) +if test "x$XFONT_BUILTINS" = xyes; then + AC_DEFINE(XFONT_BUILTINS,1,[Support built-in fonts]) + XFONT_BITMAP=yes +fi + +AC_ARG_ENABLE(pcfformat, [ --disable-pcfformat ], [XFONT_PCFFORMAT=$enableval], [XFONT_PCFFORMAT=yes]) +AM_CONDITIONAL(XFONT_PCFFORMAT, [test "x$XFONT_PCFFORMAT" = xyes]) +if test "x$XFONT_PCFFORMAT" = xyes; then + AC_DEFINE(XFONT_PCFFORMAT,1,[Support pcf format bitmap font files]) + XFONT_BITMAP=yes +fi + +AC_ARG_ENABLE(bdfformat, [ --disable-bdfformat ], [XFONT_BDFFORMAT=$enableval], [XFONT_BDFFORMAT=yes]) +AM_CONDITIONAL(XFONT_BDFFORMAT, [test "x$XFONT_BDFFORMAT" = xyes]) +if test "x$XFONT_BDFFORMAT" = xyes; then + AC_DEFINE(XFONT_BDFFORMAT,1,[Support bdf format bitmap font files]) + XFONT_BITMAP=yes +fi + +AC_ARG_ENABLE(snfformat, [ --disable-snfformat ], [XFONT_SNFFORMAT=$enableval], [XFONT_SNFFORMAT=yes]) +AM_CONDITIONAL(XFONT_SNFFORMAT, [test "x$XFONT_SNFFORMAT" = xyes]) +if test "x$XFONT_SNFFORMAT" = xyes; then + AC_DEFINE(XFONT_SNFFORMAT,1,[Support snf format bitmap font files]) + XFONT_BITMAP=yes +fi + +AM_CONDITIONAL(XFONT_BITMAP, [test "x$XFONT_BITMAP" = xyes ]) +if test "x$XFONT_BITMAP" = xyes; then + AC_DEFINE(XFONT_BITMAP,1,[Support bitmap font files]) + XFONT_FONTFILE=yes +fi + +AM_CONDITIONAL(XFONT_FONTFILE, [test "x$XFONT_FONTFILE" = xyes]) +if test "x$XFONT_FONTFILE" = xyes; then + AC_DEFINE(XFONT_FONTFILE,1,[Support fonts in files]) +fi + +# +# Support connection to font servers? +# + +AC_ARG_ENABLE(fc, [ --disable-fc ],[XFONT_FC=$enableval],[XFONT_FC=yes]) +AM_CONDITIONAL(XFONT_FC, [test "x$XFONT_FC" = xyes]) +if test "x$XFONT_FC" = xyes; then + AC_DEFINE(XFONT_FC,1,[Support the X Font Services Protocol]) +fi + + +AC_CHECK_LIB(m, hypot, [MATH_LIBS=-lm +AC_SUBST(MATH_LIBS)], AC_MSG_ERROR([*** libm is required])) + +PKG_CHECK_MODULES(XFONT, xproto xtrans fontsproto fontenc) + +# Transport selection macro from xtrans.m4 +XTRANS_CONNECTION_FLAGS + +case $host_os in + linux*) + OS_CFLAGS="-D_XOPEN_SOURCE" + ;; + darwin*) + OS_CFLAGS="-Wl,-flat_namespace" + ;; + *) + OS_CFLAGS= + ;; +esac +AC_SUBST([OS_CFLAGS]) + +AC_OUTPUT([Makefile + doc/Makefile + src/Makefile + src/fontfile/Makefile + src/FreeType/Makefile + src/builtins/Makefile + src/bitmap/Makefile + src/fc/Makefile + src/util/Makefile + src/stubs/Makefile + xfont.pc]) diff --git a/debian/README.source b/debian/README.source new file mode 100644 index 0000000..34ab4bf --- /dev/null +++ b/debian/README.source @@ -0,0 +1,73 @@ +------------------------------------------------------ +Quick Guide To Patching This Package For The Impatient +------------------------------------------------------ + +1. Make sure you have quilt installed +2. Unpack the package as usual with "dpkg-source -x" +3. Run the "patch" target in debian/rules +4. Create a new patch with "quilt new" (see quilt(1)) +5. Edit all the files you want to include in the patch with "quilt edit" + (see quilt(1)). +6. Write the patch with "quilt refresh" (see quilt(1)) +7. Run the "clean" target in debian/rules + +Alternatively, instead of using quilt directly, you can drop the patch in to +debian/patches and add the name of the patch to debian/patches/series. + +------------------------------------ +Guide To The X Strike Force Packages +------------------------------------ + +The X Strike Force team maintains X packages in git repositories on +git.debian.org in the pkg-xorg subdirectory. Most upstream packages +are actually maintained in git repositories as well, so they often +just need to be pulled into git.debian.org in a "upstream-*" branch. +Otherwise, the upstream sources are manually installed in the Debian +git repository. + +The .orig.tar.gz upstream source file could be generated this +"upstream-*" branch in the Debian git repository but it is actually +copied from upstream tarballs directly. + +Due to X.org being highly modular, packaging all X.org applications +as their own independent packages would have created too many Debian +packages. For this reason, some X.org applications have been grouped +into larger packages: xutils, xutils-dev, x11-apps, x11-session-utils, +x11-utils, x11-xfs-utils, x11-xkb-utils, x11-xserver-utils. +Most packages, including the X.org server itself and all libraries +and drivers are, however maintained independently. + +The Debian packaging is added by creating the "debian-*" git branch +which contains the aforementioned "upstream-*" branch plus the debian/ +repository files. +When a patch has to be applied to the Debian package, two solutions +are involved: +* If the patch is available in one of the upstream branches, it + may be git'cherry-picked into the Debian repository. In this + case, it appears directly in the .diff.gz. +* Otherwise, the patch is added to debian/patches/ which is managed + with quilt as documented in /usr/share/doc/quilt/README.source. + +quilt is actually invoked by the Debian X packaging through a larger +set of scripts called XSFBS. XSFBS brings some other X specific +features such as managing dependencies and conflicts due to the video +and input driver ABIs. +XSFBS itself is maintained in a separate repository at + git://git.debian.org/pkg-xorg/xsfbs.git +and it is pulled inside the other Debian X repositories when needed. + +The XSFBS patching system requires a build dependency on quilt. Also +a dependency on $(STAMP_DIR)/patch has to be added to debian/rules +so that the XSFBS patching occurs before the actual build. So the +very first target of the build (likely the one running autoreconf) +should depend on $(STAMP_DIR)/patch. It should also not depend on +anything so that parallel builds are correctly supported (nothing +should probably run while patching is being done). And finally, the +clean target should depend on the xsfclean target so that patches +are unapplied on clean. + +When the upstream sources contain some DFSG-nonfree files, they are +listed in text files in debian/prune/ in the "debian-*" branch of +the Debian repository. XSFBS' scripts then take care of removing +these listed files during the build so as to generate a modified +DFSG-free .orig.tar.gz tarball. diff --git a/debian/changelog b/debian/changelog new file mode 100755 index 0000000..d9c56c7 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,300 @@ +libxfont (1:1.4.3-2slp2) unstable; urgency=low + + * upgrade version due to the change of fontconfig + * Git: 165.213.180.234:slp/pkgs/xorg/lib/libxfont + * Tag: libxfont_1.4.3-2slp2 + + -- SooChan Lim Mon, 11 Apr 2011 11:02:33 +0900 + +libxfont (1:1.4.3-1slp2) unstable; urgency=low + + * [X11R7.6] upgrade pacakge + * Git: 165.213.180.234:slp/pkgs/xorg/lib/libxfont + * Tag: libxfont_1.4.3-1slp2 + + -- SooChan Lim Thu, 06 Jan 2011 11:39:02 +0900 + +libxfont (1:1.4.2-1) experimental; urgency=low + + * New upstream release. + * Bump xutils-dev build-dep for new xorg-macros. + * Bump shlibs for register_fpe_functions(). + * Update debian/copyright. + * Bump Standards-Version to 3.9.0, no changes. + + -- Julien Cristau Wed, 07 Jul 2010 18:25:15 +0100 + +libxfont (1:1.4.1-2) unstable; urgency=low + + [ Julien Cristau ] + * Rename the build directory to not include DEB_BUILD_GNU_TYPE for no + good reason. Thanks, Colin Watson! + * Remove myself from Uploaders + + [ Cyril Brulebois ] + * Use dh_makeshlibs?™s -V argument instead of debian/libxfont1.shlibs + * Add udeb needed for the graphical installer: libxfont1-udeb. + * Version the B-D on libfontenc-dev to ensure libxfont1-udeb gets a + dependency on libfontenc1-udeb. + * Use a bzip2-less flavour for the udeb. + * Bump Standards-Version from 3.8.3 to 3.8.4 (no changes needed). + * Fix obsolete-relation-form-in-source by using ?? Wed, 10 Mar 2010 20:05:31 +0100 + +libxfont (1:1.4.1-1) unstable; urgency=low + + * New upstream release. + * Bump xutils-dev build-dep for new util-macros. + * Build documentation, install it in libxfont-dev. + * Enable support for bzip2 compressed bitmap fonts. + * Don't use LDFLAGS from the environment. Ubuntu sets that to + -Bsymbolic-functions, which breaks libXfont's weak symbols usage. + + -- Julien Cristau Wed, 02 Dec 2009 11:12:13 +0100 + +libxfont (1:1.4.0-8slp2) unstable; urgency=low + + * To sync git and dpkg + * Git: 165.213.180.234:/git/slp/pkgs/xorg/lib/libxfont + * Tag: libxfont_1.4.0-8slp2 + + -- YoungHoon Jung Thu, 02 Dec 2010 15:45:37 +0900 + +libxfont (1:1.4.0-7slp2) unstable; urgency=low + + * Update maintainer + * Git: 165.213.180.234:/git/slp2.0/slp2.0-pkgs/X11 + * Tag: libxfont_1.4.0-7slp2 + + -- Sung-Jin Park Wed, 21 Apr 2010 13:46:42 +0900 + +libxfont (1:1.4.0-6slp2) unstable; urgency=low + + * modify the package name + + -- SooChan Lim Thu, 25 Mar 2010 17:51:04 +0900 + +libxfont (1:1.4.0-5) unstable; urgency=low + + * Fix debian/rules to install .la files properly + + -- Sung-Jin Park Mon, 07 Dec 2009 14:51:41 +0900 + +libxfont (1:1.4.0-4) unstable; urgency=low + + * Import debian package + * Install .la files + + -- Sung-Jin Park Mon, 07 Dec 2009 10:30:58 +0900 + +libxfont (1:1.4.0-3) unstable; urgency=low + + * libxfont1 Conflicts: xprint (< 2:1.6.0-1). + The requiem release of xprint (1.6) will not conflict with + libxfont1. I am assured the garlic wreaths should prove most + efficacious at protecting the general public from the undead. + * Standards version 3.8.3. + + -- Drew Parsons Sat, 31 Oct 2009 11:29:34 +1100 + +libxfont (1:1.4.0-2) unstable; urgency=high + + * libxfont1 Conflicts with xprint, printer font support was removed upstream + in 1.4.0 (closes: #535952). + * Add README.source from xsfbs. Bump Standards-Version to 3.8.2. + + -- Julien Cristau Sun, 02 Aug 2009 13:36:46 +0200 + +libxfont (1:1.4.0-1) unstable; urgency=low + + * New upstream release. + * Move libxfont1-dbg to new section 'debug'. + + -- Julien Cristau Mon, 13 Apr 2009 12:11:23 +0100 + +libxfont (1:1.3.4-2) unstable; urgency=low + + * Update debian/copyright from upstream COPYING. + * Upload to unstable. + + -- Julien Cristau Mon, 16 Feb 2009 19:31:59 +0100 + +libxfont (1:1.3.4-1) experimental; urgency=low + + * Wrap build-deps in debian/control. + * Run autoreconf on build; build-dep on xutils-dev, autoconf, automake and + libtool. + * Handle parallel builds. + * New upstream release. + * Drop obsolete x11proto-fontcache-dev build-dependency. + + -- Julien Cristau Tue, 23 Dec 2008 15:06:37 +0100 + +libxfont (1:1.3.3-1) unstable; urgency=high + + [ Julien Cristau ] + * Drop dependency on x11-common from libxfont1{,-dbg}. + * New upstream bugfix release. + * Disable the type1 rasterizer and support for speedo font files. The + former is a security hazard, and Speedo fonts are disabled in the X server + since before etch anyway. + * Urgency high so the above gets in lenny. + + [ Brice Goglin ] + * Add upstream URL to debian/copyright. + * Add a link to www.X.org and a reference to the upstream module + in the long description. + + -- Julien Cristau Thu, 17 Jul 2008 22:50:03 +0200 + +libxfont (1:1.3.2-1) unstable; urgency=low + + * New upstream release + * Drop CVE-2008-0006.diff, included upstream. + + -- Julien Cristau Fri, 07 Mar 2008 13:32:43 +0100 + +libxfont (1:1.3.1-2) unstable; urgency=high + + * High urgency upload for security fix. + * Fix a buffer overflow in the PCF font parser (CVE-2008-0006). + * debian/control updates + + add myself to Uploaders, and remove Branden and Fabio with their + permission + + s/^XS-Vcs/Vcs/ + + bump Standards-Version to 3.7.3 (no changes) + + libxfont1 is Section: libs + + libxfont-dev and libxfont1-dbg are Section: libdevel + + -- Julien Cristau Thu, 17 Jan 2008 00:09:38 +0100 + +libxfont (1:1.3.1-1) unstable; urgency=low + + * New upstream release. + * Add libxfont1.shlibs, bump shlibs to >= 1:1.2.9. + + -- Julien Cristau Wed, 05 Sep 2007 22:45:57 +0200 + +libxfont (1:1.2.9-1) unstable; urgency=low + + * New upstream version. + - Add a new 'catalogue' FPE (font path element), which takes font + paths from symlinks in a dir. + * Use libxfont1 (= ${binary:Version}) instead of ${Source-Version} + in debian/control. + + -- Drew Parsons Sat, 23 Jun 2007 09:40:45 +1000 + +libxfont (1:1.2.8-1) unstable; urgency=low + + * Add XS-Vcs-Browser to debian/control. + * New upstream release. + + drop patch from 1:1.2.2-2, applied upstream. + * Upload to unstable. + + -- Julien Cristau Wed, 11 Apr 2007 15:52:11 +0200 + +libxfont (1:1.2.7-1) experimental; urgency=low + + * New upstream release. + * Add XS-Vcs-Git header to debian/control, and drop obsolete CVS information. + * Install the upstream ChangeLog. + + -- Julien Cristau Fri, 16 Feb 2007 14:32:57 +0100 + +libxfont (1:1.2.2-2) unstable; urgency=high + + * Grab patch from upstream git to fix security issues: + + CVE-2007-1351: BDFFont Parsing Integer Overflow + + CVE-2007-1352: fonts.dir File Parsing Integer Overflow + + -- Julien Cristau Tue, 03 Apr 2007 19:31:24 +0200 + +libxfont (1:1.2.2-1) unstable; urgency=high + + * New upstream version. + - closes security bug in CID encoded fonts (iDefense CVE-ID + 2006-3739, 2006-3740) + - applies patches 10_freetype_buffer_overflow.patch, 10_pcf_font.patch + * dbg package has priority extra. + + -- Drew Parsons Wed, 13 Sep 2006 17:50:06 +1000 + +libxfont (1:1.2.0-2) unstable; urgency=high + + * Apply upstream patch 10_pcf_font.patch (security vulnerability + CVE-2006-3467). Closes: #383353. + * Upload to unstable to ensure patch is propagated quickly. + * Apply patch 10_freetype_buffer_overflow.patch while we're at it + (no known exploits). + + -- Drew Parsons Thu, 17 Aug 2006 07:45:40 +1000 + +libxfont (1:1.2.0-1) experimental; urgency=low + + * New upstream version. Closes: #364854. + - builds and works with Freetype 2.2. Closes: #362920, #370149. + * Standards version 3.7.2. + * libxfont-dev doesn't need both Depends: and Pre-Depends: x11-common. + * Use debhelper 5, tidy up debian/rules to match. + * libxfont does not provide libfontcache.so! + + -- Drew Parsons Thu, 27 Jul 2006 15:08:14 +1000 + +libxfont (1:1.1.0-1) UNRELEASED; urgency=low + + [ David Nusinow ] + * New upstream release + * Remove obsolete patch 01_fontserver_fix_SEGV.diff + + [ Andres Salomon ] + * Test for obj-$(DEB_BUILD_GNU_TYPE) before creating it during build; + idempotency fix. + * Run dh_install w/ --list-missing. + + -- Andres Salomon Mon, 17 Jul 2006 01:20:57 -0400 + +libxfont (1:1.0.0-4) unstable; urgency=low + + * Reorder makeshlib command in rules file so that ldconfig is run + properly. Thanks Drew Parsons and Steve Langasek. + * Add quilt to build-depends + + -- David Nusinow Wed, 19 Apr 2006 00:10:33 -0400 + +libxfont (1:1.0.0-3) unstable; urgency=low + + * Upload to unstable + + -- David Nusinow Thu, 23 Mar 2006 22:44:39 -0500 + +libxfont (1:1.0.0-2) experimental; urgency=low + + * Have libxfont-dev depend on libfreetype6-dev and libfontenc-dev. Thanks + Eugene Konev. + * Port patches from trunk + + general/099v_fontserver_fix_SEGV.diff + + -- David Nusinow Sun, 26 Feb 2006 18:35:44 -0500 + +libxfont (1:1.0.0-1) experimental; urgency=low + + * First upload to Debian + + -- David Nusinow Thu, 29 Dec 2005 20:51:40 -0500 + +libxfont (1:0.99.0+cvs.20050909-1) breezy; urgency=low + + * Fix the XFONT_FONTCACHE/FONTCACHE define in configure.ac (close: + Ubuntu#14319). + + -- Daniel Stone Fri, 9 Sep 2005 15:39:57 +1000 + +libxfont (1:0.99.0-1) breezy; urgency=low + + * First libxfont release. + + -- Daniel Stone Mon, 16 May 2005 22:10:17 +1000 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100755 index 0000000..69d42b6 --- /dev/null +++ b/debian/control @@ -0,0 +1,69 @@ +Source: libxfont +Section: x11 +Priority: optional +Maintainer: YoungHoon Jung , SangJin Lee , Debian X Strike Force +Uploaders: SooChan Lim , David Nusinow , Drew Parsons , Cyril Brulebois +Build-Depends: debhelper (>= 5), pkg-config, libfontenc-dev (>= 1:1.0.5-2), x11proto-core-dev, xtrans-dev, x11proto-fonts-dev, libfreetype6-dev, zlib1g-dev, libbz2-dev, quilt, xutils-dev (>= 1:7.5-1slp2), autoconf, automake, libtool, xmlto, +Standards-Version: 3.9.0 +Vcs-Git: git://git.debian.org/git/pkg-xorg/lib/libxfont +Vcs-Browser: http://git.debian.org/?p=pkg-xorg/lib/libxfont.git + +Package: libxfont1 +Section: libs +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Conflicts: xprint (<< 2:1.6.0-1) +Description: X11 font rasterisation library + libXfont provides various services for X servers, most notably font + selection and rasterisation (through external libraries). + . + More information about X.Org can be found at: + + . + This module can be found at + git://anongit.freedesktop.org/git/xorg/lib/libXfont + +#Package: libxfont1-udeb +#XC-Package-Type: udeb +#Section: debian-installer +#Architecture: any +#Depends: ${shlibs:Depends}, ${misc:Depends} +#Description: X11 font rasterisation library +# This is a udeb, or a microdeb, for the debian-installer. + +Package: libxfont1-dbg +Section: debug +Architecture: any +Priority: extra +Depends: ${shlibs:Depends}, ${misc:Depends}, libxfont1 (= ${binary:Version}) +Description: X11 font rasterisation library (debug package) + libXfont provides various services for X servers, most notably font + selection and rasterisation (through external libraries). + . + This package contains the debug versions of the library found in libxfont1. + Non-developers likely have little use for this package. + . + More information about X.Org can be found at: + + . + This module can be found at + git://anongit.freedesktop.org/git/xorg/lib/libXfont + +Package: libxfont-dev +Section: libdevel +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libxfont1 (= ${binary:Version}), libx11-dev, x11proto-core-dev, x11proto-fonts-dev, libfreetype6-dev, libfontenc-dev (>= 1:1.0.1-1) +Pre-Depends: x11-common (>= 1:7.0.0) +Replaces: xlibs-static-dev (<< 6.8.2-51) +Description: X11 font rasterisation library (development headers) + libXfont provides various services for X servers, most notably font + selection and rasterisation (through external libraries). + . + This package contains the development headers for the library found in + libxfont1. Non-developers likely have little use for this package. + . + More information about X.Org can be found at: + + . + This module can be found at + git://anongit.freedesktop.org/git/xorg/lib/libXfont diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..ec711a1 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,265 @@ +This package was downloaded from +http://xorg.freedesktop.org/releases/individual/lib/ + +Copyright © 2007 Red Hat, Inc +Copyright © 2008,2009 Sun Microsystems, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +Copyright (c) 1997 by Mark Leisher +Copyright (c) 1998-2003 by Juliusz Chroboczek +Copyright (c) 1998 Go Watanabe, All rights reserved. +Copyright (c) 1998 Kazushi (Jam) Marukawa, All rights reserved. +Copyright (c) 1998 Takuya SHIOZAKI, All rights reserved. +Copyright (c) 1998 X-TrueType Server Project, All rights reserved. +Copyright (c) 2003-2004 After X-TT Project, All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + + +Copyright 1999 SuSE, Inc. + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the name of SuSE not be used in advertising or +publicity pertaining to distribution of the software without specific, +written prior permission. SuSE makes no representations about the +suitability of this software for any purpose. It is provided "as is" +without express or implied warranty. + +SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE +BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +Copyright 1990 Network Computing Devices + +Permission to use, copy, modify, distribute, and sell this software and +its documentation for any purpose is hereby granted without fee, provided +that the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the name of Network Computing Devices not be used +in advertising or publicity pertaining to distribution of the software +without specific, written prior permission. Network Computing Devices +makes no representations about the suitability of this software for any +purpose. It is provided "as is" without express or implied warranty. + +NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, +IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, +INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE +OR PERFORMANCE OF THIS SOFTWARE. + + +Copyright 1990 Network Computing Devices + +Permission to use, copy, modify, distribute, and sell this software and +its documentation for any purpose is hereby granted without fee, provided +that the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the names of Network Computing Devices, or Digital +not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +NETWORK COMPUTING DEVICES, AND DIGITAL AND DISCLAIM ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, +OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + + +[Note: clause 3 in the following license, the "advertising clause", was +rescinded by Berkeley in 1999. See +] + +Copyright (c) 1991, 1993 + The Regents of the University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by the University of + California, Berkeley and its contributors. +4. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + + +Copyright (c) 1998-1999 Shunsuke Akiyama . +All rights reserved. +Copyright (c) 1998-1999 X-TrueType Server Project, All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + + +Copyright © 2004 Keith Packard + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the name of Keith Packard not be used in +advertising or publicity pertaining to distribution of the software without +specific, written prior permission. Keith Packard makes no +representations about the suitability of this software for any purpose. It +is provided "as is" without express or implied warranty. + +KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + + +/* lib/font/fontfile/gunzip.c + written by Mark Eichin September 1996. + intended for inclusion in X11 public releases. */ + + +Copyright (c) 1999 The XFree86 Project Inc. + +All Rights Reserved. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The XFree86 Project +Inc. shall not be used in advertising or otherwise to promote the +sale, use or other dealings in this Software without prior written +authorization from The XFree86 Project Inc.. diff --git a/debian/libxfont-dev.install b/debian/libxfont-dev.install new file mode 100755 index 0000000..b0cfdd5 --- /dev/null +++ b/debian/libxfont-dev.install @@ -0,0 +1,5 @@ +usr/include/X11/* +usr/lib/libXfont.a +usr/lib/libXfont.so +usr/lib/libXfont.la +usr/lib/pkgconfig/xfont.pc diff --git a/debian/libxfont1-udeb.install b/debian/libxfont1-udeb.install new file mode 100644 index 0000000..e73e376 --- /dev/null +++ b/debian/libxfont1-udeb.install @@ -0,0 +1,2 @@ +usr/lib/libXfont.so.1* + diff --git a/debian/libxfont1.install b/debian/libxfont1.install new file mode 100644 index 0000000..e73e376 --- /dev/null +++ b/debian/libxfont1.install @@ -0,0 +1,2 @@ +usr/lib/libXfont.so.1* + diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..58a8919 --- /dev/null +++ b/debian/rules @@ -0,0 +1,104 @@ +#!/usr/bin/make -f +# debian/rules for the Debian libxfont package. +# Copyright © 2004 Scott James Remnant +# Copyright © 2005 Daniel Stone +# Copyright © 2005 David Nusinow + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +PACKAGE = libxfont1 + +include debian/xsfbs/xsfbs.mk + +CFLAGS = -Wall -g +ifneq (,$(filter noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif +ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) + NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) + MAKEFLAGS += -j$(NUMJOBS) +endif + +DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH) +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) +ifeq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE)) + confflags += --build=$(DEB_HOST_GNU_TYPE) +else + confflags += --build=$(DEB_HOST_GNU_TYPE) --host=$(DEB_HOST_GNU_TYPE) +# confflags += --build=$(DEB_BUILD_GNU_TYPE) --host=$(DEB_HOST_GNU_TYPE) +endif + +confflags += --enable-fc --enable-builtins --enable-pcfformat --enable-bdfformat + +configure: $(STAMP_DIR)/patch + autoreconf -vfi + +obj-$(DEB_BUILD_GNU_TYPE)/config.status: configure + mkdir -p obj-$(DEB_BUILD_GNU_TYPE) + cd obj-$(DEB_BUILD_GNU_TYPE) && \ + ../configure --prefix=/usr --mandir=\$${prefix}/share/man \ + --infodir=\$${prefix}/share/info $(confflags) \ + --without-bzip2 \ + CFLAGS="$(CFLAGS)" + +build: build-stamp +build-stamp: obj-$(DEB_BUILD_GNU_TYPE)/config.status + dh_testdir + + cd obj-$(DEB_BUILD_GNU_TYPE) && $(MAKE) + >$@ + +clean: xsfclean + dh_testdir + dh_testroot + rm -f build-stamp + + rm -f config.cache config.log config.status + rm -f */config.cache */config.log */config.status + rm -f conftest* */conftest* + rm -rf autom4te.cache */autom4te.cache + rm -rf obj-* + rm -f $$(find -name Makefile.in) + rm -f aclocal.m4 config.guess config.h.in config.sub configure + rm -f depcomp install-sh ltmain.sh missing mkinstalldirs + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + cd obj-$(DEB_BUILD_GNU_TYPE) && $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + + dh_installdocs + dh_install --sourcedir=debian/tmp --list-missing + #dh_install --sourcedir=debian/tmp --list-missing -XlibXfont.la + dh_installchangelogs ChangeLog + dh_link + dh_strip --dbg-package=$(PACKAGE)-dbg + dh_compress + dh_fixperms + dh_makeshlibs -V'libxfont1 (>= 1:1.4.2)' + dh_shlibdeps + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb + +# Build architecture-independent files here. +binary-indep: build install +# Nothing to do + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install diff --git a/debian/watch b/debian/watch new file mode 100644 index 0000000..a241b87 --- /dev/null +++ b/debian/watch @@ -0,0 +1,2 @@ +version=3 +http://xorg.freedesktop.org/releases/individual/lib/ libXfont-(.*)\.tar\.gz diff --git a/debian/xsfbs/repack.sh b/debian/xsfbs/repack.sh new file mode 100644 index 0000000..5935cc9 --- /dev/null +++ b/debian/xsfbs/repack.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +set -e + +if ! [ -d debian/prune ]; then + exit 0 +fi + +if [ "x$1" != x--upstream-version ]; then + exit 1 +fi + +version="$2" +filename="$3" + +if [ -z "$version" ] || ! [ -f "$filename" ]; then + exit 1 +fi + +dir="$(pwd)" +tempdir="$(mktemp -d)" + +cd "$tempdir" +tar xf "$dir/$filename" +cat "$dir"/debian/prune/* | while read file; do rm -f */$file; done + +tar czf "$dir/$filename" * +cd "$dir" +rm -rf "$tempdir" +echo "Done pruning upstream tarball" + +exit 0 diff --git a/debian/xsfbs/xsfbs.mk b/debian/xsfbs/xsfbs.mk new file mode 100644 index 0000000..5e16b10 --- /dev/null +++ b/debian/xsfbs/xsfbs.mk @@ -0,0 +1,276 @@ +#!/usr/bin/make -f + +# Debian X Strike Force Build System (XSFBS): Make portion + +# Copyright 1996 Stephen Early +# Copyright 1997 Mark Eichin +# Copyright 1998-2005, 2007 Branden Robinson +# Copyright 2005 David Nusinow +# +# Licensed under the GNU General Public License, version 2. See the file +# /usr/share/common-licenses/GPL or . + +# Originally by Stephen Early +# Modified by Mark W. Eichin +# Modified by Adam Heath +# Modified by Branden Robinson +# Modified by Fabio Massimo Di Nitto +# Modified by David Nusinow +# Acknowledgements to Manoj Srivastava. + +# Pass $(DH_OPTIONS) into the environment for debhelper's benefit. +export DH_OPTIONS + +# force quilt to not use ~/.quiltrc and to use debian/patches +QUILT = QUILT_PATCHES=debian/patches quilt --quiltrc /dev/null + +# Set up parameters for the upstream build environment. + +# Determine (source) package name from Debian changelog. +SOURCE_NAME:=$(shell dpkg-parsechangelog -ldebian/changelog \ + | grep '^Source:' | awk '{print $$2}') + +# Determine package version from Debian changelog. +SOURCE_VERSION:=$(shell dpkg-parsechangelog -ldebian/changelog \ + | grep '^Version:' | awk '{print $$2}') + +# Determine upstream version number. +UPSTREAM_VERSION:=$(shell echo $(SOURCE_VERSION) | sed 's/-.*//') + +# Determine the source version without the epoch for make-orig-tar-gz +NO_EPOCH_VER:=$(shell echo $(UPSTREAM_VERSION) | sed 's/^.://') + +# Figure out who's building this package. +BUILDER:=$(shell echo $${DEBEMAIL:-$${EMAIL:-$$(echo $$LOGNAME@$$(cat /etc/mailname 2>/dev/null))}}) + +# Find out if this is an official build; an official build has nothing but +# digits, dots, and/or the codename of a release in the Debian part of the +# version number. Anything else indicates an unofficial build. +OFFICIAL_BUILD:=$(shell VERSION=$(SOURCE_VERSION); if ! expr "$$(echo $${VERSION\#\#*-} | sed 's/\(woody\|sarge\|etch\|lenny\)//g')" : ".*[^0-9.].*" >/dev/null 2>&1; then echo yes; fi) + +# Set up parameters for the Debian build environment. + +# Determine our architecture. +BUILD_ARCH:=$(shell dpkg-architecture -qDEB_BUILD_ARCH) +# Work around some old-time dpkg braindamage. +BUILD_ARCH:=$(subst i486,i386,$(BUILD_ARCH)) +# The DEB_HOST_ARCH variable may be set per the Debian cross-compilation policy. +ifdef DEB_HOST_ARCH + ARCH:=$(DEB_HOST_ARCH) +else + # dpkg-cross sets the ARCH environment variable; if set, use it. + ifdef ARCH + ARCH:=$(ARCH) + else + ARCH:=$(BUILD_ARCH) + endif +endif + +# $(STAMP_DIR) houses stamp files for complex targets. +STAMP_DIR:=stampdir + +# $(DEBTREEDIR) is where all install rules are told (via $(DESTDIR)) to place +# their files. +DEBTREEDIR:=$(CURDIR)/debian/tmp + +# All "important" targets have four lines: +# 1) A target name that is invoked by a package-building tool or the user. +# This consists of a dependency on a "$(STAMP_DIR)/"-prefixed counterpart. +# 2) A line delcaring 1) as a phony target (".PHONY:"). +# 3) A "$(STAMP_DIR)/"-prefixed target which does the actual work, and may +# depend on other targets. +# 4) A line declaring 3) as a member of the $(stampdir_targets) variable; the +# "$(STAMP_DIR)/" prefix is omitted. +# +# This indirection is needed so that the "stamp" files that signify when a rule +# is done can be located in a separate "stampdir". Recall that make has no way +# to know when a goal has been met for a phony target (like "build" or +# "install"). +# +# At the end of each "$(STAMP_DIR)/" target, be sure to run the command ">$@" +# so that the target will not be run again. Removing the file will make Make +# run the target over. + +# All phony targets should be declared as dependencies of .PHONY, even if they +# do not have "($STAMP_DIR)/"-prefixed counterparts. + +# Define a harmless default rule to keep things from going nuts by accident. +.PHONY: default +default: + +# Set up the $(STAMP_DIR) directory. +.PHONY: stampdir +stampdir_targets+=stampdir +stampdir: $(STAMP_DIR)/stampdir +$(STAMP_DIR)/stampdir: + mkdir $(STAMP_DIR) + >$@ + +# Set up the package build directory as quilt expects to find it. +.PHONY: prepare +stampdir_targets+=prepare +prepare: $(STAMP_DIR)/prepare +$(STAMP_DIR)/prepare: $(STAMP_DIR)/log $(STAMP_DIR)/genscripts + >$@ + +.PHONY: log +stampdir_targets+=log +log: $(STAMP_DIR)/log +$(STAMP_DIR)/log: $(STAMP_DIR)/stampdir + mkdir -p $(STAMP_DIR)/log + +# Apply all patches to the upstream source. +.PHONY: patch +stampdir_targets+=patch +patch: $(STAMP_DIR)/patch +$(STAMP_DIR)/patch: $(STAMP_DIR)/prepare + if ! [ `which quilt` ]; then \ + echo "Couldn't find quilt. Please install it or add it to the build-depends for this package."; \ + exit 1; \ + fi; \ + if $(QUILT) next >/dev/null 2>&1; then \ + echo -n "Applying patches..."; \ + if $(QUILT) push -a -v >$(STAMP_DIR)/log/patch 2>&1; then \ + cat $(STAMP_DIR)/log/patch; \ + echo "successful."; \ + else \ + cat $(STAMP_DIR)/log/patch; \ + echo "failed! (check $(STAMP_DIR)/log/patch for details)"; \ + exit 1; \ + fi; \ + else \ + echo "No patches to apply"; \ + fi; \ + >$@ + +# Revert all patches to the upstream source. +.PHONY: unpatch +unpatch: $(STAMP_DIR)/log + rm -f $(STAMP_DIR)/patch + @echo -n "Unapplying patches..."; \ + if $(QUILT) applied >/dev/null 2>/dev/null; then \ + if $(QUILT) pop -a -v >$(STAMP_DIR)/log/unpatch 2>&1; then \ + cat $(STAMP_DIR)/log/unpatch; \ + echo "successful."; \ + else \ + cat $(STAMP_DIR)/log/unpatch; \ + echo "failed! (check $(STAMP_DIR)/log/unpatch for details)"; \ + exit 1; \ + fi; \ + else \ + echo "nothing to do."; \ + fi + +# Clean the generated maintainer scripts. +.PHONY: cleanscripts +cleanscripts: + rm -f $(STAMP_DIR)/genscripts + rm -f debian/*.config \ + debian/*.postinst \ + debian/*.postrm \ + debian/*.preinst \ + debian/*.prerm + +# Clean the package build tree. +.PHONY: xsfclean +xsfclean: cleanscripts unpatch + dh_testdir + rm -rf .pc + rm -rf $(STAMP_DIR) + dh_clean + +# Remove files from the upstream source tree that we don't need, or which have +# licensing problems. It must be run before creating the .orig.tar.gz. +# +# Note: This rule is for Debian package maintainers' convenience, and is not +# needed for conventional build scenarios. +.PHONY: prune-upstream-tree +prune-upstream-tree: + # Ensure we're in the correct directory. + dh_testdir + grep -rvh '^#' debian/prune/ | xargs --no-run-if-empty rm -rf + +# Verify that there are no offsets or fuzz in the patches we apply. +# +# Note: This rule is for Debian package maintainers' convenience, and is not +# needed for conventional build scenarios. +.PHONY: patch-audit +patch-audit: prepare unpatch + @echo -n "Auditing patches..."; \ + >$(STAMP_DIR)/log/patch; \ + FUZZY=; \ + while [ -n "$$($(QUILT) next)" ]; do \ + RESULT=$$($(QUILT) push -v | tee -a $(STAMP_DIR)/log/patch | grep ^Hunk | sed 's/^Hunk.*\(succeeded\|FAILED\).*/\1/');\ + case "$$RESULT" in \ + succeeded) \ + echo "fuzzy patch: $$($(QUILT) top)" \ + | tee -a $(STAMP_DIR)/log/$$($(QUILT) top); \ + FUZZY=yes; \ + ;; \ + FAILED) \ + echo "broken patch: $$($(QUILT) next)" \ + | tee -a $(STAMP_DIR)/log/$$($(QUILT) next); \ + exit 1; \ + ;; \ + esac; \ + done; \ + if [ -n "$$FUZZY" ]; then \ + echo "there were fuzzy patches; please fix."; \ + exit 1; \ + else \ + echo "done."; \ + fi + +# Generate the maintainer scripts. +.PHONY: genscripts +stampdir_targets+=genscripts +genscripts: $(STAMP_DIR)/genscripts +$(STAMP_DIR)/genscripts: $(STAMP_DIR)/stampdir + for FILE in debian/*.config.in \ + debian/*.postinst.in \ + debian/*.postrm.in \ + debian/*.preinst.in \ + debian/*.prerm.in; do \ + if [ -e "$$FILE" ]; then \ + MAINTSCRIPT=$$(echo $$FILE | sed 's/.in$$//'); \ + sed -n '1,/^#INCLUDE_SHELL_LIB#$$/p' <$$FILE \ + | sed -e '/^#INCLUDE_SHELL_LIB#$$/d' >$$MAINTSCRIPT.tmp; \ + cat debian/xsfbs/xsfbs.sh >>$$MAINTSCRIPT.tmp; \ + sed -n '/^#INCLUDE_SHELL_LIB#$$/,$$p' <$$FILE \ + | sed -e '/^#INCLUDE_SHELL_LIB#$$/d' >>$$MAINTSCRIPT.tmp; \ + sed -e 's/@SOURCE_VERSION@/$(SOURCE_VERSION)/' \ + -e 's/@OFFICIAL_BUILD@/$(OFFICIAL_BUILD)/' \ + <$$MAINTSCRIPT.tmp >$$MAINTSCRIPT; \ + rm $$MAINTSCRIPT.tmp; \ + fi; \ + done + # Validate syntax of generated shell scripts. + #sh debian/scripts/validate-posix-sh debian/*.config \ + # debian/*.postinst \ + # debian/*.postrm \ + # debian/*.preinst \ + # debian/*.prerm + >$@ + +SERVERMINVERS = $(shell cat /usr/share/xserver-xorg/serverminver 2>/dev/null) +VIDEOABI = $(shell cat /usr/share/xserver-xorg/videoabiver 2>/dev/null) +INPUTABI = $(shell cat /usr/share/xserver-xorg/inputabiver 2>/dev/null) +SERVER_DEPENDS = xserver-xorg-core (>= $(SERVERMINVERS)) +VIDDRIVER_PROVIDES = xserver-xorg-video-$(VIDEOABI) +INPDRIVER_PROVIDES = xserver-xorg-input-$(INPUTABI) +ifeq ($(PACKAGE),) +PACKAGE=$(shell awk '/^Package:/ { print $$2; exit }' < debian/control) +endif + +.PHONY: serverabi +serverabi: install +ifeq ($(SERVERMINVERS),) + @echo error: xserver-xorg-dev needs to be installed + @exit 1 +else + echo "xserver:Depends=$(SERVER_DEPENDS)" >> debian/$(PACKAGE).substvars + echo "xviddriver:Provides=$(VIDDRIVER_PROVIDES)" >> debian/$(PACKAGE).substvars + echo "xinpdriver:Provides=$(INPDRIVER_PROVIDES)" >> debian/$(PACKAGE).substvars +endif + +# vim:set noet ai sts=8 sw=8 tw=0: diff --git a/debian/xsfbs/xsfbs.sh b/debian/xsfbs/xsfbs.sh new file mode 100644 index 0000000..813fd8d --- /dev/null +++ b/debian/xsfbs/xsfbs.sh @@ -0,0 +1,622 @@ +# This is the X Strike Force shell library for X Window System package +# maintainer scripts. It serves to define shell functions commonly used by +# such packages, and performs some error checking necessary for proper operation +# of those functions. By itself, it does not "do" much; the maintainer scripts +# invoke the functions defined here to accomplish package installation and +# removal tasks. + +# If you are reading this within a Debian package maintainer script (e.g., +# /var/lib/dpkg/info/PACKAGE.{config,preinst,postinst,prerm,postrm}), you can +# skip past this library by scanning forward in this file to the string +# "GOBSTOPPER". + +SOURCE_VERSION=@SOURCE_VERSION@ +OFFICIAL_BUILD=@OFFICIAL_BUILD@ + +# Use special abnormal exit codes so that problems with this library are more +# easily tracked down. +SHELL_LIB_INTERNAL_ERROR=86 +SHELL_LIB_THROWN_ERROR=74 +SHELL_LIB_USAGE_ERROR=99 + +# old -> new variable names +if [ -z "$DEBUG_XORG_PACKAGE" ] && [ -n "$DEBUG_XFREE86_PACKAGE" ]; then + DEBUG_XORG_PACKAGE="$DEBUG_XFREE86_PACKAGE" +fi +if [ -z "$DEBUG_XORG_DEBCONF" ] && [ -n "$DEBUG_XFREE86_DEBCONF" ]; then + DEBUG_XORG_DEBCONF="$DEBUG_XFREE86_DEBCONF" +fi + +# initial sanity checks +if [ -z "$THIS_PACKAGE" ]; then + cat >&2 < on the World Wide Web for +instructions, read the file /usr/share/doc/debian/bug-reporting.txt from the +"doc-debian" package, or install the "reportbug" package and use the command of +the same name to file a report against version $SOURCE_VERSION of this package. +EOF + exit $SHELL_LIB_USAGE_ERROR +fi + +if [ -z "$THIS_SCRIPT" ]; then + cat >&2 < on the World Wide Web for +instructions, read the file /usr/share/doc/debian/bug-reporting.txt from the +"doc-debian" package, or install the "reportbug" package and use the command of +the same name to file a report against version $SOURCE_VERSION of the +"$THIS_PACKAGE" package. +EOF + exit $SHELL_LIB_USAGE_ERROR +fi + +if [ "$1" = "reconfigure" ] || [ -n "$DEBCONF_RECONFIGURE" ]; then + RECONFIGURE="true" +else + RECONFIGURE= +fi + +if ([ "$1" = "install" ] || [ "$1" = "configure" ]) && [ -z "$2" ]; then + FIRSTINST="yes" +fi + +if [ -z "$RECONFIGURE" ] && [ -z "$FIRSTINST" ]; then + UPGRADE="yes" +fi + +trap "message;\ + message \"Received signal. Aborting $THIS_PACKAGE package $THIS_SCRIPT script.\";\ + message;\ + exit 1" HUP INT QUIT TERM + +reject_nondigits () { + # syntax: reject_nondigits [ operand ... ] + # + # scan operands (typically shell variables whose values cannot be trusted) for + # characters other than decimal digits and barf if any are found + while [ -n "$1" ]; do + # does the operand contain anything but digits? + if ! expr "$1" : "[[:digit:]]\+$" > /dev/null 2>&1; then + # can't use die(), because it wraps message() which wraps this function + echo "$THIS_PACKAGE $THIS_SCRIPT error: reject_nondigits() encountered" \ + "possibly malicious garbage \"$1\"" >&2 + exit $SHELL_LIB_THROWN_ERROR + fi + shift + done +} + +reject_unlikely_path_chars () { + # syntax: reject_unlikely_path_chars [ operand ... ] + # + # scan operands (typically shell variables whose values cannot be trusted) for + # characters unlikely to be seen in a path and which the shell might + # interpret and barf if any are found + while [ -n "$1" ]; do + # does the operand contain any funny characters? + if expr "$1" : '.*[!$&()*;<>?|].*' > /dev/null 2>&1; then + # can't use die(), because I want to avoid forward references + echo "$THIS_PACKAGE $THIS_SCRIPT error: reject_unlikely_path_chars()" \ + "encountered possibly malicious garbage \"$1\"" >&2 + exit $SHELL_LIB_THROWN_ERROR + fi + shift + done +} + +# Query the terminal to establish a default number of columns to use for +# displaying messages to the user. This is used only as a fallback in the +# event the COLUMNS variable is not set. ($COLUMNS can react to SIGWINCH while +# the script is running, and this cannot, only being calculated once.) +DEFCOLUMNS=$(stty size 2> /dev/null | awk '{print $2}') || true +if ! expr "$DEFCOLUMNS" : "[[:digit:]]\+$" > /dev/null 2>&1; then + DEFCOLUMNS=80 +fi + +message () { + # pretty-print messages of arbitrary length + reject_nondigits "$COLUMNS" + echo "$*" | fmt -t -w ${COLUMNS:-$DEFCOLUMNS} >&2 +} + +observe () { + # syntax: observe message ... + # + # issue observational message suitable for logging someday when support for + # it exists in dpkg + if [ -n "$DEBUG_XORG_PACKAGE" ]; then + message "$THIS_PACKAGE $THIS_SCRIPT note: $*" + fi +} + +warn () { + # syntax: warn message ... + # + # issue warning message suitable for logging someday when support for + # it exists in dpkg; also send to standard error + message "$THIS_PACKAGE $THIS_SCRIPT warning: $*" +} + +die () { + # syntax: die message ... + # + # exit script with error message + message "$THIS_PACKAGE $THIS_SCRIPT error: $*" + exit $SHELL_LIB_THROWN_ERROR +} + +internal_error () { + # exit script with error; essentially a "THIS SHOULD NEVER HAPPEN" message + message "internal error: $*" + if [ -n "$OFFICIAL_BUILD" ]; then + message "Please report a bug in the $THIS_SCRIPT script of the" \ + "$THIS_PACKAGE package, version $SOURCE_VERSION to the Debian Bug" \ + "Tracking System. Include all messages above that mention the" \ + "$THIS_PACKAGE package. Visit " \ + " on the World Wide Web for" \ + "instructions, read the file" \ + "/usr/share/doc/debian/bug-reporting.txt from the doc-debian" \ + "package, or install the reportbug package and use the command of" \ + "the same name to file a report." + fi + exit $SHELL_LIB_INTERNAL_ERROR +} + +usage_error () { + message "usage error: $*" + message "Please report a bug in the $THIS_SCRIPT script of the" \ + "$THIS_PACKAGE package, version $SOURCE_VERSION to the Debian Bug" \ + "Tracking System. Include all messages above that mention the" \ + "$THIS_PACKAGE package. Visit " \ + " on the World Wide Web for" \ + "instructions, read the file" \ + "/usr/share/doc/debian/bug-reporting.txt from the doc-debian" \ + "package, or install the reportbug package and use the command of" \ + "the same name to file a report." + exit $SHELL_LIB_USAGE_ERROR +} + +font_update () { + # run $UPDATECMDS in $FONTDIRS + + local dir cmd shortcmd x_font_dir_prefix + + x_font_dir_prefix="/usr/share/fonts/X11" + + if [ -z "$UPDATECMDS" ]; then + usage_error "font_update() called but \$UPDATECMDS not set" + fi + if [ -z "$FONTDIRS" ]; then + usage_error "font_update() called but \$FONTDIRS not set" + fi + + reject_unlikely_path_chars "$UPDATECMDS" + reject_unlikely_path_chars "$FONTDIRS" + + for dir in $FONTDIRS; do + if [ -d "$x_font_dir_prefix/$dir" ]; then + for cmd in $UPDATECMDS; do + if which "$cmd" > /dev/null 2>&1; then + shortcmd=${cmd##*/} + observe "running $shortcmd in $dir font directory" + cmd_opts= + if [ "$shortcmd" = "update-fonts-alias" ]; then + cmd_opts=--x11r7-layout + fi + if [ "$shortcmd" = "update-fonts-dir" ]; then + cmd_opts=--x11r7-layout + fi + if [ "$shortcmd" = "update-fonts-scale" ]; then + cmd_opts=--x11r7-layout + fi + $cmd $cmd_opts $dir || warn "$cmd $cmd_opts $dir" \ + "failed; font directory data may not" \ + "be up to date" + else + warn "$cmd not found; not updating corresponding $dir font" \ + "directory data" + fi + done + else + warn "$dir is not a directory; not updating font directory data" + fi + done +} + +remove_conffile_prepare () { + # syntax: remove_conffile_prepare filename official_md5sum ... + # + # Check a conffile "filename" against a list of canonical MD5 checksums. + # If the file's current MD5 checksum matches one of the "official_md5sum" + # operands provided, then prepare the conffile for removal from the system. + # We defer actual deletion until the package is configured so that we can + # roll this operation back if package installation fails. + # + # Call this function from a preinst script in the event $1 is "upgrade" or + # "install" and verify $2 to ensure the package is being upgraded from a + # version (or installed over a version removed-but-not-purged) prior to the + # one in which the conffile was obsoleted. + + local conffile current_checksum + + # validate arguments + if [ $# -lt 2 ]; then + usage_error "remove_conffile_prepare() called with wrong number of" \ + "arguments; expected at least 2, got $#" + exit $SHELL_LIB_USAGE_ERROR + fi + + conffile="$1" + shift + + # does the conffile even exist? + if [ -e "$conffile" ]; then + # calculate its checksum + current_checksum=$(md5sum < "$conffile" | sed 's/[[:space:]].*//') + # compare it to each supplied checksum + while [ -n "$1" ]; do + if [ "$current_checksum" = "$1" ]; then + # we found a match; move the confffile and stop looking + observe "preparing obsolete conffile $conffile for removal" + mv "$conffile" "$conffile.$THIS_PACKAGE-tmp" + break + fi + shift + done + fi +} + +remove_conffile_lookup () { + # syntax: remove_conffile_lookup package filename + # + # Lookup the md5sum of a conffile in dpkg's database, and prepare for removal + # if it matches the actual file's md5sum. + # + # Call this function when you would call remove_conffile_prepare but only + # want to check against dpkg's status database instead of known checksums. + + local package conffile old_md5sum + + # validate arguments + if [ $# -ne 2 ]; then + usage_error "remove_conffile_lookup() called with wrong number of" \ + "arguments; expected 1, got $#" + exit $SHELL_LIB_USAGE_ERROR + fi + + package="$1" + conffile="$2" + + if ! [ -e "$conffile" ]; then + return + fi + old_md5sum="$(dpkg-query -W -f='${Conffiles}' "$package" | \ + awk '{ if (match($0, "^ '"$conffile"' ")) print $2}')" + if [ -n "$old_md5sum" ]; then + remove_conffile_prepare "$conffile" "$old_md5sum" + fi +} + +remove_conffile_commit () { + # syntax: remove_conffile_commit filename + # + # Complete the removal of a conffile "filename" that has become obsolete. + # + # Call this function from a postinst script after having used + # remove_conffile_prepare() in the preinst. + + local conffile + + # validate arguments + if [ $# -ne 1 ]; then + usage_error "remove_conffile_commit() called with wrong number of" \ + "arguments; expected 1, got $#" + exit $SHELL_LIB_USAGE_ERROR + fi + + conffile="$1" + + # if the temporary file created by remove_conffile_prepare() exists, remove it + if [ -e "$conffile.$THIS_PACKAGE-tmp" ]; then + observe "committing removal of obsolete conffile $conffile" + rm "$conffile.$THIS_PACKAGE-tmp" + fi +} + +remove_conffile_rollback () { + # syntax: remove_conffile_rollback filename + # + # Roll back the removal of a conffile "filename". + # + # Call this function from a postrm script in the event $1 is "abort-upgrade" + # or "abort-install" is after having used remove_conffile_prepare() in the + # preinst. + + local conffile + + # validate arguments + if [ $# -ne 1 ]; then + usage_error "remove_conffile_rollback() called with wrong number of" \ + "arguments; expected 1, got $#" + exit $SHELL_LIB_USAGE_ERROR + fi + + conffile="$1" + + # if the temporary file created by remove_conffile_prepare() exists, move it + # back + if [ -e "$conffile.$THIS_PACKAGE-tmp" ]; then + observe "rolling back removal of obsolete conffile $conffile" + mv "$conffile.$THIS_PACKAGE-tmp" "$conffile" + fi +} + +replace_conffile_with_symlink_prepare () { + # syntax: replace_conffile_with_symlink_prepare oldfilename newfilename \ + # official_md5sum ... + # + # Check a conffile "oldfilename" against a list of canonical MD5 checksums. + # If the file's current MD5 checksum matches one of the "official_md5sum" + # operands provided, then prepare the conffile for removal from the system. + # We defer actual deletion until the package is configured so that we can + # roll this operation back if package installation fails. Otherwise copy it + # to newfilename and let dpkg handle it through conffiles mechanism. + # + # Call this function from a preinst script in the event $1 is "upgrade" or + # "install" and verify $2 to ensure the package is being upgraded from a + # version (or installed over a version removed-but-not-purged) prior to the + # one in which the conffile was obsoleted. + + local conffile current_checksum + + # validate arguments + if [ $# -lt 3 ]; then + usage_error "replace_conffile_with_symlink_prepare() called with wrong" \ + " number of arguments; expected at least 3, got $#" + exit $SHELL_LIB_USAGE_ERROR + fi + + oldconffile="$1" + shift + newconffile="$1" + shift + + remove_conffile_prepare "$_oldconffile" "$@" + # If $oldconffile still exists, then md5sums didn't match. + # Copy it to new one. + if [ -f "$oldconffile" ]; then + cp "$oldconffile" "$newconffile" + fi + +} + +replace_conffile_with_symlink_commit () { + # syntax: replace_conffile_with_symlink_commit oldfilename + # + # Complete the removal of a conffile "oldfilename" that has been + # replaced by a symlink. + # + # Call this function from a postinst script after having used + # replace_conffile_with_symlink_prepare() in the preinst. + + local conffile + + # validate arguments + if [ $# -ne 1 ]; then + usage_error "replace_conffile_with_symlink_commit() called with wrong" \ + "number of arguments; expected 1, got $#" + exit $SHELL_LIB_USAGE_ERROR + fi + + conffile="$1" + + remove_conffile_commit "$conffile" +} + +replace_conffile_with_symlink_rollback () { + # syntax: replace_conffile_with_symlink_rollback oldfilename newfilename + # + # Roll back the replacing of a conffile "oldfilename" with symlink to + # "newfilename". + # + # Call this function from a postrm script in the event $1 is "abort-upgrade" + # or "abort-install" and verify $2 to ensure the package failed to upgrade + # from a version (or install over a version removed-but-not-purged) prior + # to the one in which the conffile was obsoleted. + # You should have used replace_conffile_with_symlink_prepare() in the + # preinst. + + local conffile + + # validate arguments + if [ $# -ne 2 ]; then + usage_error "replace_conffile_with_symlink_rollback() called with wrong" \ + "number of arguments; expected 2, got $#" + exit $SHELL_LIB_USAGE_ERROR + fi + + oldconffile="$1" + newconffile="$2" + + remove_conffile_rollback "$_oldconffile" + if [ -f "$newconffile" ]; then + rm "$newconffile" + fi +} + +run () { + # syntax: run command [ argument ... ] + # + # Run specified command with optional arguments and report its exit status. + # Useful for commands whose exit status may be nonzero, but still acceptable, + # or commands whose failure is not fatal to us. + # + # NOTE: Do *not* use this function with db_get or db_metaget commands; in + # those cases the return value of the debconf command *must* be checked + # before the string returned by debconf is used for anything. + + local retval + + # validate arguments + if [ $# -lt 1 ]; then + usage_error "run() called with wrong number of arguments; expected at" \ + "least 1, got $#" + exit $SHELL_LIB_USAGE_ERROR + fi + + "$@" || retval=$? + + if [ ${retval:-0} -ne 0 ]; then + observe "command \"$*\" exited with status $retval" + fi +} + +make_symlink_sane () { + # syntax: make_symlink_sane symlink target + # + # Ensure that the symbolic link symlink exists, and points to target. + # + # If symlink does not exist, create it and point it at target. + # + # If symlink exists but is not a symbolic link, back it up. + # + # If symlink exists, is a symbolic link, but points to the wrong location, fix + # it. + # + # If symlink exists, is a symbolic link, and already points to target, do + # nothing. + # + # This function wouldn't be needed if ln had an -I, --idempotent option. + + # Validate arguments. + if [ $# -ne 2 ]; then + usage_error "make_symlink_sane() called with wrong number of arguments;" \ + "expected 2, got $#" + exit $SHELL_LIB_USAGE_ERROR + fi + + # We could just use the positional parameters as-is, but that makes things + # harder to follow. + local symlink target + + symlink="$1" + target="$2" + + if [ -L "$symlink" ] && [ "$(readlink "$symlink")" = "$target" ]; then + observe "link from $symlink to $target already exists" + else + observe "creating symbolic link from $symlink to $target" + mkdir -p "${target%/*}" "${symlink%/*}" + ln -s -b -S ".dpkg-old" "$target" "$symlink" + fi +} + +migrate_dir_to_symlink () { + # syntax: migrate_dir_to_symlink old_location new_location + # + # Per Debian Policy section 6.5.4, "A directory will never be replaced by a + # symbolic link to a directory or vice versa; instead, the existing state + # (symlink or not) will be left alone and dpkg will follow the symlink if + # there is one." + # + # We have to do it ourselves. + # + # This function moves the contents of old_location, a directory, into + # new_location, a directory, then makes old_location a symbolic link to + # new_location. + # + # old_location need not exist, but if it does, it must be a directory (or a + # symlink to a directory). If it is not, it is backed up. If new_location + # exists already and is not a directory, it is backed up. + # + # This function should be called from a package's preinst so that other + # packages unpacked after this one --- but before this package's postinst runs + # --- are unpacked into new_location even if their payloads contain + # old_location filespecs. + + # Validate arguments. + if [ $# -ne 2 ]; then + usage_error "migrate_dir_to_symlink() called with wrong number of" + "arguments; expected 2, got $#" + exit $SHELL_LIB_USAGE_ERROR + fi + + # We could just use the positional parameters as-is, but that makes things + # harder to follow. + local new old + + old="$1" + new="$2" + + # Is old location a symlink? + if [ -L "$old" ]; then + # Does it already point to new location? + if [ "$(readlink "$old")" = "$new" ]; then + # Nothing to do; migration has already been done. + observe "migration of $old to $new already done" + return 0 + else + # Back it up. + warn "backing up symbolic link $old as $old.dpkg-old" + mv -b "$old" "$old.dpkg-old" + fi + fi + + # Does old location exist, but is not a directory? + if [ -e "$old" ] && ! [ -d "$old" ]; then + # Back it up. + warn "backing up non-directory $old as $old.dpkg-old" + mv -b "$old" "$old.dpkg-old" + fi + + observe "migrating $old to $new" + + # Is new location a symlink? + if [ -L "$new" ]; then + # Does it point the wrong way, i.e., back to where we're migrating from? + if [ "$(readlink "$new")" = "$old" ]; then + # Get rid of it. + observe "removing symbolic link $new which points to $old" + rm "$new" + else + # Back it up. + warn "backing up symbolic link $new as $new.dpkg-old" + mv -b "$new" "$new.dpkg-old" + fi + fi + + # Does new location exist, but is not a directory? + if [ -e "$new" ] && ! [ -d "$new" ]; then + warn "backing up non-directory $new as $new.dpkg-old" + mv -b "$new" "$new.dpkg-old" + fi + + # Create new directory if it does not yet exist. + if ! [ -e "$new" ]; then + observe "creating $new" + mkdir -p "$new" + fi + + # Copy files in old location to new location. Back up any filenames that + # already exist in the new location with the extension ".dpkg-old". + observe "copying files from $old to $new" + if ! (cd "$old" && cp -a -b -S ".dpkg-old" . "$new"); then + die "error(s) encountered while copying files from $old to $new" + fi + + # Remove files at old location. + observe "removing $old" + rm -r "$old" + + # Create symlink from old location to new location. + make_symlink_sane "$old" "$new" +} + +# vim:set ai et sw=2 ts=2 tw=80: + +# GOBSTOPPER: The X Strike Force shell library ends here. diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100755 index 0000000..dc3f0a6 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,66 @@ +# +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# + +# Developer documentation - not installed on system +EXTRA_DIST = fontlib.xml + +if ENABLE_DEVEL_DOCS +doc_sources = fontlib.xml + +if HAVE_XMLTO +noinst_DATA = $(doc_sources:.xml=.html) + +if HAVE_FOP +noinst_DATA += $(doc_sources:.xml=.ps) $(doc_sources:.xml=.pdf) +endif + +if HAVE_XMLTO_TEXT +noinst_DATA += $(doc_sources:.xml=.txt) +endif + +if HAVE_STYLESHEETS +XMLTO_FLAGS = -m $(XSL_STYLESHEET) + +noinst_DATA += xorg.css +xorg.css: $(STYLESHEET_SRCDIR)/xorg.css + $(AM_V_GEN)cp -pf $(STYLESHEET_SRCDIR)/xorg.css $@ +endif + +CLEANFILES = $(noinst_DATA) + +SUFFIXES = .xml .ps .pdf .txt .html + +.xml.txt: + $(AM_V_GEN)$(XMLTO) $(XMLTO_FLAGS) txt $< + +.xml.html: + $(AM_V_GEN)$(XMLTO) $(XMLTO_FLAGS) xhtml-nochunks $< + +.xml.pdf: + $(AM_V_GEN)$(XMLTO) $(XMLTO_FLAGS) --with-fop pdf $< + +.xml.ps: + $(AM_V_GEN)$(XMLTO) $(XMLTO_FLAGS) --with-fop ps $< + +endif HAVE_XMLTO +endif ENABLE_DEVEL_DOCS diff --git a/doc/fontlib.css b/doc/fontlib.css new file mode 100644 index 0000000..0bc70e6 --- /dev/null +++ b/doc/fontlib.css @@ -0,0 +1,41 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +.structname, .property, .errorname, .function, .parameter, .filename { + font-family: monospace; +} + +h1, .author, .pubdate { + text-align: center; +} + +.legalnotice { + text-align: justify; + font-size: small; + font-style: italic; +} + +.warning { + border: 1px solid red; + background: yellow; +} diff --git a/doc/fontlib.xml b/doc/fontlib.xml new file mode 100755 index 0000000..f2e4811 --- /dev/null +++ b/doc/fontlib.xml @@ -0,0 +1,659 @@ + + + + + +
+ + + + + + + + + The X Font Library + + July 27, 1991 + + + Keith + Packard + + MIT X Consortium + + + + David + Lemke + + Network Computing Devices + + + + + + Copyright 1993 Network Computing Devices + + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby + granted without fee, provided that the above copyright + notice appear in all copies and that both that copyright + notice and this permission notice appear in supporting + documentation, and that the name of Network Computing + Devices not be used in advertising or publicity pertaining + to distribution of the software without specific, written + prior permission. Network Computing Devices makes no + representations about the suitability of this software for + any purpose. It is provided “as is” without + express or implied warranty. + + + Copyright 1993, 1994 X Consortium + + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated + documentation files (the “Software”), to deal in the + Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY + OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X + CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of the X + Consortium shall not be used in advertising or otherwise to + promote the sale, use or other dealings in this Software + without prior written authorization from the X Consortium. + + + + + + + This document has not been updated since X11R6, and is likely + to be somewhat out of date for the current libXfont. + + + + + This document describes the data structures and interfaces for + using the X Font library. It is intended as a reference for + programmers building X and Font servers. You may want to refer + to the following documents: + + + + + + Definition of the Porting Layer for + the X v11 Sample Server for a discussion on how this + library interacts with the X server + + + + + Font Server Implementation + Overview which discusses the design of the font + server. + + + + + Bitmap Distribution Format + which covers the contents of the bitmap font files which this + library reads; although the library is capable of reading other + formats as well, including non-bitmap fonts. + + + + + The X Font Service Protocol + for a description of the constraints placed on the design by + including support for this font service mechanism. + + + + + + This document assumes the reader is familiar with the X server design, + the X protocol as it relates to fonts and the C programming language. + As with most MIT produced documentation, this relies heavily on the + source code, so have a listing handy. + + + + + Requirements for the Font library + + + + To avoid miles of duplicate code in the X server, the font server + and the various font manipulation tools, the font library should + provide interfaces appropriate for all of these tasks. In + particular, the X server and font server should be able to both + use the library to access disk based fonts, and to communicate + with a font server. By providing a general library, we hoped to + avoid duplicating code between the X server and font server. + + + + Another requirement is that the X server (or even a font server) + be able to continue servicing requests from other clients while + awaiting a response from the font server on behalf of one client. + This is the strongest requirement placed on the font library, and + has warped the design in curious ways. Because both the X server + and font server are single threaded, the font library must not + suspend internally, rather it returns an indication of suspension + to the application which continues processing other things, until + the font data is ready, at which time it restarts the suspended + request. + + + + Because the code for reading and manipulating bitmap font data is + used by the font applications mkfontdir and + bdftopcf, the font library includes + bitmap-font specific interfaces which those applications use, + instead of the more general interfaces used by the X and font + servers, which are unaware of the source of the font data. + These routines will be refered to as the bitmap font access + methods. + + + + + + + General Font Library Interface details. + + + + To avoid collision between the #define name space for errors, the Font + library defines a new set of return values: + + + +#define AllocError 80 +#define StillWorking 81 +#define FontNameAlias 82 +#define BadFontName 83 +#define Suspended 84 +#define Successful 85 +#define BadFontPath 86 +#define BadCharRange 87 +#define BadFontFormat 88 +#define FPEResetFailed 89 + + + + Whenever a routine returns Suspended, + the font library will notify the caller (via the ClientSignal + interface described below) who should then reinvoke the same routine + again with the same arguments. + + + + + + + Font Path Elements + + + + At the center of the general font access methods used by X and + xfs is the Font Path Element data structure. + Like most structures in the X server, this contains a collection + of data and some function pointers for manipulating this data: + + + +/* External view of font paths */ +typedef struct _FontPathElement { + int name_length; + char *name; + int type; + int refcount; + pointer private; +} FontPathElementRec, *FontPathElementPtr; + +typedef struct _FPEFunctions { + int (*name_check) ( /* name */ ); + int (*init_fpe) ( /* fpe */ ); + int (*reset_fpe) ( /* fpe */ ); + int (*free_fpe) ( /* fpe */ ); + int (*open_font) ( /* client, fpe, flags, + name, namelen, format, + fid, ppfont, alias */ ); + int (*close_font) ( /* pfont */ ); + int (*list_fonts) ( /* client, fpe, pattern, + patlen, maxnames, paths */ ); + int (*start_list_fonts_with_info) ( + /* client, fpe, name, namelen, + maxnames, data */ ); + int (*list_next_font_with_info) ( + /* client, fpe, name, namelen, + info, num, data */ ); + int (*wakeup_fpe) ( /* fpe, mask */ ); + int (*client_died) ( /* client, fpe */ ); +} FPEFunctionsRec, FPEFunctions; + + + + The function pointers are split out from the data structure to + save memory; additionally, this avoids any complications when + initializing the data structure as there would not be any way + to discover the appropriate function to call (a chicken and + egg problem). + + + + When a font path type is initialized, it passes the function + pointers to the server which are then stored in an + FPEFunctionsRec. Each function is + described below in turn. + + + + + (*name_check) + + + + Each new font path member is passed to this function; if + the return value is Successful, then + the FPE recognises the format of the string. This does not + guarantee that the FPE will be able to successfully use this + member. For example, the disk-based font directory file + fonts.dir may be corrupted, this will + not be detected until the font path is initialized. This + routine never returns Suspended. + + + + + + (*init_fpe) + + + + Initialize a new font path element. This function prepares + a new font path element for other requests: the disk font + routine reads the fonts.dir and + fonts.alias files into the internal + format, while the font server routine connects to the + requested font server and prepares for using it. This + routine returns Successful if + everything went OK, otherwise the return value indicates the + source of the problem. This routine never returns + Suspended. + + + + + + (*reset_fpe) + + + + When the X font path is reset, and some of the new members + are also in the old font path, this function is called to + reinitialize those FPEs. This routine returns + Successful if everything went OK. It + returns FPEResetFailed if (for some + reason) the reset failed, and the caller should remove the + old FPE and simply create a new one in its place. This is + used by the disk-based fonts routine as resetting the + internal directory structures would be more complicated than + simply having destroying the old and creating a new. + + + + + + (*free_fpe) + + + + When the server is finished with an FPE, this function is + called to dispose of any internal state. It should return + Successful, unless something terrible + happens. + + + + + + (*open_font) + + + + This routine requests that a font be opened. The client argument is used by the + font library only in connection with suspending/restarting + the request. The flags + argument specifies some behaviour for the library and can be + any of: + + + +/* OpenFont flags */ +#define FontLoadInfo 0x0001 +#define FontLoadProps 0x0002 +#define FontLoadMetrics 0x0004 +#define FontLoadBitmaps 0x0008 +#define FontLoadAll 0x000f +#define FontOpenSync 0x0010 + + + + The various fields specify which portions of the font should + be loaded at this time. When FontOpenSync + is specified, this routine will not return until all of the + requested portions are loaded. Otherwise, this routine may + return Suspended. When the presented + font name is actually an alias for some other font name, + FontNameAlias is returned, and the + actual font name is stored in the location pointed to by the + alias argument as a + null-terminated string. + + + + + + (*close_font) + + + + When the server is finished with a font, this routine + disposes of any internal state and frees the font data + structure. + + + + + + (*list_fonts) + + + + The paths argument is + a data structure which will be filled with all of the font names + from this directory which match the specified + pattern. At + most maxnames will be added. + This routine may return Suspended. + + + + + + (*start_list_fonts_with_info) + + + + This routine sets any internal state for a verbose listing of + all fonts matching the specified pattern. This routine may + return Suspended. + + + + + + (*list_next_font_with_info) + + + + To avoid storing huge amounts of data, the interface for + ListFontsWithInfo allows the server to get one reply at a time + and forward that to the client. When the font name returned + is actually an alias for some other font, + FontNameAlias will be returned. The + actual font name is return instead, and the font alias which + matched the pattern is returned in the location pointed to by + data as a null-terminated string. The caller can then get the + information by recursively listing that font name with a + maxnames of 1. When Successful is + returned, the matching font name is returned, and a + FontInfoPtr is stored in the location pointed to by + data. + Data must be initialized + with a pointer to a FontInfoRec allocated by the caller. When the + pointer pointed to by data + is not left pointing at that storage, the caller mustn't free the + associated property data. This routine may return + Suspended. + + + + + + (*wakeup_fpe) + + + + Whenever an FPE function has returned + Suspended, this routine is called + whenever the application wakes up from waiting for input + (from select + 2). This + mask argument should be + the value returned from select(2). + + + + + + (*client_died) + + + + When an FPE function has returned Suspended + and the associated client is being destroyed, this function + allows the font library to dispose of any state associated + with that client. + + + + + + + Fonts + + + + The data structure which actually contains the font information has + changed significantly since previous releases; it now attempts to + hide the actual storage format for the data from the application, + providing accessor functions to get at the data. This allows a + range of internal details for different font sources. The structure + is split into two pieces, so that ListFontsWithInfo can share + information from the font when it has been loaded. The + FontInfo structure, then, contains only + information germane to LFWI. + + + +typedef struct _FontInfo { + unsigned short firstCol; /* range of glyphs for this font */ + unsigned short lastCol; + unsigned short firstRow; + unsigned short lastRow; + unsigned short defaultCh; /* default character index */ + unsigned int noOverlap:1; /* no combination of glyphs overlap */ + unsigned int terminalFont:1; /* Character cell font */ + unsigned int constantMetrics:1; /* all metrics are the same */ + unsigned int constantWidth:1; /* all character widths are the same*/ + unsigned int inkInside:1; /* all ink inside character cell */ + unsigned int inkMetrics:1; /* font has ink metrics */ + unsigned int allExist:1; /* no missing chars in range */ + unsigned int drawDirection:2; /* left-to-right/right-to-left*/ + unsigned int cachable:1; /* font needn't be opened each time*/ + unsigned int anamorphic:1; /* font is strangely scaled */ + short maxOverlap; /* maximum overlap amount */ + short pad; /* unused */ + xCharInfo maxbounds; /* glyph metrics maximums */ + xCharInfo minbounds; /* glyph metrics minimums */ + xCharInfo ink_maxbounds; /* ink metrics maximums */ + xCharInfo ink_minbounds; /* ink metrics minimums */ + short fontAscent; /* font ascent amount */ + short fontDescent; /* font descent amount */ + int nprops; /* number of font properties */ + FontPropPtr props; /* font properties */ + char *isStringProp; /* boolean array */ +} FontInfoRec, *FontInfoPtr; + + + + The font structure, then, contains a font info record, the format of + the bits in each bitmap and the functions which access the font + records (which are stored in an opaque format hung off of + fontPrivate). + + + +typedef struct _Font { + int refcnt; + FontInfoRec info; + char bit; /* bit order: LSBFirst/MSBFirst */ + char byte; /* byte order: LSBFirst/MSBFirst */ + char glyph; /* glyph pad: 1, 2, 4 or 8 */ + char scan; /* glyph scan unit: 1, 2 or 4 */ + fsBitmapFormat format; /* FS-style format (packed) */ + int (*get_glyphs) ( /* font, count, chars, encoding, count, glyphs */ ); + int (*get_metrics) ( /* font, count, chars, encoding, count, glyphs */ ); + int (*get_bitmaps) ( /* client, font, flags, format, + flags, nranges, ranges, data_sizep, + num_glyphsp, offsetsp, glyph_datap, + free_datap */ ); + int (*get_extents) ( /* client, font, flags, nranges, + ranges, nextentsp, extentsp */); + void (*unload_font) ( /* font */ ); + FontPathElementPtr fpe; /* FPE associated with this font */ + pointer svrPrivate; /* X/FS private data */ + pointer fontPrivate; /* private to font */ + pointer fpePrivate; /* private to FPE */ + int maxPrivate; /* devPrivates (see below) */ + pointer *devPrivates; /* ... */ +} FontRec, *FontPtr; + + + + Yes, there are several different private pointers in the + Font structure; they were added + haphazardly until the devPrivate pointers were added. Future + releases may remove some (or all) of the specific pointers, + leaving only the devPrivatesmechanism. + + + + There are two similar interfaces implemented - + get_glyphs/get_metrics + and + get_bitmaps/get_extents. + Too little time caused the font-server specific interfaces to + be placed in the font library (and portions duplicated in each + renderer) instead of having them integrated into the font server + itself. This may change. The X server uses only + get_glyphs/get_metrics, + and those will not change dramatically. Each of the routines + is described below. + + + + + (*get_glyphs) + + + + This routine returns CharInfoPtrs + for each of the requested characters in the font. If the + character does not exist in the font, the default character + will be returned, unless no default character exists in + which case that character is skipped. Thus, the number of + glyphs returned will not always be the same as the number of + characters passed in. + + + + + + (*get_metrics) + + + + This is similar to (*get_glyphs) + except that pointers to xCharInfo + structures are returned, and, if the font has ink metrics, + those are returned instead of the bitmap metrics. + + + + + + (*get_bitmaps) + + + + This packs the glyph image data in the requested + format and returns it. The + ranges/nranges + argument specify the set of glyphs from the font to pack together. + + + + + + (*get_extents) + + + + This returns the metrics for the specified font from the + specified ranges. + + + + + + + (*unload_font) + + + + This is called from the FPE routine + (*close_font), and so should not ever be + called from the application. + + + + + + maxPrivate + + + + When initializing a new font structure, + maxPrivate should be set to -1 so + that the FontSetPrivate() macro works + properly with an index of 0. Initializing + maxPrivate to 0 can cause + problems if the server tries to set something at index 0. + + + +
diff --git a/doc/fontlib.xsl b/doc/fontlib.xsl new file mode 100644 index 0000000..5de4a28 --- /dev/null +++ b/doc/fontlib.xsl @@ -0,0 +1,32 @@ + + + + + + yes + + + + diff --git a/include/X11/fonts/bdfint.h b/include/X11/fonts/bdfint.h new file mode 100755 index 0000000..913f660 --- /dev/null +++ b/include/X11/fonts/bdfint.h @@ -0,0 +1,87 @@ +/* + +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifndef BDFINT_H +#define BDFINT_H + +#define bdfIsPrefix(buf,str) (!strncmp((char *)buf,str,strlen(str))) +#define bdfStrEqual(s1,s2) (!strcmp(s1,s2)) + +#define BDF_GENPROPS 6 +#define NullProperty ((FontPropPtr)0) + +/* + * This structure holds some properties we need to generate if they aren't + * specified in the BDF file and some other values read from the file + * that we'll need to calculate them. We need to keep track of whether + * or not we've read them. + */ +typedef struct BDFSTAT { + int linenum; + char *fileName; + char fontName[MAXFONTNAMELEN]; + float pointSize; + int resolution_x; + int resolution_y; + int digitCount; + int digitWidths; + int exHeight; + + FontPropPtr fontProp; + FontPropPtr pointSizeProp; + FontPropPtr resolutionXProp; + FontPropPtr resolutionYProp; + FontPropPtr resolutionProp; + FontPropPtr xHeightProp; + FontPropPtr weightProp; + FontPropPtr quadWidthProp; + BOOL haveFontAscent; + BOOL haveFontDescent; + BOOL haveDefaultCh; +} bdfFileState; + +extern void bdfError ( char * message, ... ); +extern void bdfWarning ( char *message, ... ); +extern unsigned char * bdfGetLine ( FontFilePtr file, unsigned char *buf, + int len ); +extern Atom bdfForceMakeAtom ( char *str, int *size ); +extern Atom bdfGetPropertyValue ( char *s ); +extern int bdfIsInteger ( char *str ); +extern unsigned char bdfHexByte ( unsigned char *s ); +extern Bool bdfSpecialProperty ( FontPtr pFont, FontPropPtr prop, + char isString, bdfFileState *bdfState ); +extern int bdfReadFont( FontPtr pFont, FontFilePtr file, + int bit, int byte, int glyph, int scan ); +extern int bdfReadFontInfo( FontInfoPtr pFontInfo, FontFilePtr file ); + +extern void FontCharInkMetrics ( FontPtr pFont, CharInfoPtr pCI, + xCharInfo *pInk ); +extern void FontCharReshape ( FontPtr pFont, CharInfoPtr pSrc, + CharInfoPtr pDst ); + +#endif /* BDFINT_H */ diff --git a/include/X11/fonts/bitmap.h b/include/X11/fonts/bitmap.h new file mode 100755 index 0000000..c023427 --- /dev/null +++ b/include/X11/fonts/bitmap.h @@ -0,0 +1,101 @@ +/* + +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifndef _BITMAP_H_ +#define _BITMAP_H_ + +#include +#include /* just for NULL */ + +/* + * Internal format used to store bitmap fonts + */ + +/* number of encoding entries in one segment */ +#define BITMAP_FONT_SEGMENT_SIZE 128 + +typedef struct _BitmapExtra { + Atom *glyphNames; + int *sWidths; + CARD32 bitmapsSizes[GLYPHPADOPTIONS]; + FontInfoRec info; +} BitmapExtraRec, *BitmapExtraPtr; + +typedef struct _BitmapFont { + unsigned version_num; + int num_chars; + int num_tables; + CharInfoPtr metrics; /* font metrics, including glyph pointers */ + xCharInfo *ink_metrics; /* ink metrics */ + char *bitmaps; /* base of bitmaps, useful only to free */ + CharInfoPtr **encoding; /* array of arrays of char info pointers */ + CharInfoPtr pDefault; /* default character */ + BitmapExtraPtr bitmapExtra; /* stuff not used by X server */ +} BitmapFontRec, *BitmapFontPtr; + +#define ACCESSENCODING(enc,i) \ +(enc[(i)/BITMAP_FONT_SEGMENT_SIZE]?\ +(enc[(i)/BITMAP_FONT_SEGMENT_SIZE][(i)%BITMAP_FONT_SEGMENT_SIZE]):\ +0) +#define ACCESSENCODINGL(enc,i) \ +(enc[(i)/BITMAP_FONT_SEGMENT_SIZE][(i)%BITMAP_FONT_SEGMENT_SIZE]) + +#define SEGMENT_MAJOR(n) ((n)/BITMAP_FONT_SEGMENT_SIZE) +#define SEGMENT_MINOR(n) ((n)%BITMAP_FONT_SEGMENT_SIZE) +#define NUM_SEGMENTS(n) \ + (((n)+BITMAP_FONT_SEGMENT_SIZE-1)/BITMAP_FONT_SEGMENT_SIZE) + +extern int bitmapGetGlyphs ( FontPtr pFont, unsigned long count, + unsigned char *chars, FontEncoding charEncoding, + unsigned long *glyphCount, CharInfoPtr *glyphs ); +extern int bitmapGetMetrics ( FontPtr pFont, unsigned long count, + unsigned char *chars, FontEncoding charEncoding, + unsigned long *glyphCount, xCharInfo **glyphs ); + +extern void bitmapComputeFontBounds ( FontPtr pFont ); +extern void bitmapComputeFontInkBounds ( FontPtr pFont ); +extern Bool bitmapAddInkMetrics ( FontPtr pFont ); +extern int bitmapComputeWeight ( FontPtr pFont ); + +extern void BitmapRegisterFontFileFunctions ( void ); + +extern int BitmapOpenScalable ( FontPathElementPtr fpe, FontPtr *pFont, + int flags, FontEntryPtr entry, char *fileName, + FontScalablePtr vals, fsBitmapFormat format, + fsBitmapFormatMask fmask, + FontPtr non_cachable_font ); +extern int BitmapGetInfoScalable ( FontPathElementPtr fpe, + FontInfoPtr pFontInfo, FontEntryPtr entry, + FontNamePtr fontName, char *fileName, + FontScalablePtr vals ); + +#endif /* _BITMAP_H_ */ diff --git a/include/X11/fonts/bufio.h b/include/X11/fonts/bufio.h new file mode 100755 index 0000000..e7a9f4a --- /dev/null +++ b/include/X11/fonts/bufio.h @@ -0,0 +1,83 @@ +/* + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifndef ___BUFIO_H___ +#define ___BUFIO_H___ 1 + +#include + +#define BUFFILESIZE 8192 +#define BUFFILEEOF -1 + +typedef unsigned char BufChar; +typedef struct _buffile *BufFilePtr; + +typedef struct _buffile { + BufChar *bufp; + int left; + int eof; + BufChar buffer[BUFFILESIZE]; + int (*input)( BufFilePtr /* f */); + int (*output)( int /* c */, BufFilePtr /* f */); + int (*skip)( BufFilePtr /* f */, int /* count */); + int (*close)( BufFilePtr /* f */, int /* doClose */); + char *private; +} BufFileRec; + +extern BufFilePtr BufFileCreate ( + char*, + int (*)(BufFilePtr), + int (*)(int, BufFilePtr), + int (*)(BufFilePtr, int), + int (*)(BufFilePtr, int)); +extern BufFilePtr BufFileOpenRead ( int ); +extern BufFilePtr BufFileOpenWrite ( int ); +extern BufFilePtr BufFilePushCompressed ( BufFilePtr ); +#ifdef X_GZIP_FONT_COMPRESSION +extern BufFilePtr BufFilePushZIP ( BufFilePtr ); +#endif +#ifdef X_BZIP2_FONT_COMPRESSION +extern BufFilePtr BufFilePushBZIP2 ( BufFilePtr ); +#endif +extern int BufFileClose ( BufFilePtr, int ); +extern int BufFileRead ( BufFilePtr, char*, int ); +extern int BufFileWrite ( BufFilePtr, char*, int ); + +#define BufFileGet(f) ((f)->left-- ? *(f)->bufp++ : ((f)->eof = (*(f)->input) (f))) +#define BufFilePut(c,f) (--(f)->left ? *(f)->bufp++ = ((unsigned char)(c)) : (*(f)->output) ((unsigned char)(c),f)) +#define BufFileSkip(f,c) ((f)->eof = (*(f)->skip) (f, c)) + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#endif /* ___BUFIO_H___ */ + diff --git a/include/X11/fonts/fntfil.h b/include/X11/fonts/fntfil.h new file mode 100755 index 0000000..25d1f30 --- /dev/null +++ b/include/X11/fonts/fntfil.h @@ -0,0 +1,179 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifndef _FONTFILE_H_ +#define _FONTFILE_H_ + +#include + +typedef struct _FontEntry *FontEntryPtr; +typedef struct _FontTable *FontTablePtr; +typedef struct _FontName *FontNamePtr; +typedef struct _FontScaled *FontScaledPtr; +typedef struct _FontScalableExtra *FontScalableExtraPtr; +typedef struct _FontScalableEntry *FontScalableEntryPtr; +typedef struct _FontScaleAliasEntry *FontScaleAliasEntryPtr; +typedef struct _FontBitmapEntry *FontBitmapEntryPtr; +typedef struct _FontAliasEntry *FontAliasEntryPtr; +typedef struct _FontBCEntry *FontBCEntryPtr; +typedef struct _FontDirectory *FontDirectoryPtr; +typedef struct _FontRenderer *FontRendererPtr; + +#define NullFontEntry ((FontEntryPtr) 0) +#define NullFontTable ((FontTablePtr) 0) +#define NullFontName ((FontNamePtr) 0) +#define NullFontScaled ((FontScaled) 0) +#define NullFontScalableExtra ((FontScalableExtra) 0) +#define NullFontscalableEntry ((FontScalableEntry) 0) +#define NullFontScaleAliasEntry ((FontScaleAliasEntry) 0) +#define NullFontBitmapEntry ((FontBitmapEntry) 0) +#define NullFontAliasEntry ((FontAliasEntry) 0) +#define NullFontBCEntry ((FontBCEntry) 0) +#define NullFontDirectory ((FontDirectoryPtr) 0) +#define NullFontRenderer ((FontRendererPtr) 0) + +#define FONT_ENTRY_SCALABLE 0 +#define FONT_ENTRY_SCALE_ALIAS 1 +#define FONT_ENTRY_BITMAP 2 +#define FONT_ENTRY_ALIAS 3 +#define FONT_ENTRY_BC 4 + +#define MAXFONTNAMELEN 1024 +#define MAXFONTFILENAMELEN 1024 + +#define FontDirFile "fonts.dir" +#define FontAliasFile "fonts.alias" +#define FontScalableFile "fonts.scale" + +extern int FontFileNameCheck ( char *name ); +extern int FontFileInitFPE ( FontPathElementPtr fpe ); +extern int FontFileResetFPE ( FontPathElementPtr fpe ); +extern int FontFileFreeFPE ( FontPathElementPtr fpe ); +extern int FontFileOpenFont ( pointer client, FontPathElementPtr fpe, + Mask flags, char *name, int namelen, + fsBitmapFormat format, fsBitmapFormatMask fmask, + XID id, FontPtr *pFont, char **aliasName, + FontPtr non_cachable_font ); +extern void FontFileCloseFont ( FontPathElementPtr fpe, FontPtr pFont ); +extern int FontFileOpenBitmap ( FontPathElementPtr fpe, FontPtr *pFont, + int flags, FontEntryPtr entry, + fsBitmapFormat format, + fsBitmapFormatMask fmask ); +extern int FontFileListFonts ( pointer client, FontPathElementPtr fpe, + char *pat, int len, int max, + FontNamesPtr names ); +extern int FontFileStartListFonts ( pointer client, FontPathElementPtr fpe, + char *pat, int len, int max, + pointer *privatep, int mark_aliases ); +extern int FontFileStartListFontsWithInfo ( pointer client, + FontPathElementPtr fpe, + char *pat, int len, int max, + pointer *privatep ); +extern int FontFileListNextFontWithInfo ( pointer client, + FontPathElementPtr fpe, + char **namep, int *namelenp, + FontInfoPtr *pFontInfo, + int *numFonts, pointer private ); +extern int FontFileStartListFontsAndAliases ( pointer client, + FontPathElementPtr fpe, + char *pat, int len, int max, + pointer *privatep ); +extern int FontFileListNextFontOrAlias ( pointer client, + FontPathElementPtr fpe, + char **namep, int *namelenp, + char **resolvedp, int *resolvedlenp, + pointer private ); +extern void FontFileRegisterLocalFpeFunctions ( void ); +extern void CatalogueRegisterLocalFpeFunctions ( void ); + + +extern FontEntryPtr FontFileAddEntry ( FontTablePtr table, + FontEntryPtr prototype ); +extern Bool FontFileAddFontAlias ( FontDirectoryPtr dir, char *aliasName, + char *fontName ); +extern Bool FontFileAddFontFile ( FontDirectoryPtr dir, char *fontName, + char *fileName ); +extern int FontFileCountDashes ( char *name, int namelen ); +extern FontEntryPtr FontFileFindNameInDir ( FontTablePtr table, + FontNamePtr pat ); +extern FontEntryPtr FontFileFindNameInScalableDir ( FontTablePtr table, + FontNamePtr pat, + FontScalablePtr vals ); +extern int FontFileFindNamesInDir ( FontTablePtr table, FontNamePtr pat, + int max, FontNamesPtr names ); +extern int FontFileFindNamesInScalableDir ( FontTablePtr table, + FontNamePtr pat, int max, + FontNamesPtr names, + FontScalablePtr vals, + int alias_behavior, int *newmax ); + +extern void FontFileFreeDir ( FontDirectoryPtr dir ); +extern void FontFileFreeEntry ( FontEntryPtr entry ); +extern void FontFileFreeTable ( FontTablePtr table ); +extern Bool FontFileInitTable ( FontTablePtr table, int size ); +extern FontDirectoryPtr FontFileMakeDir ( char *dirName, int size ); +extern Bool FontFileMatchName ( char *name, int length, FontNamePtr pat ); +extern char * FontFileSaveString ( char *s ); +extern void FontFileSortDir ( FontDirectoryPtr dir ); +extern void FontFileSortTable ( FontTablePtr table ); + +extern void FontDefaultFormat ( int *bit, int *byte, int *glyph, int *scan ); + +extern Bool FontFileRegisterRenderer ( FontRendererPtr renderer ); +extern Bool FontFilePriorityRegisterRenderer ( FontRendererPtr renderer, + int priority ); +extern FontRendererPtr FontFileMatchRenderer ( char *fileName ); + +extern Bool FontFileAddScaledInstance ( FontEntryPtr entry, + FontScalablePtr vals, FontPtr pFont, + char *bitmapName ); +extern void FontFileSwitchStringsToBitmapPointers ( FontDirectoryPtr dir ); +extern void FontFileRemoveScaledInstance ( FontEntryPtr entry, FontPtr pFont ); +extern Bool FontFileCompleteXLFD ( FontScalablePtr vals, FontScalablePtr def ); +extern FontScaledPtr FontFileFindScaledInstance ( FontEntryPtr entry, + FontScalablePtr vals, + int noSpecificSize ); + +extern Bool FontFileRegisterBitmapSource ( FontPathElementPtr fpe ); +extern void FontFileUnregisterBitmapSource ( FontPathElementPtr fpe ); +extern void FontFileEmptyBitmapSource ( void ); +extern int FontFileMatchBitmapSource ( FontPathElementPtr fpe, + FontPtr *pFont, int flags, + FontEntryPtr entry, + FontNamePtr zeroPat, + FontScalablePtr vals, + fsBitmapFormat format, + fsBitmapFormatMask fmask, + Bool noSpecificSize ); + +extern int FontFileReadDirectory ( char *directory, FontDirectoryPtr *pdir ); +extern Bool FontFileDirectoryChanged ( FontDirectoryPtr dir ); + +#endif /* _FONTFILE_H_ */ diff --git a/include/X11/fonts/fntfilio.h b/include/X11/fonts/fntfilio.h new file mode 100755 index 0000000..3a8f4ca --- /dev/null +++ b/include/X11/fonts/fntfilio.h @@ -0,0 +1,53 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifndef _FNTFILIO_H_ +#define _FNTFILIO_H_ + +#include + +typedef BufFilePtr FontFilePtr; + +#define FontFileGetc(f) BufFileGet(f) +#define FontFilePutc(c,f) BufFilePut(c,f) +#define FontFileRead(f,b,n) BufFileRead(f,b,n) +#define FontFileWrite(f,b,n) BufFileWrite(f,b,n) +#define FontFileSkip(f,n) (BufFileSkip (f, n) != BUFFILEEOF) +#define FontFileSeek(f,n) (BufFileSeek (f,n,0) != BUFFILEEOF) + +#define FontFileEOF BUFFILEEOF + +extern FontFilePtr FontFileOpen ( const char *name ); +extern int FontFileClose ( FontFilePtr f ); +extern FontFilePtr FontFileOpenWrite ( const char *name ); +extern FontFilePtr FontFileOpenWriteFd ( int fd ); +extern FontFilePtr FontFileOpenFd ( int fd ); + +#endif /* _FNTFILIO_H_ */ diff --git a/include/X11/fonts/fntfilst.h b/include/X11/fonts/fntfilst.h new file mode 100755 index 0000000..29e0a56 --- /dev/null +++ b/include/X11/fonts/fntfilst.h @@ -0,0 +1,193 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifndef _FONTFILEST_H_ +#define _FONTFILEST_H_ + +#include +#ifndef XP_PSTEXT +#include +#endif +#include +#include +#include + +typedef struct _FontName { + char *name; + short length; + short ndashes; +} FontNameRec; + +typedef struct _FontScaled { + FontScalableRec vals; + FontEntryPtr bitmap; + FontPtr pFont; +} FontScaledRec; + +typedef struct _FontScalableExtra { + FontScalableRec defaults; + int numScaled; + int sizeScaled; + FontScaledPtr scaled; + pointer private; +} FontScalableExtraRec; + +typedef struct _FontScalableEntry { + FontRendererPtr renderer; + char *fileName; + FontScalableExtraPtr extra; +} FontScalableEntryRec; + +/* + * This "can't" work yet - the returned alias string must be permanent, + * but this layer would need to generate the appropriate name from the + * resolved scalable + the XLFD values passed in. XXX + */ + +typedef struct _FontScaleAliasEntry { + char *resolved; +} FontScaleAliasEntryRec; + +typedef struct _FontBitmapEntry { + FontRendererPtr renderer; + char *fileName; + FontPtr pFont; +} FontBitmapEntryRec; + +typedef struct _FontAliasEntry { + char *resolved; +} FontAliasEntryRec; + +typedef struct _FontBCEntry { + FontScalableRec vals; + FontEntryPtr entry; +} FontBCEntryRec; + +typedef struct _FontEntry { + FontNameRec name; + int type; + union _FontEntryParts { + FontScalableEntryRec scalable; + FontBitmapEntryRec bitmap; + FontAliasEntryRec alias; + FontBCEntryRec bc; + } u; +} FontEntryRec; + +typedef struct _FontTable { + int used; + int size; + FontEntryPtr entries; + Bool sorted; +} FontTableRec; + +typedef struct _FontDirectory { + char *directory; + unsigned long dir_mtime; + unsigned long alias_mtime; + FontTableRec scalable; + FontTableRec nonScalable; + char *attributes; +} FontDirectoryRec; + +/* Capability bits: for definition of capabilities bitmap in the + FontRendererRec to indicate support of XLFD enhancements */ + +#define CAP_MATRIX 0x1 +#define CAP_CHARSUBSETTING 0x2 + +typedef struct _FontRenderer { + char *fileSuffix; + int fileSuffixLen; + int (*OpenBitmap)(FontPathElementPtr /* fpe */, + FontPtr * /* pFont */, + int /* flags */, + FontEntryPtr /* entry */, + char * /* fileName */, + fsBitmapFormat /* format */, + fsBitmapFormatMask /* mask */, + FontPtr /* non_cachable_font */); + int (*OpenScalable)(FontPathElementPtr /* fpe */, + FontPtr * /* pFont */, + int /* flags */, + FontEntryPtr /* entry */, + char * /* fileName */, + FontScalablePtr /* vals */, + fsBitmapFormat /* format */, + fsBitmapFormatMask /* fmask */, + FontPtr /* non_cachable_font */); + int (*GetInfoBitmap)(FontPathElementPtr /* fpe */, + FontInfoPtr /* pFontInfo */, + FontEntryPtr /* entry */, + char * /*fileName */); + int (*GetInfoScalable)(FontPathElementPtr /* fpe */, + FontInfoPtr /* pFontInfo */, + FontEntryPtr /* entry */, + FontNamePtr /* fontName */, + char * /* fileName */, + FontScalablePtr /* vals */); + int number; + int capabilities; /* Bitmap components defined above */ +} FontRendererRec; + +typedef struct _FontRenders { + int number; + struct _FontRenderersElement { + /* In order to preserve backward compatibility, the + priority field is made invisible to renderers */ + FontRendererPtr renderer; + int priority; + } *renderers; +} FontRenderersRec, *FontRenderersPtr; + +typedef struct _BitmapInstance { + FontScalableRec vals; + FontBitmapEntryPtr bitmap; +} BitmapInstanceRec, *BitmapInstancePtr; + +typedef struct _BitmapScalablePrivate { + int numInstances; + BitmapInstancePtr instances; +} BitmapScalablePrivateRec, *BitmapScalablePrivatePtr; + +typedef struct _BitmapSources { + FontPathElementPtr *fpe; + int size; + int count; +} BitmapSourcesRec, *BitmapSourcesPtr; + +extern BitmapSourcesRec FontFileBitmapSources; + +/* Defines for FontFileFindNamesInScalableDir() behavior */ +#define NORMAL_ALIAS_BEHAVIOR 0 +#define LIST_ALIASES_AND_TARGET_NAMES (1<<0) +#define IGNORE_SCALABLE_ALIASES (1<<1) + +#endif /* _FONTFILEST_H_ */ diff --git a/include/X11/fonts/fontconf.h.in b/include/X11/fonts/fontconf.h.in new file mode 100755 index 0000000..67783d3 --- /dev/null +++ b/include/X11/fonts/fontconf.h.in @@ -0,0 +1,49 @@ +/* + * Copyright © 2005 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* Define as 1 if you have FreeType support in Xfont */ +#undef XFONT_FREETYPE + +/* Define as 1 if you have builtin font support in Xfont */ +#undef XFONT_BUILTINS + +/* Define as 1 if you have pcf font support in Xfont */ +#undef XFONT_PCFFORMAT + +/* Define as 1 if you have bdf font support in Xfont */ +#undef XFONT_BDFFORMAT + +/* Define as 1 if you have snf font support in Xfont */ +#undef XFONT_SNFFORMAT + +/* Define as 1 if you have bitmap font support in Xfont */ +#undef XFONT_BITMAP + +/* Define as 1 if you have fontfile support in Xfont */ +#undef XFONT_FONTFILE + +/* Define as 1 if you have font cache support in Xfont */ +#undef XFONT_FONTCACHE + +/* Define as 1 if you have X Font Services Protocol support in Xfont */ +#undef XFONT_FC + diff --git a/include/X11/fonts/fontencc.h b/include/X11/fonts/fontencc.h new file mode 100755 index 0000000..987cbfb --- /dev/null +++ b/include/X11/fonts/fontencc.h @@ -0,0 +1,35 @@ +/* +Copyright (c) 1998-2001 by Juliusz Chroboczek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/* Binary compatibility entry points. */ + +/* This file includes code to make modules compiled for earlier + versions of the fontenc interfaces link with this one. It does + *not* provide source compatibility, as many of the data structures + now have different names. */ + +extern char *font_encoding_from_xlfd(const char*, int); +extern unsigned font_encoding_recode(unsigned, FontEncPtr, FontMapPtr); +extern FontEncPtr font_encoding_find(const char*, const char*); +extern char *font_encoding_name(unsigned, FontEncPtr, FontMapPtr); +extern char **identifyEncodingFile(const char *fileName); + diff --git a/include/X11/fonts/fontmisc.h b/include/X11/fonts/fontmisc.h new file mode 100755 index 0000000..cd9d52a --- /dev/null +++ b/include/X11/fonts/fontmisc.h @@ -0,0 +1,100 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifndef _FONTMISC_H_ +#define _FONTMISC_H_ + +#include +#include +#include +#include +#include + + +#ifndef LSBFirst +#define LSBFirst 0 +#define MSBFirst 1 +#endif + +#ifndef None +#define None 0l +#endif + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +extern Atom MakeAtom ( char *string, unsigned len, int makeit ); +extern int ValidAtom ( Atom atom ); +extern char *NameForAtom (Atom atom); + +#define lowbit(x) ((x) & (~(x) + 1)) + +#undef assert +#define assert(x) ((void)0) + +extern void +BitOrderInvert( + register unsigned char *, + register int +); + +extern void +TwoByteSwap( + register unsigned char *, + register int +); + +extern void +FourByteSwap( + register unsigned char *, + register int +); + +extern int +RepadBitmap ( + char*, + char*, + unsigned, + unsigned, + int, + int +); + +extern void CopyISOLatin1Lowered( + char * /*dest*/, + char * /*source*/, + int /*length*/ +); + +extern void register_fpe_functions(void); + +#endif /* _FONTMISC_H_ */ diff --git a/include/X11/fonts/fontshow.h b/include/X11/fonts/fontshow.h new file mode 100755 index 0000000..126cab6 --- /dev/null +++ b/include/X11/fonts/fontshow.h @@ -0,0 +1,35 @@ +/* + +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#define FONT_SHOW_INFO (1<<0) +#define FONT_SHOW_PROPS (1<<1) +#define FONT_SHOW_METRICS (1<<2) +#define FONT_SHOW_GLYPHS (1<<3) +#define FONT_SHOW_ALL (FONT_SHOW_INFO|FONT_SHOW_PROPS|FONT_SHOW_GLYPHS) diff --git a/include/X11/fonts/fontutil.h b/include/X11/fonts/fontutil.h new file mode 100755 index 0000000..71d507b --- /dev/null +++ b/include/X11/fonts/fontutil.h @@ -0,0 +1,24 @@ +#ifndef _FONTUTIL_H_ +#define _FONTUTIL_H_ + +#include + +extern int FontCouldBeTerminal(FontInfoPtr); +extern int CheckFSFormat(fsBitmapFormat, fsBitmapFormatMask, int *, int *, + int *, int *, int *); +extern void FontComputeInfoAccelerators(FontInfoPtr); + +extern void GetGlyphs ( FontPtr font, unsigned long count, + unsigned char *chars, FontEncoding fontEncoding, + unsigned long *glyphcount, CharInfoPtr *glyphs ); +extern void QueryGlyphExtents ( FontPtr pFont, CharInfoPtr *charinfo, + unsigned long count, ExtentInfoRec *info ); +extern Bool QueryTextExtents ( FontPtr pFont, unsigned long count, + unsigned char *chars, ExtentInfoRec *info ); +extern Bool ParseGlyphCachingMode ( char *str ); +extern void InitGlyphCaching ( void ); +extern void SetGlyphCachingMode ( int newmode ); +extern int add_range ( fsRange *newrange, int *nranges, fsRange **range, + Bool charset_subset ); + +#endif /* _FONTUTIL_H_ */ diff --git a/include/X11/fonts/fontxlfd.h b/include/X11/fonts/fontxlfd.h new file mode 100755 index 0000000..3555706 --- /dev/null +++ b/include/X11/fonts/fontxlfd.h @@ -0,0 +1,97 @@ +/* + +Copyright 1990, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifndef _FONTXLFD_H_ +#define _FONTXLFD_H_ + +#include + +/* Constants for values_supplied bitmap */ + +#define SIZE_SPECIFY_MASK 0xf + +#define PIXELSIZE_MASK 0x3 +#define PIXELSIZE_UNDEFINED 0 +#define PIXELSIZE_SCALAR 0x1 +#define PIXELSIZE_ARRAY 0x2 +#define PIXELSIZE_SCALAR_NORMALIZED 0x3 /* Adjusted for resolution */ + +#define POINTSIZE_MASK 0xc +#define POINTSIZE_UNDEFINED 0 +#define POINTSIZE_SCALAR 0x4 +#define POINTSIZE_ARRAY 0x8 + +#define PIXELSIZE_WILDCARD 0x10 +#define POINTSIZE_WILDCARD 0x20 + +#define ENHANCEMENT_SPECIFY_MASK 0x40 + +#define CHARSUBSET_SPECIFIED 0x40 + +#define EPS 1.0e-20 +#define XLFD_NDIGITS 3 /* Round numbers in pixel and + point arrays to this many + digits for repeatability */ + +typedef struct _FontScalable { + int values_supplied; /* Bitmap identifying what advanced + capabilities or enhancements + were specified in the font name */ + double pixel_matrix[4]; + double point_matrix[4]; + + /* Pixel and point fields are deprecated in favor of the + transformation matrices. They are provided and filled in for the + benefit of rasterizers that do not handle the matrices. */ + + int pixel, + point; + + int x, + y, + width; + char *xlfdName; + int nranges; + fsRange *ranges; +} FontScalableRec, *FontScalablePtr; + + +extern double xlfd_round_double ( double x ); +extern Bool FontParseXLFDName ( char *fname, FontScalablePtr vals, int subst ); +extern fsRange *FontParseRanges ( char *name, int *nranges ); + +#define FONT_XLFD_REPLACE_NONE 0 +#define FONT_XLFD_REPLACE_STAR 1 +#define FONT_XLFD_REPLACE_ZERO 2 +#define FONT_XLFD_REPLACE_VALUE 3 + +#endif /* _FONTXLFD_H_ */ diff --git a/include/X11/fonts/pcf.h b/include/X11/fonts/pcf.h new file mode 100755 index 0000000..a5fdbcd --- /dev/null +++ b/include/X11/fonts/pcf.h @@ -0,0 +1,97 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifndef _PCF_H_ +#define _PCF_H_ + +#include + +/* + * Information used to read/write PCF fonts + */ + +typedef struct _PCFTable { + CARD32 type; + CARD32 format; + CARD32 size; + CARD32 offset; +} PCFTableRec, *PCFTablePtr; + +#define PCF_FILE_VERSION (('p'<<24)|('c'<<16)|('f'<<8)|1) +#define PCF_FORMAT_MASK 0xffffff00 + +#define PCF_DEFAULT_FORMAT 0x00000000 +#define PCF_INKBOUNDS 0x00000200 +#define PCF_ACCEL_W_INKBOUNDS 0x00000100 +#define PCF_COMPRESSED_METRICS 0x00000100 + +#define PCF_FORMAT_MATCH(a,b) (((a)&PCF_FORMAT_MASK) == ((b)&PCF_FORMAT_MASK)) + +#define PCF_GLYPH_PAD_MASK (3<<0) +#define PCF_BYTE_MASK (1<<2) +#define PCF_BIT_MASK (1<<3) +#define PCF_SCAN_UNIT_MASK (3<<4) + +#define PCF_BYTE_ORDER(f) (((f) & PCF_BYTE_MASK)?MSBFirst:LSBFirst) +#define PCF_BIT_ORDER(f) (((f) & PCF_BIT_MASK)?MSBFirst:LSBFirst) +#define PCF_GLYPH_PAD_INDEX(f) ((f) & PCF_GLYPH_PAD_MASK) +#define PCF_GLYPH_PAD(f) (1<> 4) +#define PCF_SCAN_UNIT(f) (1< + +#define FREETYPE_VERSION (FREETYPE_MAJOR * 1000000 + FREETYPE_MINOR * 1000 + FREETYPE_PATCH) + +#undef DEBUG_TRUETYPE + +#ifdef DEBUG_TRUETYPE +#define MUMBLE ErrorF +#else +#define MUMBLE(...) +#endif + +#undef MAX +#define MAX(h,i) ((h) > (i) ? (h) : (i)) +#define ADJUSTMAX(m,v) if((v)>(m)) (m)=(v) +#undef MIN +#define MIN(l,o) ((l) < (o) ? (l) : (o)) +#define ADJUSTMIN(m,v) if ((v)<(m)) (m)=(v) + +/* When comparing floating point values, we want to ignore small errors. */ +#define NEGLIGIBLE ((double)0.001) +/* Are x and y significantly different? */ +#define DIFFER(x,y) (fabs((x)-(y))>=NEGLIGIBLE*fabs(x)) +/* Is x significantly different from 0 w.r.t. y? */ +#define DIFFER0(x,y) (fabs(x)>=NEGLIGIBLE*fabs(y)) + +#ifndef ABS +#define ABS(x) ((x) >= 0 ? (x) : -(x)) +#endif + +/* Two to the sixteenth power, as a double. */ +#define TWO_SIXTEENTH ((double)(1<<16)) +#define TWO_SIXTH ((double)(1<<6)) + +/* Data structures used across files */ + +typedef struct _FTMapping +{ + int named; + FT_CharMap cmap; + int base; + struct _FontMap *mapping; /* allow inclusion without fontenc.h */ +} FTMappingRec, *FTMappingPtr; + +/* Prototypes */ + +/* ftfuncs.c */ + +/* ftenc.c */ + +int FTPickMapping(char*, int, char*, FT_Face, FTMappingPtr); +unsigned FTRemap(FT_Face face, FTMappingPtr, unsigned code); + +/* fttools.c */ + +int FTtoXReturnCode(int); +int FTGetEnglishName(FT_Face, int, char *, int); + +extern void ErrorF(const char*, ...); + +#endif /* _FT_H_ */ diff --git a/src/FreeType/ftenc.c b/src/FreeType/ftenc.c new file mode 100755 index 0000000..99defbe --- /dev/null +++ b/src/FreeType/ftenc.c @@ -0,0 +1,239 @@ +/* +Copyright (c) 1998-2003 by Juliusz Chroboczek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +#include +#include +#include + +#include +#include +#include +#include FT_FREETYPE_H +#include FT_TRUETYPE_IDS_H +#include FT_TRUETYPE_TABLES_H +#include FT_TYPE1_TABLES_H +#include FT_BDF_H +#include FT_XFREE86_H +#include "ft.h" + +static int find_cmap(int, int, int, FT_Face, FT_CharMap *); + +static int +FTEncFontSpecific(char *encoding) +{ + char *p = encoding; + + if(strcasecmp(encoding, "microsoft-symbol") == 0) + return 1; + + while(*p != '-') { + if(*p == '\0') + return 0; + p++; + } + p++; + return (strcasecmp(p, "fontspecific") == 0); +} + +int +FTPickMapping(char *xlfd, int length, char *filename, FT_Face face, + FTMappingPtr tm) +{ + FontEncPtr encoding; + FontMapPtr mapping; + FT_CharMap cmap; + int ftrc; + int symbol = 0; + const char *enc, *reg; + char *encoding_name = 0; + char buf[20]; + + if(xlfd) + encoding_name = FontEncFromXLFD(xlfd, length); + if(!encoding_name) + encoding_name = "iso8859-1"; + + symbol = FTEncFontSpecific(encoding_name); + +#if XFONT_BDFFORMAT + ftrc = FT_Get_BDF_Charset_ID(face, &enc, ®); +#else + ftrc = -1; +#endif + if(ftrc == 0) { + /* Disable reencoding for non-Unicode fonts. This will + currently only work for BDFs. */ + if(strlen(enc) + strlen(reg) > 18) + goto native; + strcpy(buf, enc); + strcat(buf, "-"); + strcat(buf, reg); + ErrorF("%s %s\n", buf, encoding_name); + if(strcasecmp(buf, "iso10646-1") != 0) { + if(strcasecmp(buf, encoding_name) == 0) + goto native; + return BadFontFormat; + } + } else if(symbol) { + ftrc = FT_Select_Charmap(face, ft_encoding_adobe_custom); + if(ftrc == 0) + goto native; + } + + encoding = FontEncFind(encoding_name, filename); + if(symbol && encoding == NULL) + encoding = FontEncFind("microsoft-symbol", filename); + if(encoding == NULL) { + ErrorF("FreeType: couldn't find encoding '%s' for '%s'\n", + encoding_name, filename); + return BadFontName; + } + + if(FT_Has_PS_Glyph_Names(face)) { + for(mapping = encoding->mappings; mapping; mapping = mapping->next) { + if(mapping->type == FONT_ENCODING_POSTSCRIPT) { + tm->named = 1; + tm->base = 0; + tm->mapping = mapping; + return Successful; + } + } + } + + for(mapping = encoding->mappings; mapping; mapping = mapping->next) { + if(find_cmap(mapping->type, mapping->pid, mapping->eid, face, + &cmap)) { + tm->named = 0; + tm->cmap = cmap; + if(symbol) { + /* deal with an undocumented ``feature'' of the + Microsft-Symbol cmap */ + TT_OS2 *os2; + os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2); + if(os2) + tm->base = os2->usFirstCharIndex - 0x20; + else + tm->base = 0; + } else + tm->base = 0; + tm->mapping = mapping; + return Successful; + } + } + + return BadFontFormat; + + native: + tm->named = 0; + tm->cmap = face->charmap; + tm->base = 0; + tm->mapping = NULL; + return Successful; +} + +static int +find_cmap(int type, int pid, int eid, FT_Face face, FT_CharMap *cmap_return) +{ + int i, n; + FT_CharMap cmap = NULL; + + n = face->num_charmaps; + + switch(type) { + case FONT_ENCODING_TRUETYPE: /* specific cmap */ + for(i=0; icharmaps[i]; + if(cmap->platform_id == pid && cmap->encoding_id == eid) { + *cmap_return = cmap; + return 1; + } + } + break; + case FONT_ENCODING_UNICODE: /* any Unicode cmap */ + /* prefer Microsoft Unicode */ + for(i=0; icharmaps[i]; + if(cmap->platform_id == TT_PLATFORM_MICROSOFT && + cmap->encoding_id == TT_MS_ID_UNICODE_CS) { + *cmap_return = cmap; + return 1; + } + } + break; + /* Try Apple Unicode */ + for(i=0; icharmaps[i]; + if(cmap->platform_id == TT_PLATFORM_APPLE_UNICODE) { + *cmap_return = cmap; + return 1; + } + } + /* ISO Unicode? */ + for(i=0; icharmaps[i]; + if(cmap->platform_id == TT_PLATFORM_ISO) { + *cmap_return = cmap; + return 1; + } + } + break; + default: + return 0; + } + return 0; +} + +unsigned +FTRemap(FT_Face face, FTMappingPtr tm, unsigned code) +{ + unsigned index; + char *name; + unsigned glyph_index; + + if(tm->mapping) { + if(tm->named) { + name = FontEncName(code, tm->mapping); + if(!name) + return 0; + glyph_index = FT_Get_Name_Index(face, name); + return glyph_index; + } else { + index = FontEncRecode(code, tm->mapping) + tm->base; + FT_Set_Charmap(face, tm->cmap); + glyph_index = FT_Get_Char_Index(face, index); + return glyph_index; + } + } else { + if(code < 0x100) { + index = code; + FT_Set_Charmap(face, tm->cmap); + glyph_index = FT_Get_Char_Index(face, index); + return glyph_index; + } else + return 0; + } +} diff --git a/src/FreeType/ftfuncs.c b/src/FreeType/ftfuncs.c new file mode 100755 index 0000000..fd8e53e --- /dev/null +++ b/src/FreeType/ftfuncs.c @@ -0,0 +1,3924 @@ +/* +Copyright (c) 1997 by Mark Leisher +Copyright (c) 1998-2003 by Juliusz Chroboczek +Copyright (c) 1998 Go Watanabe, All rights reserved. +Copyright (c) 1998 Kazushi (Jam) Marukawa, All rights reserved. +Copyright (c) 1998 Takuya SHIOZAKI, All rights reserved. +Copyright (c) 1998 X-TrueType Server Project, All rights reserved. +Copyright (c) 2003-2004 After X-TT Project, All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +#include +#include +#include + +#include +#include +#include +#include +#include FT_FREETYPE_H +#include FT_SIZES_H +#include FT_TRUETYPE_IDS_H +#include FT_TRUETYPE_TABLES_H +#include FT_TYPE1_TABLES_H +#include FT_XFREE86_H +#include FT_BBOX_H +#include FT_TRUETYPE_TAGS_H +/* + * If you want to use FT_Outline_Get_CBox instead of + * FT_Outline_Get_BBox, define here. + */ +/* #define USE_GET_CBOX */ +#ifdef USE_GET_CBOX +#include FT_OUTLINE_H +#endif + +#include +#include "ft.h" +#include "ftfuncs.h" +#include "xttcap.h" + +/* Work around FreeType bug */ +#define WORK_AROUND_UPM 2048 + +#ifndef True +#define True (-1) +#endif /* True */ +#ifndef False +#define False (0) +#endif /* False */ + +#define FLOOR64(x) ((x) & -64) +#define CEIL64(x) (((x) + 64 - 1) & -64) + +/* + * If you want very lazy method(vl=y) AS DEFAULT when + * handling large charset, define here. + */ +/* #define DEFAULT_VERY_LAZY 1 */ /* Always */ +#define DEFAULT_VERY_LAZY 2 /* Multi-byte only */ +/* #define DEFAULT_VERY_LAZY 256 */ /* Unicode only */ + +/* Does the X accept noSuchChar? */ +#define X_ACCEPTS_NO_SUCH_CHAR +/* Does the XAA accept NULL noSuchChar.bits?(dangerous) */ +/* #define XAA_ACCEPTS_NULL_BITS */ + +#ifdef X_ACCEPTS_NO_SUCH_CHAR +static CharInfoRec noSuchChar = { /* metrics */{0,0,0,0,0,0}, + /* bits */ NULL }; +#endif + +/* The propery names for all the XLFD properties. */ + +static char *xlfd_props[] = { + "FOUNDRY", + "FAMILY_NAME", + "WEIGHT_NAME", + "SLANT", + "SETWIDTH_NAME", + "ADD_STYLE_NAME", + "PIXEL_SIZE", + "POINT_SIZE", + "RESOLUTION_X", + "RESOLUTION_Y", + "SPACING", + "AVERAGE_WIDTH", + "CHARSET_REGISTRY", + "CHARSET_ENCODING", +}; + + +/* read 2-byte value from a SFNT table */ +static FT_UShort +sfnt_get_ushort( FT_Face face, + FT_ULong table_tag, + FT_ULong table_offset ) +{ + FT_Byte buff[2]; + FT_ULong len = sizeof(buff); + FT_UShort result = 0; + + if ( !FT_Load_Sfnt_Table( face, table_tag, table_offset, buff, &len ) ); + result = (FT_UShort)( (buff[0] << 8) | buff[1] ); + + return result; +} + +#define sfnt_get_short(f,t,o) ((FT_Short)sfnt_get_ushort((f),(t),(o))) + + +static int ftypeInitP = 0; /* is the engine initialised? */ +FT_Library ftypeLibrary; + +static FTFacePtr faceTable[NUMFACEBUCKETS]; + +static unsigned +hash(char *string) +{ + int i; + unsigned u = 0; + for(i = 0; string[i] != '\0'; i++) + u = (u<<5) + (u >> (NUMFACEBUCKETS - 5)) + (unsigned char)string[i]; + return u; +} + +static int +ifloor(int x, int y) +{ + if(x >= 0) + return x/y; + else + return x/y - 1; +} + +static int +iceil(int x, int y) +{ + return ifloor(x + y - 1, y); +} + +static int +FreeTypeOpenFace(FTFacePtr *facep, char *FTFileName, char *realFileName, int faceNumber) +{ + FT_Error ftrc; + int bucket; + FTFacePtr face, otherFace; + + if (!ftypeInitP) { + ftrc = FT_Init_FreeType(&ftypeLibrary); + if (ftrc != 0) { + ErrorF("FreeType: error initializing ftypeEngine: %d\n", ftrc); + return AllocError; + } + ftypeInitP = 1; + } + + /* Try to find a matching face in the hashtable */ + bucket = hash(FTFileName)%NUMFACEBUCKETS; + otherFace = faceTable[bucket]; + while(otherFace) { + if( strcmp(otherFace->filename, FTFileName) == 0 ) break; + otherFace = otherFace->next; + } + if(otherFace) { + MUMBLE("Returning cached face: %s\n", otherFace->filename); + *facep = otherFace; + return Successful; + } + + /* No cached match; need to make a new one */ + face = calloc(1, sizeof(FTFaceRec)); + if (face == NULL) { + return AllocError; + } + + face->filename = strdup(FTFileName); + if (face->filename == NULL) { + free(face); + return AllocError; + } + + ftrc = FT_New_Face(ftypeLibrary, realFileName, faceNumber, &face->face); + if(ftrc != 0) { + ErrorF("FreeType: couldn't open face %s: %d\n", FTFileName, ftrc); + free(face->filename); + free(face); + return BadFontName; + } + + face->bitmap = ((face->face->face_flags & FT_FACE_FLAG_SCALABLE) == 0); + if(!face->bitmap) { + TT_MaxProfile *maxp; + maxp = FT_Get_Sfnt_Table(face->face, ft_sfnt_maxp); + if(maxp && maxp->maxContours == 0) + face->bitmap = 1; + } + + face->num_hmetrics = (FT_UInt) sfnt_get_ushort( face->face, + TTAG_hhea, 34 ); + + /* Insert face in hashtable and return it */ + face->next = faceTable[bucket]; + faceTable[bucket] = face; + *facep = face; + return Successful; +} + +static void +FreeTypeFreeFace(FTFacePtr face) +{ + int bucket; + FTFacePtr otherFace; + + if(!face->instances) { + bucket = hash(face->filename) % NUMFACEBUCKETS; + if(faceTable[bucket] == face) + faceTable[bucket] = face->next; + else { + otherFace = faceTable[bucket]; + while(otherFace) { + if(otherFace->next == face) + break; + otherFace = otherFace->next; + } + if(otherFace && otherFace->next) + otherFace->next = otherFace->next->next; + else + ErrorF("FreeType: freeing unknown face\n"); + } + MUMBLE("Closing face: %s\n", face->filename); + FT_Done_Face(face->face); + free(face->filename); + free(face); + } +} + +static int +TransEqual(FTNormalisedTransformationPtr t1, FTNormalisedTransformationPtr t2) +{ + if(t1->scale != t2->scale) + return 0; + else if(t1->xres != t2->xres || t1->yres != t2->yres) + return 0; + else if(t1->nonIdentity != t2->nonIdentity) + return 0; + else if(t1->nonIdentity && t2->nonIdentity) { + return + t1->matrix.xx == t2->matrix.xx && + t1->matrix.yx == t2->matrix.yx && + t1->matrix.yy == t2->matrix.yy && + t1->matrix.xy == t2->matrix.xy; + } else + return 1; +} + +static int +BitmapFormatEqual(FontBitmapFormatPtr f1, FontBitmapFormatPtr f2) +{ + return + f1->bit == f2->bit && + f1->byte == f2->byte && + f1->glyph == f2->glyph; +} + +static int +TTCapEqual(struct TTCapInfo *t1, struct TTCapInfo *t2) +{ + return + t1->autoItalic == t2->autoItalic && + t1->scaleWidth == t2->scaleWidth && + t1->scaleBBoxWidth == t2->scaleBBoxWidth && + t1->scaleBBoxHeight == t2->scaleBBoxHeight && + t1->doubleStrikeShift == t2->doubleStrikeShift && + t1->adjustBBoxWidthByPixel == t2->adjustBBoxWidthByPixel && + t1->adjustLeftSideBearingByPixel == t2->adjustLeftSideBearingByPixel && + t1->adjustRightSideBearingByPixel == t2->adjustRightSideBearingByPixel && + t1->flags == t2->flags && + t1->scaleBitmap == t2->scaleBitmap && + /* + If we use forceConstantSpacing, + we *MUST* allocate new instance. + */ + t1->forceConstantSpacingEnd < 0 && + t2->forceConstantSpacingEnd < 0; +} + +static int +FTInstanceMatch(FTInstancePtr instance, + char *FTFileName, FTNormalisedTransformationPtr trans, + int spacing, FontBitmapFormatPtr bmfmt, + struct TTCapInfo *tmp_ttcap, FT_Int32 load_flags) +{ + if(strcmp(instance->face->filename, FTFileName) != 0) { + return 0; + } else if(!TransEqual(&instance->transformation, trans)) { + return 0; + } else if( spacing != instance->spacing ) { + return 0; + } else if( load_flags != instance->load_flags ) { + return 0; + } else if(!BitmapFormatEqual(&instance->bmfmt, bmfmt)) { + return 0; + } else if(!TTCapEqual(&instance->ttcap, tmp_ttcap)) { + return 0; + } else { + return 1; + } +} + +static int +FreeTypeActivateInstance(FTInstancePtr instance) +{ + FT_Error ftrc; + if(instance->face->active_instance == instance) + return Successful; + + ftrc = FT_Activate_Size(instance->size); + if(ftrc != 0) { + instance->face->active_instance = NULL; + ErrorF("FreeType: couldn't activate instance: %d\n", ftrc); + return FTtoXReturnCode(ftrc); + } + FT_Set_Transform(instance->face->face, + instance->transformation.nonIdentity ? + &instance->transformation.matrix : 0, + 0); + + instance->face->active_instance = instance; + return Successful; +} + +static int +FTFindSize(FT_Face face, FTNormalisedTransformationPtr trans, + int *x_return, int *y_return) +{ + int tx, ty, x, y; + int i, j; + int d, dd; + + if(trans->nonIdentity) + return BadFontName; + + tx = (int)(trans->scale * trans->xres / 72.0 + 0.5); + ty = (int)(trans->scale * trans->yres / 72.0 + 0.5); + + d = 100; + j = -1; + for(i = 0; i < face->num_fixed_sizes; i++) { + x = face->available_sizes[i].width; + y = face->available_sizes[i].height; + if(ABS(x - tx) <= 1 && ABS(y - ty) <= 1) { + dd = ABS(x - tx) * ABS(x - tx) + ABS(y - ty) * ABS(y - ty); + if(dd < d) { + j = i; + d = dd; + } + } + } + if(j < 0) + return BadFontName; + + *x_return = face->available_sizes[j].width; + *y_return = face->available_sizes[j].height; + return Successful; +} + +static int +FreeTypeOpenInstance(FTInstancePtr *instance_return, FTFacePtr face, + char *FTFileName, FTNormalisedTransformationPtr trans, + int spacing, FontBitmapFormatPtr bmfmt, + struct TTCapInfo *tmp_ttcap, FT_Int32 load_flags) +{ + FT_Error ftrc; + int xrc; + FTInstancePtr instance, otherInstance; + + /* Search for a matching instance */ + for(otherInstance = face->instances; + otherInstance; + otherInstance = otherInstance->next) { + if(FTInstanceMatch(otherInstance, FTFileName, trans, spacing, bmfmt, + tmp_ttcap, load_flags)) break; + } + if(otherInstance) { + MUMBLE("Returning cached instance\n"); + otherInstance->refcount++; + *instance_return = otherInstance; + return Successful; + } + + /* None matching found */ + instance = malloc(sizeof(FTInstanceRec)); + if(instance == NULL) { + return AllocError; + } + + instance->refcount = 1; + instance->face = face; + + instance->load_flags = load_flags; + instance->spacing = spacing; /* Actual spacing */ + instance->pixel_size =0; + instance->pixel_width_unit_x =0; + instance->pixel_width_unit_y =0; + instance->charcellMetrics = NULL; + instance->averageWidth = 0; + instance->rawAverageWidth = 0; + instance->forceConstantMetrics = NULL; + + instance->transformation = *trans; + instance->bmfmt = *bmfmt; + instance->glyphs = NULL; + instance->available = NULL; + + if( 0 <= tmp_ttcap->forceConstantSpacingEnd ) + instance->nglyphs = 2 * instance->face->face->num_glyphs; + else + instance->nglyphs = instance->face->face->num_glyphs; + + /* Store the TTCap info. */ + memcpy((char*)&instance->ttcap, (char*)tmp_ttcap, + sizeof(struct TTCapInfo)); + + ftrc = FT_New_Size(instance->face->face, &instance->size); + if(ftrc != 0) { + ErrorF("FreeType: couldn't create size object: %d\n", ftrc); + free(instance); + return FTtoXReturnCode(ftrc); + } + FreeTypeActivateInstance(instance); + if(!face->bitmap) { + ftrc = FT_Set_Char_Size(instance->face->face, + (int)(trans->scale*(1<<6) + 0.5), + (int)(trans->scale*(1<<6) + 0.5), + trans->xres, trans->yres); + } else { + int xsize, ysize; + xrc = FTFindSize(face->face, trans, &xsize, &ysize); + if(xrc != Successful) { + free(instance); + return xrc; + } + ftrc = FT_Set_Pixel_Sizes(instance->face->face, xsize, ysize); + } + if(ftrc != 0) { + FT_Done_Size(instance->size); + free(instance); + return FTtoXReturnCode(ftrc); + } + + if( FT_IS_SFNT( face->face ) ) { +#if 1 + FT_F26Dot6 tt_char_width, tt_char_height, tt_dim_x, tt_dim_y; + FT_UInt nn; + + instance->strike_index=0xFFFFU; + + tt_char_width = (FT_F26Dot6)(trans->scale*(1<<6) + 0.5); + tt_char_height = (FT_F26Dot6)(trans->scale*(1<<6) + 0.5); + + tt_dim_x = FLOOR64( ( tt_char_width * trans->xres + 36 ) / 72 + 32 ); + tt_dim_y = FLOOR64( ( tt_char_height * trans->yres + 36 ) / 72 + 32 ); + + if ( tt_dim_x && !tt_dim_y ) + tt_dim_y = tt_dim_x; + else if ( !tt_dim_x && tt_dim_y ) + tt_dim_x = tt_dim_y; + + for ( nn = 0; nn < face->face->num_fixed_sizes; nn++ ) + { + FT_Bitmap_Size* sz = &face->face->available_sizes[nn]; + + if ( tt_dim_x == FLOOR64(sz->x_ppem + 32) && tt_dim_y == FLOOR64(sz->y_ppem + 32) ) + { + instance->strike_index = nn; + break; + } + } +#else + /* See Set_Char_Sizes() in ttdriver.c */ + FT_Error err; + TT_Face tt_face; + FT_Long tt_dim_x, tt_dim_y; + FT_UShort tt_x_ppem, tt_y_ppem; + FT_F26Dot6 tt_char_width, tt_char_height; + SFNT_Service sfnt; + tt_face=(TT_Face)face->face; + tt_char_width = (int)(trans->scale*(1<<6) + 0.5); + tt_char_height = (int)(trans->scale*(1<<6) + 0.5); + if ( ( tt_face->header.Flags & 8 ) != 0 ) { + tt_dim_x = ( ( tt_char_width * trans->xres + (36+32*72) ) / 72 ) & -64; + tt_dim_y = ( ( tt_char_height * trans->yres + (36+32*72) ) / 72 ) & -64; + } + else{ + tt_dim_x = ( ( tt_char_width * trans->xres + 36 ) / 72 ); + tt_dim_y = ( ( tt_char_height * trans->yres + 36 ) / 72 ); + } + tt_x_ppem = (FT_UShort)( tt_dim_x >> 6 ); + tt_y_ppem = (FT_UShort)( tt_dim_y >> 6 ); + /* See Reset_SBit_Size() in ttobjs.c */ + sfnt = (SFNT_Service)tt_face->sfnt; + err = sfnt->set_sbit_strike(tt_face,tt_x_ppem,tt_y_ppem,&instance->strike_index); + if ( err ) instance->strike_index=0xFFFFU; +#endif + } + + /* maintain a linked list of instances */ + instance->next = instance->face->instances; + instance->face->instances = instance; + + *instance_return = instance; + return Successful; +} + +static void +FreeTypeFreeInstance(FTInstancePtr instance) +{ + FTInstancePtr otherInstance; + + if( instance == NULL ) return; + + if(instance->face->active_instance == instance) + instance->face->active_instance = NULL; + instance->refcount--; + if(instance->refcount <= 0) { + int i,j; + + if(instance->face->instances == instance) + instance->face->instances = instance->next; + else { + for(otherInstance = instance->face->instances; + otherInstance; + otherInstance = otherInstance->next) + if(otherInstance->next == instance) { + otherInstance->next = instance->next; + break; + } + } + + FT_Done_Size(instance->size); + FreeTypeFreeFace(instance->face); + + if(instance->charcellMetrics) { + free(instance->charcellMetrics); + } + if(instance->forceConstantMetrics) { + free(instance->forceConstantMetrics); + } + if(instance->glyphs) { + for(i = 0; i < iceil(instance->nglyphs, FONTSEGMENTSIZE); i++) { + if(instance->glyphs[i]) { + for(j = 0; j < FONTSEGMENTSIZE; j++) { + if(instance->available[i][j] == + FT_AVAILABLE_RASTERISED) + free(instance->glyphs[i][j].bits); + } + free(instance->glyphs[i]); + } + } + free(instance->glyphs); + } + if(instance->available) { + for(i = 0; i < iceil(instance->nglyphs, FONTSEGMENTSIZE); i++) { + if(instance->available[i]) + free(instance->available[i]); + } + free(instance->available); + } + free(instance); + } +} + +static int +FreeTypeInstanceFindGlyph(unsigned idx_in, int flags, FTInstancePtr instance, + CharInfoPtr **glyphs, int ***available, + int *found, int *segmentP, int *offsetP) +{ + int segment, offset; + unsigned idx = idx_in; + + if( 0 <= instance->ttcap.forceConstantSpacingEnd ){ + if( (flags & FT_FORCE_CONSTANT_SPACING) ) + idx += instance->nglyphs / 2 ; + } + + if(idx > instance->nglyphs) { + *found = 0; + return Successful; + } + + if(*available == NULL) { + *available = calloc(iceil(instance->nglyphs, FONTSEGMENTSIZE), + sizeof(int *)); + if(*available == NULL) + return AllocError; + } + + segment = ifloor(idx, FONTSEGMENTSIZE); + offset = idx - segment * FONTSEGMENTSIZE; + + if((*available)[segment] == NULL) { + (*available)[segment] = calloc(FONTSEGMENTSIZE, sizeof(int *)); + if((*available)[segment] == NULL) + return AllocError; + } + + if(*glyphs == NULL) { + *glyphs = calloc(iceil(instance->nglyphs, FONTSEGMENTSIZE), + sizeof(CharInfoPtr)); + if(*glyphs == NULL) + return AllocError; + } + + if((*glyphs)[segment] == NULL) { + (*glyphs)[segment] = malloc(sizeof(CharInfoRec) * FONTSEGMENTSIZE); + if((*glyphs)[segment] == NULL) + return AllocError; + } + + *found = 1; + *segmentP = segment; + *offsetP = offset; + return Successful; +} + +static int +FreeTypeInstanceGetGlyph(unsigned idx, int flags, CharInfoPtr *g, FTInstancePtr instance) +{ + int found, segment, offset; + int xrc; + int ***available; + CharInfoPtr **glyphs; + + available = &instance->available; + glyphs = &instance->glyphs; + + xrc = FreeTypeInstanceFindGlyph(idx, flags, instance, glyphs, available, + &found, &segment, &offset); + if(xrc != Successful) + return xrc; + + if(!found || (*available)[segment][offset] == FT_AVAILABLE_NO) { + *g = NULL; + return Successful; + } + + if((*available)[segment][offset] == FT_AVAILABLE_RASTERISED) { + *g = &(*glyphs)[segment][offset]; + return Successful; + } + + flags |= FT_GET_GLYPH_BOTH; + + xrc = FreeTypeRasteriseGlyph(idx, flags, + &(*glyphs)[segment][offset], instance, + (*available)[segment][offset] >= FT_AVAILABLE_METRICS); + if(xrc != Successful && (*available)[segment][offset] >= FT_AVAILABLE_METRICS) { + ErrorF("Warning: FreeTypeRasteriseGlyph() returns an error,\n"); + ErrorF("\tso the backend tries to set a white space.\n"); + xrc = FreeTypeRasteriseGlyph(idx, flags | FT_GET_DUMMY, + &(*glyphs)[segment][offset], instance, + (*available)[segment][offset] >= FT_AVAILABLE_METRICS); + } + if(xrc == Successful) { + (*available)[segment][offset] = FT_AVAILABLE_RASTERISED; + /* return the glyph */ + *g = &(*glyphs)[segment][offset]; + } + return xrc; +} + +static int +FreeTypeInstanceGetGlyphMetrics(unsigned idx, int flags, + xCharInfo **metrics, FTInstancePtr instance ) +{ + int xrc; + int found, segment, offset; + + /* Char cell */ + if(instance->spacing == FT_CHARCELL) { + *metrics = instance->charcellMetrics; + return Successful; + } + /* Force constant metrics */ + if( flags & FT_FORCE_CONSTANT_SPACING) { + *metrics = instance->forceConstantMetrics; + return Successful; + } + + /* Not char cell */ + + xrc = FreeTypeInstanceFindGlyph(idx, flags, instance, + &instance->glyphs, &instance->available, + &found, &segment, &offset); + if(xrc != Successful) + return xrc; + if(!found) { + *metrics = NULL; + return Successful; + } + if( instance->available[segment][offset] == FT_AVAILABLE_NO ) { + *metrics = NULL; + return Successful; + } + + if( instance->available[segment][offset] >= FT_AVAILABLE_METRICS ) { + *metrics = &instance->glyphs[segment][offset].metrics; + return Successful; + } + + flags |= FT_GET_GLYPH_METRICS_ONLY; + + xrc = FreeTypeRasteriseGlyph(idx, flags, + &instance->glyphs[segment][offset], + instance, 0); + if(xrc == Successful) { + instance->available[segment][offset] = FT_AVAILABLE_METRICS; + *metrics = &instance->glyphs[segment][offset].metrics; + } + return xrc; +} + +/* + * Pseudo enbolding similar as Microsoft Windows. + * It is useful but poor. + */ +static void +ft_make_up_bold_bitmap( char *raster, int bpr, int ht, int ds_mode) +{ + int x, y; + unsigned char *p = (unsigned char *)raster; + if ( ds_mode & TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT ) { + for (y=0; y>1) | lsb; + *p &= ~(rev_pat & (*p << 1)); + lsb = tmp; + p++; + } + } + } + else { + for (y=0; y>1) | lsb; + lsb = tmp; + p++; + } + } + } +} + +static void +ft_make_up_italic_bitmap( char *raster, int bpr, int ht, int shift, + int h_total, int h_offset, double a_italic) +{ + int x, y; + unsigned char *p = (unsigned char *)raster; + if ( a_italic < 0 ) shift = -shift; + for (y=0; y>=tmp_shift; + } + } + if ( tmp_byte_shift ) { + for (x=bpr-1;0>(8-tmp_shift); + tmp_p[x]<<=tmp_shift; + } + } + if ( tmp_byte_shift ) { + for (x=0;x length ) + { + *advance = 0; + *bearing = 0; + } + else + { + *advance = sfnt_get_ushort( face, TTAG_hmtx, offset ); + *bearing = sfnt_get_short ( face, TTAG_hmtx, offset+2 ); + } + } + else + { + offset = 4L * (count - 1); + if ( offset + 4 > length ) + { + *advance = 0; + *bearing = 0; + } + else + { + *advance = sfnt_get_ushort ( face, TTAG_hmtx, offset ); + offset += 4 + 2 * ( idx - count ); + if ( offset + 2 > length) + *bearing = 0; + else + *bearing = sfnt_get_short ( face, TTAG_hmtx, offset ); + } + } +} + +static int +ft_get_very_lazy_bbox( FT_UInt index, + FT_Face face, + FT_Size size, + FT_UInt num_hmetrics, + double slant, + FT_Matrix *matrix, + FT_BBox *bbox, + FT_Long *horiAdvance, + FT_Long *vertAdvance) +{ + if ( FT_IS_SFNT( face ) ) { + FT_Size_Metrics *smetrics = &size->metrics; + FT_Short leftBearing = 0; + FT_UShort advance = 0; + FT_Vector p0, p1, p2, p3; + + /* horizontal */ + tt_get_metrics( face, index, num_hmetrics, + &leftBearing, &advance ); + +#if 0 + fprintf(stderr,"x_scale=%f y_scale=%f\n", + (double)smetrics->x_scale,(double)smetrics->y_scale); +#endif + bbox->xMax = *horiAdvance = + FT_MulFix( advance, smetrics->x_scale ); + bbox->xMin = + FT_MulFix( leftBearing, smetrics->x_scale ); + /* vertical */ + bbox->yMin = FT_MulFix( face->bbox.yMin, + smetrics->y_scale ); + bbox->yMax = FT_MulFix( face->bbox.yMax, + smetrics->y_scale ); + /* slant */ + if( 0 < slant ) { + bbox->xMax += slant * bbox->yMax; + bbox->xMin += slant * bbox->yMin; + } + else if( slant < 0 ) { + bbox->xMax += slant * bbox->yMin; + bbox->xMin += slant * bbox->yMax; + } + + *vertAdvance = -1; /* We don't support */ + + p0.x = p2.x = bbox->xMin; + p1.x = p3.x = bbox->xMax; + p0.y = p1.y = bbox->yMin; + p2.y = p3.y = bbox->yMax; + + FT_Vector_Transform(&p0, matrix); + FT_Vector_Transform(&p1, matrix); + FT_Vector_Transform(&p2, matrix); + FT_Vector_Transform(&p3, matrix); + +#if 0 + fprintf(stderr, + "->(%.1f %.1f) (%.1f %.1f)" + " (%.1f %.1f) (%.1f %.1f)\n", + p0.x / 64.0, p0.y / 64.0, + p1.x / 64.0, p1.y / 64.0, + p2.x / 64.0, p2.y / 64.0, + p3.x / 64.0, p3.y / 64.0); +#endif + bbox->xMin = MIN(p0.x, MIN(p1.x, MIN(p2.x, p3.x))); + bbox->xMax = MAX(p0.x, MAX(p1.x, MAX(p2.x, p3.x))); + bbox->yMin = MIN(p0.y, MIN(p1.y, MIN(p2.y, p3.y))); + bbox->yMax = MAX(p0.y, MAX(p1.y, MAX(p2.y, p3.y))); + return 0; /* Successful */ + } + return -1; +} + +static FT_Error +FT_Do_SBit_Metrics( FT_Face ft_face, FT_Size ft_size, FT_ULong strike_index, + FT_UShort glyph_index, FT_Glyph_Metrics *metrics_return, + int *sbitchk_incomplete_but_exist ) +{ +#if 1 + if ( strike_index != 0xFFFFU && ft_face->available_sizes != NULL ) + { + FT_Error error; + FT_Bitmap_Size* sz = &ft_face->available_sizes[strike_index]; + + error = FT_Set_Pixel_Sizes( ft_face, sz->x_ppem/64, sz->y_ppem/64 ); + if ( !error ) + { + error = FT_Load_Glyph( ft_face, glyph_index, FT_LOAD_SBITS_ONLY ); + if ( !error ) + { + if ( metrics_return != NULL ) + *metrics_return = ft_face->glyph->metrics; + + return 0; + } + } + } + return -1; +#elif (FREETYPE_VERSION >= 2001008) + SFNT_Service sfnt; + TT_Face face; + FT_Error error; + FT_Stream stream; + TT_SBit_Strike strike; + TT_SBit_Range range; + TT_SBit_MetricsRec elem_metrics; + FT_ULong ebdt_pos; + FT_ULong glyph_offset; + ; + + if ( ! FT_IS_SFNT( ft_face ) ) + { + error=-1; + goto Exit; + } + + face = (TT_Face)ft_face; + sfnt = (SFNT_Service)face->sfnt; + + if (strike_index != 0xFFFFU && sfnt && sfnt->find_sbit_image && + sfnt->load_sbits) { + /* Check whether there is a glyph sbit for the current index */ + error = sfnt->find_sbit_image( face, glyph_index, strike_index, + &range, &strike, &glyph_offset ); + } + else error=-1; + if ( error ) goto Exit; + + if ( metrics_return == NULL ) goto Exit; + + stream = face->root.stream; + + /* now, find the location of the `EBDT' table in */ + /* the font file */ + error = face->goto_table( face, TTAG_EBDT, stream, 0 ); + if ( error ) + error = face->goto_table( face, TTAG_bdat, stream, 0 ); + if (error) + goto Exit; + + ebdt_pos = FT_STREAM_POS(); + + /* place stream at beginning of glyph data and read metrics */ + if ( FT_STREAM_SEEK( ebdt_pos + glyph_offset ) ) + goto Exit; + + error = sfnt->load_sbit_metrics( stream, range, &elem_metrics ); + if ( error ) + goto Exit; + + metrics_return->width = (FT_Pos)elem_metrics.width << 6; + metrics_return->height = (FT_Pos)elem_metrics.height << 6; + + metrics_return->horiBearingX = (FT_Pos)elem_metrics.horiBearingX << 6; + metrics_return->horiBearingY = (FT_Pos)elem_metrics.horiBearingY << 6; + metrics_return->horiAdvance = (FT_Pos)elem_metrics.horiAdvance << 6; + + metrics_return->vertBearingX = (FT_Pos)elem_metrics.vertBearingX << 6; + metrics_return->vertBearingY = (FT_Pos)elem_metrics.vertBearingY << 6; + metrics_return->vertAdvance = (FT_Pos)elem_metrics.vertAdvance << 6; + + Exit: + return error; +#else /* if (FREETYPE_VERSION < 2001008) */ + TT_Face face; + SFNT_Service sfnt; + if ( ! FT_IS_SFNT( ft_face ) ) return -1; + face = (TT_Face)ft_face; + sfnt = (SFNT_Service)face->sfnt; + if ( strike_index != 0xFFFFU && sfnt->load_sbits ) { + if ( sbitchk_incomplete_but_exist ) *sbitchk_incomplete_but_exist=1; + } + return -1; +#endif +} + +int +FreeTypeRasteriseGlyph(unsigned idx, int flags, CharInfoPtr tgp, + FTInstancePtr instance, int hasMetrics) +{ + FTFacePtr face; + FT_BBox bbox; + FT_Long outline_hori_advance, outline_vert_advance; + FT_Glyph_Metrics sbit_metrics; + FT_Glyph_Metrics *bitmap_metrics=NULL, *metrics = NULL; + char *raster; + int wd, ht, bpr; /* width, height, bytes per row */ + int wd_actual, ht_actual; + int ftrc, is_outline, correct, b_shift=0; + int dx, dy; + int leftSideBearing, rightSideBearing, characterWidth, rawCharacterWidth, + ascent, descent; + int sbitchk_incomplete_but_exist; + double bbox_center_raw; + + face = instance->face; + + FreeTypeActivateInstance(instance); + + if(!tgp) return AllocError; + + /* + * PREPARE METRICS + */ + + if(!hasMetrics) { + if( instance->spacing == FT_CHARCELL || flags & FT_GET_DUMMY ){ + memcpy((char*)&tgp->metrics, + (char*)instance->charcellMetrics, + sizeof(xCharInfo)); + } + else if( flags & FT_FORCE_CONSTANT_SPACING ) { + memcpy((char*)&tgp->metrics, + (char*)instance->forceConstantMetrics, + sizeof(xCharInfo)); + } + /* mono or prop. */ + else{ + int new_width; + double ratio; + + sbitchk_incomplete_but_exist=0; + if( ! (instance->load_flags & FT_LOAD_NO_BITMAP) ) { + if( FT_Do_SBit_Metrics(face->face,instance->size,instance->strike_index, + idx,&sbit_metrics,&sbitchk_incomplete_but_exist)==0 ) { + bitmap_metrics = &sbit_metrics; + } + } + if( bitmap_metrics == NULL ) { + if ( sbitchk_incomplete_but_exist==0 && (instance->ttcap.flags & TTCAP_IS_VERY_LAZY) ) { + if( ft_get_very_lazy_bbox( idx, face->face, instance->size, + face->num_hmetrics, + instance->ttcap.vl_slant, + &instance->transformation.matrix, + &bbox, &outline_hori_advance, + &outline_vert_advance ) == 0 ) { + goto bbox_ok; /* skip exact calculation */ + } + } + ftrc = FT_Load_Glyph(instance->face->face, idx, + instance->load_flags); + if(ftrc != 0) return FTtoXReturnCode(ftrc); + metrics = &face->face->glyph->metrics; + if( face->face->glyph->format == FT_GLYPH_FORMAT_BITMAP ) { + bitmap_metrics = metrics; + } + } + + if( bitmap_metrics ) { + FT_Pos factor; + + leftSideBearing = bitmap_metrics->horiBearingX / 64; + rightSideBearing = (bitmap_metrics->width + bitmap_metrics->horiBearingX) / 64; + bbox_center_raw = (2.0 * bitmap_metrics->horiBearingX + bitmap_metrics->width)/2.0/64.0; + characterWidth = (int)floor(bitmap_metrics->horiAdvance + * instance->ttcap.scaleBBoxWidth / 64.0 + .5); + ascent = bitmap_metrics->horiBearingY / 64; + descent = (bitmap_metrics->height - bitmap_metrics->horiBearingY) / 64 ; + /* */ + new_width = characterWidth; + if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH ) + new_width += instance->ttcap.doubleStrikeShift; + new_width += instance->ttcap.adjustBBoxWidthByPixel; + ratio = (double)new_width/characterWidth; + characterWidth = new_width; + /* adjustment by pixel unit */ + if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE ) + rightSideBearing += instance->ttcap.doubleStrikeShift; + rightSideBearing += instance->ttcap.adjustRightSideBearingByPixel; + leftSideBearing += instance->ttcap.adjustLeftSideBearingByPixel; + rightSideBearing += instance->ttcap.rsbShiftOfBitmapAutoItalic; + leftSideBearing += instance->ttcap.lsbShiftOfBitmapAutoItalic; + /* */ + factor = bitmap_metrics->horiAdvance; + rawCharacterWidth = (unsigned short)(short)(floor(1000 * factor + * instance->ttcap.scaleBBoxWidth * ratio / 64. + / instance->pixel_size)); + } + else { + /* Outline */ +#ifdef USE_GET_CBOX + /* Very fast?? */ + FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox); + ftrc=0; /* FT_Outline_Get_CBox returns nothing. */ +#else + /* Calculate exact metrics */ + ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox); +#endif + if( ftrc != 0 ) return FTtoXReturnCode(ftrc); + outline_hori_advance = metrics->horiAdvance; + outline_vert_advance = metrics->vertAdvance; + bbox_ok: + descent = CEIL64(-bbox.yMin - 32) / 64; + leftSideBearing = FLOOR64(bbox.xMin + 32) / 64; + ascent = FLOOR64(bbox.yMax + 32) / 64; + rightSideBearing = FLOOR64(bbox.xMax + 32) / 64; + bbox_center_raw = (double)(bbox.xMax + bbox.xMin)/2.0/64.; + if ( instance->pixel_width_unit_x != 0 ) + characterWidth = + (int)floor( outline_hori_advance + * instance->ttcap.scaleBBoxWidth + * instance->pixel_width_unit_x / 64. + .5); + else { + characterWidth = + (int)floor( outline_vert_advance + * instance->ttcap.scaleBBoxHeight + * instance->pixel_width_unit_y / 64. + .5); + if(characterWidth <= 0) + characterWidth = instance->charcellMetrics->characterWidth; + } + /* */ + new_width = characterWidth; + if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH ) + new_width += instance->ttcap.doubleStrikeShift; + new_width += instance->ttcap.adjustBBoxWidthByPixel; + ratio = (double)new_width/characterWidth; + characterWidth = new_width; + if ( instance->pixel_width_unit_x != 0 ) + rawCharacterWidth = + (unsigned short)(short)(floor(1000 * outline_hori_advance + * instance->ttcap.scaleBBoxWidth * ratio + * instance->pixel_width_unit_x / 64.)); + else { + rawCharacterWidth = + (unsigned short)(short)(floor(1000 * outline_vert_advance + * instance->ttcap.scaleBBoxHeight * ratio + * instance->pixel_width_unit_y / 64.)); + if(rawCharacterWidth <= 0) + rawCharacterWidth = instance->charcellMetrics->attributes; + } + /* adjustment by pixel unit */ + if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE ) + rightSideBearing += instance->ttcap.doubleStrikeShift; + rightSideBearing += instance->ttcap.adjustRightSideBearingByPixel; + leftSideBearing += instance->ttcap.adjustLeftSideBearingByPixel; + } + + /* Set the glyph metrics. */ + tgp->metrics.attributes = (unsigned short)((short)rawCharacterWidth); + tgp->metrics.leftSideBearing = leftSideBearing; + tgp->metrics.rightSideBearing = rightSideBearing; + tgp->metrics.characterWidth = characterWidth; + tgp->metrics.ascent = ascent; + tgp->metrics.descent = descent; + /* Update the width to match the width of the font */ + if( instance->spacing != FT_PROPORTIONAL ) + tgp->metrics.characterWidth = instance->charcellMetrics->characterWidth; + if(instance->ttcap.flags & TTCAP_MONO_CENTER){ + b_shift = (int)floor((instance->advance/2.0-bbox_center_raw) + .5); + tgp->metrics.leftSideBearing += b_shift; + tgp->metrics.rightSideBearing += b_shift; + } + } + } + + if( flags & FT_GET_GLYPH_METRICS_ONLY ) return Successful; + + /* + * CHECK THE NECESSITY OF BITMAP POSITION'S CORRECTION + */ + + correct=0; + if( instance->spacing == FT_CHARCELL ) correct=1; + else if( flags & FT_FORCE_CONSTANT_SPACING ) correct=1; + else{ + int sbit_available=0; + sbitchk_incomplete_but_exist=0; + if( !(instance->load_flags & FT_LOAD_NO_BITMAP) ) { + if( FT_Do_SBit_Metrics(face->face,instance->size, + instance->strike_index,idx,NULL, + &sbitchk_incomplete_but_exist)==0 ) { + sbit_available=1; + } + } + if( sbit_available == 0 ) { + if ( sbitchk_incomplete_but_exist==0 && (instance->ttcap.flags & TTCAP_IS_VERY_LAZY) ) { + if( FT_IS_SFNT(face->face) ) correct=1; + } + } + } + + /* + * RENDER AND ALLOCATE BUFFER + */ + + if( flags & FT_GET_DUMMY ) is_outline = -1; + else { + if( !metrics ) { + ftrc = FT_Load_Glyph(instance->face->face, idx, + instance->load_flags); + metrics = &face->face->glyph->metrics; + + if(ftrc != 0) return FTtoXReturnCode(ftrc); + } + + if( face->face->glyph->format != FT_GLYPH_FORMAT_BITMAP ) { +#ifdef USE_GET_CBOX + FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox); + ftrc = 0; +#else + ftrc = FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox); +#endif + if( ftrc != 0 ) return FTtoXReturnCode(ftrc); + bbox.yMin = FLOOR64( bbox.yMin ); + bbox.yMax = CEIL64 ( bbox.yMax ); + ht_actual = ( bbox.yMax - bbox.yMin ) >> 6; + /* FreeType think a glyph with 0 height control box is invalid. + * So just let X to create a empty bitmap instead. */ + if ( ht_actual == 0 ) + is_outline = -1; + else + { + ftrc = FT_Render_Glyph(face->face->glyph,FT_RENDER_MODE_MONO); + if( ftrc != 0 ) return FTtoXReturnCode(ftrc); + is_outline = 1; + } + } + else{ + is_outline=0; + } + } + + /* Spacial case */ + if( (instance->ttcap.flags & TTCAP_MONO_CENTER) && hasMetrics ) { + if( is_outline == 1 ){ + if( correct ){ + if( ft_get_very_lazy_bbox( idx, face->face, instance->size, + face->num_hmetrics, + instance->ttcap.vl_slant, + &instance->transformation.matrix, + &bbox, &outline_hori_advance, + &outline_vert_advance ) != 0 ){ + is_outline = -1; /* <- error */ + } + } + else { +#ifdef USE_GET_CBOX + FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox); + ftrc=0; +#else + ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox); +#endif + if( ftrc != 0 ) return FTtoXReturnCode(ftrc); + } + bbox_center_raw = (double)(bbox.xMax + bbox.xMin)/2.0/64.; + } + else if( is_outline == 0 ) + bbox_center_raw = (2.0 * metrics->horiBearingX + metrics->width)/2.0/64.0; + else + bbox_center_raw = 0; + b_shift = (int)floor((instance->advance/2.0-bbox_center_raw) + .5); + } + + wd_actual = tgp->metrics.rightSideBearing - tgp->metrics.leftSideBearing; + ht_actual = tgp->metrics.ascent + tgp->metrics.descent; + + /* The X convention is to consider a character with an empty + * bounding box as undefined. This convention is broken. */ + + if(wd_actual <= 0) wd = 1; + else wd=wd_actual; + if(ht_actual <= 0) ht = 1; + else ht=ht_actual; + + bpr = (((wd + (instance->bmfmt.glyph<<3) - 1) >> 3) & + -instance->bmfmt.glyph); + raster = calloc(1, ht * bpr); + if(raster == NULL) + return AllocError; + + tgp->bits = raster; + + /* If FT_GET_DUMMY is set, we return white space. */ + if ( is_outline == -1 ) return Successful; + + if ( wd_actual <= 0 || ht_actual <= 0 ) return Successful; + + /* + * CALCULATE OFFSET, dx AND dy. + */ + + dx = face->face->glyph->bitmap_left - tgp->metrics.leftSideBearing; + dy = tgp->metrics.ascent - face->face->glyph->bitmap_top; + + if(instance->ttcap.flags & TTCAP_MONO_CENTER) + dx += b_shift; + + /* To prevent chipped bitmap, we correct dx and dy if needed. */ + if( correct && is_outline==1 ){ + int lsb, rsb, asc, des; + int chip_left,chip_right,chip_top,chip_bot; +#ifdef USE_GET_CBOX + FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox); + ftrc=0; +#else + ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox); +#endif + if( ftrc != 0 ) return FTtoXReturnCode(ftrc); + des = CEIL64(-bbox.yMin - 32) / 64; + lsb = FLOOR64(bbox.xMin + 32) / 64; + asc = FLOOR64(bbox.yMax + 32) / 64; + rsb = FLOOR64(bbox.xMax + 32) / 64; + rightSideBearing = tgp->metrics.rightSideBearing; + leftSideBearing = tgp->metrics.leftSideBearing; + if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE ) + rightSideBearing -= instance->ttcap.doubleStrikeShift; + /* special case */ + if(instance->ttcap.flags & TTCAP_MONO_CENTER){ + leftSideBearing -= b_shift; + rightSideBearing -= b_shift; + } + chip_left = lsb - leftSideBearing; + chip_right = rightSideBearing - rsb; + if( flags & FT_FORCE_CONSTANT_SPACING ){ + if( instance->ttcap.force_c_adjust_lsb_by_pixel != 0 || + instance->ttcap.force_c_adjust_rsb_by_pixel != 0 ){ + chip_left=0; + chip_right=0; + } + } + else{ + if( instance->ttcap.adjustRightSideBearingByPixel != 0 || + instance->ttcap.adjustLeftSideBearingByPixel != 0 ){ + chip_left=0; + chip_right=0; + } + } + chip_top = tgp->metrics.ascent - asc; + chip_bot = tgp->metrics.descent - des; + if( chip_left < 0 && 0 < chip_right ) dx++; + else if( chip_right < 0 && 0 < chip_left ) dx--; + if( chip_top < 0 && 0 < chip_bot ) dy++; + else if( chip_bot < 0 && 0 < chip_top ) dy--; + } + + /* + * COPY RASTER + */ + + { + FT_Bitmap *bitmap; + int i, j; + unsigned char *current_raster; + unsigned char *current_buffer; + int mod_dx0,mod_dx1; + int div_dx; + bitmap = &face->face->glyph->bitmap; + if( 0 <= dx ){ + div_dx = dx / 8; + mod_dx0 = dx % 8; + mod_dx1 = 8-mod_dx0; + } + else{ + div_dx = dx / 8 -1; + mod_dx1 = -dx % 8; + mod_dx0 = 8-mod_dx1; + } + for( i = MAX(0, dy) ; irows <= i-dy ) break; + current_buffer=(unsigned char *)(bitmap->buffer+bitmap->pitch*(i-dy)); + current_raster=(unsigned char *)(raster+i*bpr); + j = MAX(0,div_dx); + jj = j-div_dx; + prev_jj = jj-1; + if( jpitch ) + current_raster[j]|=current_buffer[prev_jj]<pitch ){ + current_raster[j]|=current_buffer[jj]>>mod_dx0; + j++; prev_jj++; jj++; + for( ; jpitch <= jj ) break; + current_raster[j]|=current_buffer[jj]>>mod_dx0; + } + } + } + } + } + + /* by TTCap */ + if ( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE ) { + int i; + for( i=0 ; i < instance->ttcap.doubleStrikeShift ; i++ ) + ft_make_up_bold_bitmap( raster, bpr, ht, instance->ttcap.flags); + } + if ( is_outline == 0 && + ( instance->ttcap.lsbShiftOfBitmapAutoItalic != 0 || + instance->ttcap.rsbShiftOfBitmapAutoItalic != 0 ) ) { + ft_make_up_italic_bitmap( raster, bpr, ht, + - instance->ttcap.lsbShiftOfBitmapAutoItalic + + instance->ttcap.rsbShiftOfBitmapAutoItalic, + instance->charcellMetrics->ascent + + instance->charcellMetrics->descent, + instance->charcellMetrics->ascent + - tgp->metrics.ascent, + instance->ttcap.autoItalic); + } + + if(instance->bmfmt.bit == LSBFirst) { + BitOrderInvert((unsigned char*)(tgp->bits), ht*bpr); + } + + if(instance->bmfmt.byte != instance->bmfmt.bit) { + switch(instance->bmfmt.scan) { + case 1: + break; + case 2: + TwoByteSwap((unsigned char*)(tgp->bits), ht*bpr); + break; + case 4: + FourByteSwap((unsigned char*)(tgp->bits), ht*bpr); + break; + default: + ; + } + } + + return Successful; +} + +static void +FreeTypeFreeFont(FTFontPtr font) +{ + FreeTypeFreeInstance(font->instance); + if(font->ranges) + free(font->ranges); + if(font->dummy_char.bits) + free(font->dummy_char.bits); + free(font); +} + +/* Free a font. If freeProps is 0, don't free the properties. */ + +static void +FreeTypeFreeXFont(FontPtr pFont, int freeProps) +{ + FTFontPtr tf; + + if(pFont) { + if((tf = (FTFontPtr)pFont->fontPrivate)) { + FreeTypeFreeFont(tf); + } + if(freeProps && pFont->info.nprops>0) { + free(pFont->info.isStringProp); + free(pFont->info.props); + } + DestroyFontRec(pFont); + } +} + + +/* Unload a font */ + +static void +FreeTypeUnloadXFont(FontPtr pFont) +{ + MUMBLE("Unloading\n"); + FreeTypeFreeXFont(pFont, 1); +} + +/* Add the font properties, including the Font name, the XLFD + properties, some strings from the font, and various typographical + data. We only provide data readily available in the tables in the + font for now, altough FIGURE_WIDTH would be a good idea as it is + used by Xaw. */ + +static int +FreeTypeAddProperties(FTFontPtr font, FontScalablePtr vals, FontInfoPtr info, + char *fontname, int rawAverageWidth, Bool font_properties) +{ + int i, j, maxprops; + char *sp, *ep, val[MAXFONTNAMELEN], *vp; + FTFacePtr face; + FTInstancePtr instance; + FTNormalisedTransformationPtr trans; + int upm; + TT_OS2 *os2; + TT_Postscript *post; + PS_FontInfoRec t1info_rec, *t1info; + int xlfdProps = 0; + int ftrc; + + instance = font->instance; + face = instance->face; + trans = &instance->transformation; + upm = face->face->units_per_EM; + if(upm == 0) { + /* Work around FreeType bug */ + upm = WORK_AROUND_UPM; + } + + os2 = FT_Get_Sfnt_Table(face->face, ft_sfnt_os2); + post = FT_Get_Sfnt_Table(face->face, ft_sfnt_post); + ftrc = FT_Get_PS_Font_Info(face->face, &t1info_rec); + if(ftrc == 0) + t1info = &t1info_rec; + else + t1info = NULL; + + if(t1info) { + os2 = NULL; + post = NULL; + } + + info->nprops = 0; /* in case we abort */ + + strcpy(val, fontname); + if(FontParseXLFDName(val, vals, FONT_XLFD_REPLACE_VALUE)) { + xlfdProps = 1; + } else { + MUMBLE("Couldn't parse XLFD\n"); + xlfdProps = 0; + } + + maxprops= + 1 + /* NAME */ + (xlfdProps ? 14 : 0) + /* from XLFD */ + 5 + + ( !face->bitmap ? 3 : 0 ) + /* raw_av,raw_asc,raw_dec */ + ( font_properties ? 2 : 0 ) + /* asc,dec */ + ( (font_properties && os2) ? 6 : 0 ) + + ( (font_properties && (post || t1info)) ? 3 : 0 ) + + 2; /* type */ + + info->props = malloc(maxprops * sizeof(FontPropRec)); + if(info->props == NULL) + return AllocError; + + info->isStringProp = malloc(maxprops); + if(info->isStringProp == NULL) { + free(info->props); + return AllocError; + } + + memset((char *)info->isStringProp, 0, maxprops); + + i = 0; + + info->props[i].name = MakeAtom("FONT", 4, TRUE); + info->props[i].value = MakeAtom(val, strlen(val), TRUE); + info->isStringProp[i] = 1; + i++; + + if(*val && *(sp = val + 1)) { + for (j = 0, sp = val + 1; j < 14; j++) { + if (j == 13) + /* Handle the case of the final field containing a subset + specification. */ + for (ep = sp; *ep && *ep != '['; ep++); + else + for (ep = sp; *ep && *ep != '-'; ep++); + + info->props[i].name = + MakeAtom(xlfd_props[j], strlen(xlfd_props[j]), TRUE); + + switch(j) { + case 6: /* pixel size */ + info->props[i].value = + (int)(fabs(vals->pixel_matrix[3]) + 0.5); + i++; + break; + case 7: /* point size */ + info->props[i].value = + (int)(fabs(vals->point_matrix[3])*10.0 + 0.5); + i++; + break; + case 8: /* resolution x */ + info->props[i].value = vals->x; + i++; + break; + case 9: /* resolution y */ + info->props[i].value = vals->y; + i++; + break; + case 11: /* average width */ + info->props[i].value = vals->width; + i++; + break; + default: /* a string */ + info->props[i].value = MakeAtom(sp, ep - sp, TRUE); + info->isStringProp[i] = 1; + i++; + } + sp = ++ep; + } + } + + info->props[i].name = MakeAtom("RAW_PIXEL_SIZE", 14, TRUE); + info->props[i].value = 1000; + i++; + + info->props[i].name = MakeAtom("RAW_POINT_SIZE", 14, TRUE); + info->props[i].value = (long)(72270.0 / (double)vals->y + .5); + i++; + + if(!face->bitmap) { + info->props[i].name = MakeAtom("RAW_AVERAGE_WIDTH", 17, TRUE); + info->props[i].value = rawAverageWidth; + i++; + } + + if ( font_properties ) { + info->props[i].name = MakeAtom("FONT_ASCENT", 11, TRUE); + info->props[i].value = info->fontAscent; + i++; + } + + if(!face->bitmap) { + info->props[i].name = MakeAtom("RAW_ASCENT", 10, TRUE); + info->props[i].value = + ((double)face->face->ascender/(double)upm*1000.0); + i++; + } + + if ( font_properties ) { + info->props[i].name = MakeAtom("FONT_DESCENT", 12, TRUE); + info->props[i].value = info->fontDescent; + i++; + } + + if(!face->bitmap) { + info->props[i].name = MakeAtom("RAW_DESCENT", 11, TRUE); + info->props[i].value = + -((double)face->face->descender/(double)upm*1000.0); + i++; + } + + j = FTGetEnglishName(face->face, TT_NAME_ID_COPYRIGHT, + val, MAXFONTNAMELEN); + vp = val; + if (j < 0) { + if(t1info && t1info->notice) { + vp = t1info->notice; + j = strlen(vp); + } + } + if(j > 0) { + info->props[i].name = MakeAtom("COPYRIGHT", 9, TRUE); + info->props[i].value = MakeAtom(vp, j, TRUE); + info->isStringProp[i] = 1; + i++; + } + + j = FTGetEnglishName(face->face, TT_NAME_ID_FULL_NAME, + val, MAXFONTNAMELEN); + vp = val; + if (j < 0) { + if(t1info && t1info->full_name) { + vp = t1info->full_name; + j = strlen(vp); + } + } + if(j > 0) { + info->props[i].name = MakeAtom("FACE_NAME", 9, TRUE); + info->props[i].value = MakeAtom(vp, j, TRUE); + info->isStringProp[i] = 1; + i++; + } + + vp = (char *)FT_Get_Postscript_Name(face->face); + if (vp) { + j = strlen(vp); + } else { + j = -1; + } + if (j < 0) { + j = FTGetEnglishName(face->face, TT_NAME_ID_PS_NAME, + val, MAXFONTNAMELEN); + vp = val; + } + if (j < 0) { + if(t1info && t1info->full_name) { + vp = t1info->full_name; + j = strlen(vp); + } + } + if(j > 0) { + info->props[i].name = MakeAtom("_ADOBE_POSTSCRIPT_FONTNAME", 26, TRUE); + info->props[i].value = MakeAtom(vp, j, TRUE); + info->isStringProp[i] = 1; + i++; + } + + /* These macros handle the case of a diagonal matrix. They convert + FUnits into pixels. */ +#define TRANSFORM_FUNITS_X(xval) \ + ((int) \ + floor( ((double)(xval)/(double)upm) * (double)vals->pixel_matrix[0] + 0.5 ) ) + +#define TRANSFORM_FUNITS_Y(yval) \ + ((int) \ + floor( ((double)(yval)/(double)upm) * (double)vals->pixel_matrix[3] + 0.5 ) ) + + /* In what follows, we assume the matrix is diagonal. In the rare + case when it is not, the values will be somewhat wrong. */ + + if( font_properties && os2 ) { + info->props[i].name = MakeAtom("SUBSCRIPT_SIZE",14,TRUE); + info->props[i].value = + TRANSFORM_FUNITS_Y(os2->ySubscriptYSize); + i++; + info->props[i].name = MakeAtom("SUBSCRIPT_X",11,TRUE); + info->props[i].value = + TRANSFORM_FUNITS_X(os2->ySubscriptXOffset); + i++; + info->props[i].name = MakeAtom("SUBSCRIPT_Y",11,TRUE); + info->props[i].value = + TRANSFORM_FUNITS_Y(os2->ySubscriptYOffset); + i++; + info->props[i].name = MakeAtom("SUPERSCRIPT_SIZE",16,TRUE); + info->props[i].value = + TRANSFORM_FUNITS_Y(os2->ySuperscriptYSize); + i++; + info->props[i].name = MakeAtom("SUPERSCRIPT_X",13,TRUE); + info->props[i].value = + TRANSFORM_FUNITS_X(os2->ySuperscriptXOffset); + i++; + info->props[i].name = MakeAtom("SUPERSCRIPT_Y",13,TRUE); + info->props[i].value = + TRANSFORM_FUNITS_Y(os2->ySuperscriptYOffset); + i++; + } + + if( font_properties && (post || t1info) ) { + int underlinePosition, underlineThickness; + + /* Raw underlineposition counts upwards, + but UNDERLINE_POSITION counts downwards. */ + if(post) { + underlinePosition = TRANSFORM_FUNITS_Y(-post->underlinePosition); + underlineThickness = TRANSFORM_FUNITS_Y(post->underlineThickness); + } else { + underlinePosition = + TRANSFORM_FUNITS_Y(-t1info->underline_position); + underlineThickness = + TRANSFORM_FUNITS_Y(t1info->underline_thickness); + } + if(underlineThickness <= 0) + underlineThickness = 1; + + info->props[i].name = MakeAtom("UNDERLINE_THICKNESS",19,TRUE); + info->props[i].value = underlineThickness; + i++; + + info->props[i].name = MakeAtom("UNDERLINE_POSITION",18,TRUE); + + info->props[i].value = underlinePosition; + + i++; + + /* The italic angle is often unreliable for Type 1 fonts */ + if(post && trans->matrix.xx == trans->matrix.yy) { + info->props[i].name = MakeAtom("ITALIC_ANGLE",12,TRUE); + info->props[i].value = + /* Convert from TT_Fixed to + 64th of a degree counterclockwise from 3 o'clock */ + 90*64+(post->italicAngle >> 10); + i++; + } +#undef TRANSFORM_FUNITS_X +#undef TRANSFORM_FUNITS_Y + } + + info->props[i].name = MakeAtom("FONT_TYPE", 9, TRUE); + vp = (char *)FT_Get_X11_Font_Format(face->face); + info->props[i].value = MakeAtom(vp, strlen(vp), TRUE); + info->isStringProp[i] = 1; + i++; + + info->props[i].name = MakeAtom("RASTERIZER_NAME", 15, TRUE); + info->props[i].value = MakeAtom("FreeType", 10, TRUE); + info->isStringProp[i] = 1; + i++; + + info->nprops = i; + return Successful; +} + +static int +ft_get_index(unsigned code, FTFontPtr font, unsigned *idx) +{ + + /* As a special case, we pass 0 even when it is not in the ranges; + this will allow for the default glyph, which should exist in any + TrueType font. */ + + /* This is not required... + if(code > 0 && font->nranges) { + int i; + for(i = 0; i < font->nranges; i++) + if((code >= + font->ranges[i].min_char_low+ + (font->ranges[i].min_char_high<<8)) && + (code <= + font->ranges[i].max_char_low + + (font->ranges[i].max_char_high<<8))) + break; + if(i == font->nranges) { + *idx = font->zero_idx; + return -1; + } + } + */ + if( font->info ) { + if( !( font->info->firstCol <= (code & 0x000ff) && + (code & 0x000ff) <= font->info->lastCol && + font->info->firstRow <= (code >> 8) && + (code >> 8) <= font->info->lastRow ) ) { + *idx = font->zero_idx; + /* Error: The code has not been parsed in ft_compute_bounds()! + We should not return any metrics. */ + return -1; + } + } + + *idx = FTRemap(font->instance->face->face, &font->mapping, code); + + return 0; +} + +static int +FreeTypeFontGetGlyph(unsigned code, int flags, CharInfoPtr *g, FTFontPtr font) +{ + unsigned idx = 0; + int xrc; + +#ifdef X_ACCEPTS_NO_SUCH_CHAR + if( ft_get_index(code,font,&idx) || idx == 0 || idx == font->zero_idx ) { + *g = NULL; + flags &= ~FT_FORCE_CONSTANT_SPACING; + /* if( font->instance->spacing != FT_CHARCELL ) */ + return Successful; + } +#else + if( ft_get_index(code,font,&idx) ) { + /* The code has not been parsed! */ + *g = NULL; + flags &= ~FT_FORCE_CONSTANT_SPACING; + } +#endif + + xrc = FreeTypeInstanceGetGlyph(idx, flags, g, font->instance); + if( xrc == Successful && *g != NULL ) + return Successful; + if( font->zero_idx != idx ) { + xrc = FreeTypeInstanceGetGlyph(font->zero_idx, flags, g, font->instance); + if( xrc == Successful && *g != NULL ) + return Successful; + } + return FreeTypeInstanceGetGlyph(font->zero_idx, flags|FT_GET_DUMMY, g, font->instance); +} + +static int +FreeTypeFontGetGlyphMetrics(unsigned code, int flags, xCharInfo **metrics, FTFontPtr font) +{ + unsigned idx = 0; + int xrc; + +#ifdef X_ACCEPTS_NO_SUCH_CHAR + if ( ft_get_index(code,font,&idx) || idx == 0 || idx == font->zero_idx ) { + *metrics = NULL; + flags &= ~FT_FORCE_CONSTANT_SPACING; + /* if( font->instance->spacing != FT_CHARCELL ) */ + return Successful; + } +#else + if ( ft_get_index(code,font,&idx) || idx == 0 || idx == font->zero_idx ) { + /* The code has not been parsed! */ + *metrics = NULL; + flags &= ~FT_FORCE_CONSTANT_SPACING; + } +#endif + + xrc = FreeTypeInstanceGetGlyphMetrics(idx, flags, metrics, font->instance); + if( xrc == Successful && *metrics != NULL ) + return Successful; + if( font->zero_idx != idx ) { + xrc = FreeTypeInstanceGetGlyphMetrics(font->zero_idx, flags, + metrics, font->instance); + if( xrc == Successful && *metrics != NULL ) + return Successful; + } + return FreeTypeInstanceGetGlyphMetrics(font->zero_idx, flags|FT_GET_DUMMY, metrics, font->instance); +} + +/* + * restrict code range + * + * boolean for the numeric zone: + * results = results & (ranges[0] | ranges[1] | ... ranges[nranges-1]) + */ + +static void +restrict_code_range(unsigned short *refFirstCol, + unsigned short *refFirstRow, + unsigned short *refLastCol, + unsigned short *refLastRow, + fsRange const *ranges, int nRanges) +{ + if (nRanges) { + int minCol = 256, minRow = 256, maxCol = -1, maxRow = -1; + fsRange const *r = ranges; + int i; + + for (i=0; imin_char_high != r->max_char_high) { + minCol = 0x00; + maxCol = 0xff; + } else { + if (minCol > r->min_char_low) + minCol = r->min_char_low; + if (maxCol < r->max_char_low) + maxCol = r->max_char_low; + } + if (minRow > r->min_char_high) + minRow = r->min_char_high; + if (maxRow < r->max_char_high) + maxRow = r->max_char_high; + r++; + } + + if (minCol > *refLastCol) + *refFirstCol = *refLastCol; + else if (minCol > *refFirstCol) + *refFirstCol = minCol; + + if (maxCol < *refFirstCol) + *refLastCol = *refFirstCol; + else if (maxCol < *refLastCol) + *refLastCol = maxCol; + + if (minRow > *refLastRow) { + *refFirstRow = *refLastRow; + *refFirstCol = *refLastCol; + } else if (minRow > *refFirstRow) + *refFirstRow = minRow; + + if (maxRow < *refFirstRow) { + *refLastRow = *refFirstRow; + *refLastCol = *refFirstCol; + } else if (maxRow < *refLastRow) + *refLastRow = maxRow; + } +} + + +static int +restrict_code_range_by_str(int count,unsigned short *refFirstCol, + unsigned short *refFirstRow, + unsigned short *refLastCol, + unsigned short *refLastRow, + char const *str) +{ + int nRanges = 0; + int result = 0; + fsRange *ranges = NULL; + char const *p, *q; + + p = q = str; + for (;;) { + int minpoint=0, maxpoint=65535; + long val; + + /* skip comma and/or space */ + while (',' == *p || isspace(*p)) + p++; + + /* begin point */ + if ('-' != *p) { + val = strtol(p, (char **)&q, 0); + if (p == q) + /* end or illegal */ + break; + if (val<0 || val>65535) { + /* out of zone */ + break; + } + minpoint = val; + p=q; + } + + /* skip space */ + while (isspace(*p)) + p++; + + if (',' != *p && '\0' != *p) { + /* contiune */ + if ('-' == *p) + /* hyphon */ + p++; + else + /* end or illegal */ + break; + + /* skip space */ + while (isspace(*p)) + p++; + + val = strtol(p, (char **)&q, 0); + if (p != q) { + if (val<0 || val>65535) + break; + maxpoint = val; + } else if (',' != *p && '\0' != *p) + /* end or illegal */ + break; + p=q; + } else + /* comma - single code */ + maxpoint = minpoint; + + if ( count <= 0 && minpoint>maxpoint ) { + int tmp; + tmp = minpoint; + minpoint = maxpoint; + maxpoint = tmp; + } + + /* add range */ +#if 0 + fprintf(stderr, "zone: 0x%04X - 0x%04X\n", minpoint, maxpoint); + fflush(stderr); +#endif + nRanges++; + ranges = realloc(ranges, nRanges*sizeof(*ranges)); + if (NULL == ranges) + break; + { + fsRange *r = ranges+nRanges-1; + + r->min_char_low = minpoint & 0xff; + r->max_char_low = maxpoint & 0xff; + r->min_char_high = (minpoint>>8) & 0xff; + r->max_char_high = (maxpoint>>8) & 0xff; + } + } + + if (ranges) { + if ( count <= 0 ) { + restrict_code_range(refFirstCol, refFirstRow, refLastCol, refLastRow, + ranges, nRanges); + } + else { + int i; + fsRange *r; + for ( i=0 ; imin_char_low; + refLastCol[i] = r->max_char_low; + refFirstRow[i] = r->min_char_high; + refLastRow[i] = r->max_char_high; + } + result=i; + } + free(ranges); + } + return result; +} + +/* *face_number and *spacing are initialized but *load_flags is NOT. */ +static int +FreeTypeSetUpTTCap( char *fileName, FontScalablePtr vals, + char **dynStrRealFileName, char **dynStrFTFileName, + struct TTCapInfo *ret, int *face_number, FT_Int32 *load_flags, + int *spacing, Bool *font_properties, char **dynStrTTCapCodeRange ) +{ + int result = Successful; + SDynPropRecValList listPropRecVal; + SPropRecValContainer contRecValue; + Bool hinting=True; + Bool isEmbeddedBitmap = True; + Bool alwaysEmbeddedBitmap = False; + int pixel = vals->pixel; + + *font_properties=True; + *dynStrRealFileName=NULL; + *dynStrFTFileName=NULL; + *dynStrTTCapCodeRange=NULL; + + if (SPropRecValList_new(&listPropRecVal)) { + return AllocError; + } + + { + int len = strlen(fileName); + char *capHead = NULL; + { + /* font cap */ + char *p1=NULL, *p2=NULL; + + p1=strrchr(fileName, '/'); + if ( p1 == NULL ) p1 = fileName; + else p1++; + if (NULL != (p2=strrchr(p1, ':'))) { + /* colon exist in the right side of slash. */ + int dirLen = p1-fileName; + int baseLen = fileName+len - p2 -1; + + *dynStrRealFileName = malloc(dirLen+baseLen+1); + if( *dynStrRealFileName == NULL ) { + result = AllocError; + goto quit; + } + if ( 0 < dirLen ) + memcpy(*dynStrRealFileName, fileName, dirLen); + strcpy(*dynStrRealFileName+dirLen, p2+1); + capHead = p1; + } else { + *dynStrRealFileName = xstrdup(fileName); + if( *dynStrRealFileName == NULL ) { + result = AllocError; + goto quit; + } + } + } + + /* font cap */ + if (capHead) { + if (SPropRecValList_add_by_font_cap(&listPropRecVal, + capHead)) { + result = BadFontPath; + goto quit; + } + } + } + + *face_number=0; + *spacing=0; + ret->autoItalic=0.0; + ret->scaleWidth=1.0; + ret->scaleBBoxWidth = 1.0; + ret->scaleBBoxHeight = 1.0; + ret->doubleStrikeShift = 1; + ret->adjustBBoxWidthByPixel = 0; + ret->adjustLeftSideBearingByPixel = 0; + ret->adjustRightSideBearingByPixel = 0; + ret->flags = 0; + ret->scaleBitmap = 0.0; + ret->forceConstantSpacingBegin = -1; + ret->forceConstantSpacingEnd = -1; + ret->force_c_representative_metrics_char_code = -2; + ret->force_c_scale_b_box_width = 1.0; + ret->force_c_scale_b_box_height = 1.0; + ret->force_c_adjust_width_by_pixel = 0; + ret->force_c_adjust_lsb_by_pixel = 0; + ret->force_c_adjust_rsb_by_pixel = 0; + ret->force_c_scale_lsb = 0.0; + ret->force_c_scale_rsb = 1.0; + /* */ + ret->vl_slant=0; + ret->lsbShiftOfBitmapAutoItalic=0; + ret->rsbShiftOfBitmapAutoItalic=0; + /* face number */ + { + char *beginptr=NULL,*endptr; + if ( SPropRecValList_search_record(&listPropRecVal, + &contRecValue, + "FaceNumber")) { + int lv; + beginptr = SPropContainer_value_str(contRecValue); + lv=strtol(beginptr, &endptr, 10); + if ( *beginptr != '\0' && *endptr == '\0' ) { + if ( 0 < lv ) *face_number = lv; + } + } + if( beginptr && 0 < *face_number ) { + char *slash; + *dynStrFTFileName = /* add -> ':'+strlen0+':'+strlen1+'\0' */ + malloc(1+strlen(beginptr)+1+strlen(*dynStrRealFileName)+1); + if( *dynStrFTFileName == NULL ){ + result = AllocError; + goto quit; + } + **dynStrFTFileName = '\0'; + slash = strrchr(*dynStrRealFileName,'/'); + if( slash ) { + char *p; + strcat(*dynStrFTFileName,*dynStrRealFileName); + p = strrchr(*dynStrFTFileName,'/'); + p[1] = '\0'; + strcat(*dynStrFTFileName,":"); + strcat(*dynStrFTFileName,beginptr); + strcat(*dynStrFTFileName,":"); + strcat(*dynStrFTFileName,slash+1); + } + else{ + strcat(*dynStrFTFileName,":"); + strcat(*dynStrFTFileName,beginptr); + strcat(*dynStrFTFileName,":"); + strcat(*dynStrFTFileName,*dynStrRealFileName); + } + } + else{ + *dynStrFTFileName = malloc(strlen(*dynStrRealFileName)+1); + if( *dynStrFTFileName == NULL ){ + result = AllocError; + goto quit; + } + **dynStrFTFileName = '\0'; + strcat(*dynStrFTFileName,*dynStrRealFileName); + } + } + /* + fprintf(stderr,"[Filename:%s]\n",fileName); + fprintf(stderr,"[RealFilename:%s]\n",*dynStrRealFileName); + fprintf(stderr,"[FTFilename:%s]\n",*dynStrFTFileName); + */ + /* slant control */ + if (SPropRecValList_search_record(&listPropRecVal, + &contRecValue, + "AutoItalic")) + ret->autoItalic = SPropContainer_value_dbl(contRecValue); + /* hinting control */ + if (SPropRecValList_search_record(&listPropRecVal, + &contRecValue, + "Hinting")) + hinting = SPropContainer_value_bool(contRecValue); + /* scaling */ + if (SPropRecValList_search_record(&listPropRecVal, + &contRecValue, + "ScaleWidth")) { + ret->scaleWidth = SPropContainer_value_dbl(contRecValue); + if (ret->scaleWidth<=0.0) { + fprintf(stderr, "ScaleWitdh needs plus.\n"); + result = BadFontName; + goto quit; + } + } + /* bbox adjustment */ + if (SPropRecValList_search_record(&listPropRecVal, + &contRecValue, + "ScaleBBoxWidth")) { + /* Scaling to Bounding Box Width */ + int lv; + char *endptr,*beginptr; + double v,scaleBBoxWidth=1.0,scaleBBoxHeight=1.0; + beginptr = SPropContainer_value_str(contRecValue); + do { + if ( strlen(beginptr) < 1 ) break; + v=strtod(beginptr, &endptr); + if ( endptr!=beginptr ) { + scaleBBoxWidth = v; + } + if ( *endptr != ';' && *endptr != ',' ) break; + if ( *endptr == ',' ) { + beginptr=endptr+1; + v=strtod(beginptr, &endptr); + if ( endptr!=beginptr ) { + scaleBBoxHeight = v; + } + } + if ( *endptr != ';' && *endptr != ',' ) break; + beginptr=endptr+1; + lv=strtol(beginptr, &endptr, 10); + if ( endptr!=beginptr ) { + ret->adjustBBoxWidthByPixel = lv; + } + if ( *endptr != ',' ) break; + beginptr=endptr+1; + lv=strtol(beginptr, &endptr, 10); + if ( endptr!=beginptr ) { + ret->adjustLeftSideBearingByPixel = lv; + } + if ( *endptr != ',' ) break; + beginptr=endptr+1; + lv=strtol(beginptr, &endptr, 10); + if ( endptr!=beginptr ) { + ret->adjustRightSideBearingByPixel = lv; + } + } while ( 0 ); + if (scaleBBoxWidth<=0.0) { + fprintf(stderr, "ScaleBBoxWitdh needs plus.\n"); + result = BadFontName; + goto quit; + } + if (scaleBBoxHeight<=0.0) { + fprintf(stderr, "ScaleBBoxHeight needs plus.\n"); + result = BadFontName; + goto quit; + } + ret->scaleBBoxWidth = scaleBBoxWidth; + ret->scaleBBoxHeight = scaleBBoxHeight; + } + /* spacing */ + if (SPropRecValList_search_record(&listPropRecVal, + &contRecValue, + "ForceSpacing")) { + char *strSpace = SPropContainer_value_str(contRecValue); + Bool err = False; + if (1 != strlen(strSpace)) + err = True; + else + switch (strSpace[0]) { + case 'M': + ret->flags |= TTCAP_MONO_CENTER; + *spacing = 'm'; + break; + case 'm': + case 'p': + case 'c': + *spacing = strSpace[0]; + break; + default: + err = True; + } + if (err) { + result = BadFontName; + goto quit; + } + } + /* doube striking */ + if (SPropRecValList_search_record(&listPropRecVal, + &contRecValue, + "DoubleStrike")) { + /* Set or Reset Auto Bold Flag */ + char *strDoubleStrike = SPropContainer_value_str(contRecValue); + Bool err = False; + if ( 0 < strlen(strDoubleStrike) ) { + switch (strDoubleStrike[0]) { + case 'm': + case 'M': + case 'l': + case 'L': + ret->flags |= TTCAP_DOUBLE_STRIKE; + ret->flags |= TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT; + break; + case 'y': + case 'Y': + ret->flags |= TTCAP_DOUBLE_STRIKE; + break; + case 'n': + case 'N': + ret->flags &= ~TTCAP_DOUBLE_STRIKE; + ret->flags &= ~TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT; + ret->flags &= ~TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH; + break; + default: + err = True; + } + if ( err != True ) { + if ( strDoubleStrike[1] ) { + switch (strDoubleStrike[1]) { + case 'b': + case 'B': + case 'p': + case 'P': + case 'y': + case 'Y': + ret->flags |= TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH; + break; + default: + break; + } + } + do { + char *comma_ptr=strchr(strDoubleStrike,';'); + if ( !comma_ptr ) comma_ptr=strchr(strDoubleStrike,','); + if ( !comma_ptr ) break; + if ( comma_ptr[1] ) { + char *endptr; + int mkboldMaxPixel; + mkboldMaxPixel=strtol(comma_ptr+1, &endptr, 10); + if ( endptr != comma_ptr+1 && mkboldMaxPixel <= pixel ) { + ret->flags &= ~TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT; + } + } + comma_ptr=strchr(comma_ptr+1,','); + if ( !comma_ptr ) break; + if ( comma_ptr[1] ) { + char *endptr; + int max_pixel; + max_pixel=strtol(comma_ptr+1, &endptr, 10); + if ( endptr != comma_ptr+1 && max_pixel <= pixel ) { + if( ret->flags & TTCAP_DOUBLE_STRIKE ) + ret->doubleStrikeShift += pixel / max_pixel; + } + } + } while(0); + } + } + else + err = True; + if (err) { + result = BadFontName; + goto quit; + } + } + /* very lazy metrics */ + if (SPropRecValList_search_record(&listPropRecVal, + &contRecValue, + "VeryLazyMetrics")){ + Bool isVeryLazy = SPropContainer_value_bool(contRecValue); + ret->flags |= TTCAP_DISABLE_DEFAULT_VERY_LAZY; + if( isVeryLazy == True ) + ret->flags |= TTCAP_IS_VERY_LAZY; + else + ret->flags &= ~TTCAP_IS_VERY_LAZY; + } + /* embedded bitmap */ + if (SPropRecValList_search_record(&listPropRecVal, + &contRecValue, + "EmbeddedBitmap")) { + char *strEmbeddedBitmap = SPropContainer_value_str(contRecValue); + Bool err = False; + if ( 1 == strlen(strEmbeddedBitmap) ) { + switch (strEmbeddedBitmap[0]) { + case 'y': + case 'Y': + isEmbeddedBitmap = True; + alwaysEmbeddedBitmap = True; + break; + case 'u': + case 'U': + isEmbeddedBitmap = True; + alwaysEmbeddedBitmap = False; + break; + case 'n': + case 'N': + isEmbeddedBitmap = False; + break; + default: + err = True; + } + } + else + err = True; + if (err) { + result = BadFontName; + goto quit; + } + } + /* scale bitmap */ + if((ret->flags & TTCAP_IS_VERY_LAZY) && + SPropRecValList_search_record(&listPropRecVal, + &contRecValue, + "VeryLazyBitmapWidthScale")) { + /* Scaling to Bitmap Bounding Box Width */ + double scaleBitmapWidth = SPropContainer_value_dbl(contRecValue); + + fprintf(stderr, "Warning: `bs' option is not required in X-TT version 2.\n"); +#if 0 + if (scaleBitmapWidth<=0.0) { + fprintf(stderr, "ScaleBitmapWitdh needs plus.\n"); + result = BadFontName; + goto quit; + } +#endif + ret->scaleBitmap = scaleBitmapWidth; + } + /* restriction of the code range */ + if (SPropRecValList_search_record(&listPropRecVal, + &contRecValue, + "CodeRange")) { + *dynStrTTCapCodeRange = xstrdup(SPropContainer_value_str(contRecValue)); + if( *dynStrTTCapCodeRange == NULL ) { + result = AllocError; + goto quit; + } + } + /* forceConstantSpacing{Begin,End} */ + if ( 1 /* ft->spacing == 'p' */ ){ + unsigned short first_col=0,last_col=0x00ff; + unsigned short first_row=0,last_row=0x00ff; + if (SPropRecValList_search_record(&listPropRecVal, + &contRecValue, + "ForceConstantSpacingCodeRange")) { + if ( restrict_code_range_by_str(1,&first_col, &first_row, + &last_col, &last_row, + SPropContainer_value_str(contRecValue)) == 1 ) { + ret->forceConstantSpacingBegin = (int)( first_row<<8 | first_col ); + ret->forceConstantSpacingEnd = (int)( last_row<<8 | last_col ); + if ( ret->forceConstantSpacingBegin <= ret->forceConstantSpacingEnd ) + ret->flags &= ~TTCAP_FORCE_C_OUTSIDE; + else ret->flags |= TTCAP_FORCE_C_OUTSIDE; + } + } + } + /* */ + if ( 1 ){ + unsigned short first_col=0, last_col=0x0ff; + unsigned short first_row=0, last_row=0x0ff; + if ( SPropRecValList_search_record(&listPropRecVal, + &contRecValue, + "ForceConstantSpacingMetrics")) { + char *strMetrics; + strMetrics = SPropContainer_value_str(contRecValue); + if ( strMetrics ) { + char *comma_ptr,*period_ptr,*semic_ptr; + semic_ptr=strchr(strMetrics,';'); + comma_ptr=strchr(strMetrics,','); + period_ptr=strchr(strMetrics,'.'); + if ( semic_ptr && comma_ptr ) + if ( semic_ptr < comma_ptr ) comma_ptr=NULL; + if ( semic_ptr && period_ptr ) + if ( semic_ptr < period_ptr ) period_ptr=NULL; + if ( !comma_ptr && !period_ptr && strMetrics != semic_ptr ) { + if ( restrict_code_range_by_str(1,&first_col, &first_row, + &last_col, &last_row, + SPropContainer_value_str(contRecValue)) == 1 ) { + ret->force_c_representative_metrics_char_code = + (int)( first_row<<8 | first_col ); + } + } + else { + double v; + char *endptr,*beginptr=strMetrics; + do { + v=strtod(beginptr, &endptr); + if ( endptr!=beginptr ) { + ret->force_c_scale_b_box_width = v; + } + if ( *endptr != ',' ) break; + beginptr=endptr+1; + v=strtod(beginptr, &endptr); + if ( endptr!=beginptr ) { + ret->force_c_scale_lsb = v; + ret->flags |= TTCAP_FORCE_C_LSB_FLAG; + } + if ( *endptr != ',' ) break; + beginptr=endptr+1; + v=strtod(beginptr, &endptr); + if ( endptr!=beginptr ) { + ret->force_c_scale_rsb = v; + ret->flags |= TTCAP_FORCE_C_RSB_FLAG; + } + if ( *endptr != ',' ) break; + beginptr=endptr+1; + v=strtod(beginptr, &endptr); + if ( endptr!=beginptr ) { + ret->force_c_scale_b_box_height = v; + } + } while (0); + } + if ( semic_ptr ) { + int lv; + char *endptr,*beginptr=semic_ptr+1; + do { + lv=strtol(beginptr, &endptr, 10); + if ( endptr!=beginptr ) { + ret->force_c_adjust_width_by_pixel=lv; + } + if ( *endptr != ',' ) break; + beginptr=endptr+1; + lv=strtol(beginptr, &endptr, 10); + if ( endptr!=beginptr ) { + ret->force_c_adjust_lsb_by_pixel=lv; + } + if ( *endptr != ',' ) break; + beginptr=endptr+1; + lv=strtol(beginptr, &endptr, 10); + if ( endptr!=beginptr ) { + ret->force_c_adjust_rsb_by_pixel=lv; + } + } while (0); + } + } + } + } + + if (SPropRecValList_search_record(&listPropRecVal, + &contRecValue, + "FontProperties")) { + /* Set or Reset the Flag of FontProperties */ + *font_properties=SPropContainer_value_bool(contRecValue); + } + + ret->force_c_scale_b_box_width *= ret->scaleBBoxWidth; + ret->force_c_scale_b_box_height *= ret->scaleBBoxHeight; + + ret->force_c_scale_b_box_width *= ret->scaleWidth; + ret->scaleBBoxWidth *= ret->scaleWidth; + + ret->force_c_adjust_rsb_by_pixel += ret->adjustRightSideBearingByPixel; + ret->force_c_adjust_lsb_by_pixel += ret->adjustLeftSideBearingByPixel; + + /* scaleWidth, scaleBBoxWidth, force_c_scale_b_box_width, force_c_scale_b_box_width */ + + /* by TTCap */ + if( hinting == False ) *load_flags |= FT_LOAD_NO_HINTING; + if( isEmbeddedBitmap == False ) *load_flags |= FT_LOAD_NO_BITMAP; + if( ret->autoItalic != 0 && alwaysEmbeddedBitmap == False ) + *load_flags |= FT_LOAD_NO_BITMAP; + + quit: + return result; +} + +static int +ft_get_trans_from_vals( FontScalablePtr vals, FTNormalisedTransformationPtr trans ) +{ + /* Compute the transformation matrix. We use floating-point + arithmetic for simplicity */ + + trans->xres = vals->x; + trans->yres = vals->y; + + /* This value cannot be 0. */ + trans->scale = hypot(vals->point_matrix[2], vals->point_matrix[3]); + trans->nonIdentity = 0; + + /* Try to round stuff. We want approximate zeros to be exact zeros, + and if the elements on the diagonal are approximately equal, we + want them equal. We do this to avoid breaking hinting. */ + if(DIFFER(vals->point_matrix[0], vals->point_matrix[3])) { + trans->nonIdentity = 1; + trans->matrix.xx = + (int)((vals->point_matrix[0]*(double)TWO_SIXTEENTH)/trans->scale); + trans->matrix.yy = + (int)((vals->point_matrix[3]*(double)TWO_SIXTEENTH)/trans->scale); + } else { + trans->matrix.xx = trans->matrix.yy = + ((vals->point_matrix[0] + vals->point_matrix[3])/2* + (double)TWO_SIXTEENTH)/trans->scale; + } + + if(DIFFER0(vals->point_matrix[1], trans->scale)) { + trans->matrix.yx = + (int)((vals->point_matrix[1]*(double)TWO_SIXTEENTH)/trans->scale); + trans->nonIdentity = 1; + } else + trans->matrix.yx = 0; + + if(DIFFER0(vals->point_matrix[2], trans->scale)) { + trans->matrix.xy = + (int)((vals->point_matrix[2]*(double)TWO_SIXTEENTH)/trans->scale); + trans->nonIdentity = 1; + } else + trans->matrix.xy=0; + return 0; +} + + +static int +is_fixed_width(FT_Face face) +{ + PS_FontInfoRec t1info_rec; + int ftrc; + + if(FT_IS_FIXED_WIDTH(face)) { + return 1; + } + + ftrc = FT_Get_PS_Font_Info(face, &t1info_rec); + if(ftrc == 0 && t1info_rec.is_fixed_pitch) { + return 1; + } + + return 0; +} + +static int +FreeTypeLoadFont(FTFontPtr font, FontInfoPtr info, FTFacePtr face, + char *FTFileName, FontScalablePtr vals, FontEntryPtr entry, + FontBitmapFormatPtr bmfmt, FT_Int32 load_flags, + struct TTCapInfo *tmp_ttcap, char *dynStrTTCapCodeRange, + int ttcap_spacing ) +{ + int xrc; + FTNormalisedTransformationRec trans; + int spacing, actual_spacing, zero_code; + long lastCode, firstCode; + TT_Postscript *post; + + ft_get_trans_from_vals(vals,&trans); + + /* Check for charcell in XLFD */ + spacing = FT_PROPORTIONAL; + if(entry->name.ndashes == 14) { + char *p; + int dashes = 0; + for(p = entry->name.name; + p <= entry->name.name + entry->name.length - 2; + p++) { + if(*p == '-') { + dashes++; + if(dashes == 11) { + if(p[1]=='c' && p[2]=='-') + spacing=FT_CHARCELL; + else if(p[1]=='m' && p[2]=='-') + spacing=FT_MONOSPACED; + break; + } + } + } + } + /* by TTCap */ + if( ttcap_spacing != 0 ) { + if( ttcap_spacing == 'c' ) spacing=FT_CHARCELL; + else if( ttcap_spacing == 'm' ) spacing=FT_MONOSPACED; + else spacing=FT_PROPORTIONAL; + } + + actual_spacing = spacing; + if( spacing == FT_PROPORTIONAL ) { + if( is_fixed_width(face->face) ) + actual_spacing = FT_MONOSPACED; + } + + if(entry->name.ndashes == 14) { + xrc = FTPickMapping(entry->name.name, entry->name.length, FTFileName, + face->face, &font->mapping); + if (xrc != Successful) + return xrc; + } else { + xrc = FTPickMapping(0, 0, FTFileName, + face->face, &font->mapping); + if (xrc != Successful) + return xrc; + } + + font->nranges = vals->nranges; + font->ranges = 0; + if(font->nranges) { + font->ranges = malloc(vals->nranges*sizeof(fsRange)); + if(font->ranges == NULL) + return AllocError; + memcpy((char*)font->ranges, (char*)vals->ranges, + vals->nranges*sizeof(fsRange)); + } + + zero_code=-1; + if(info) { + firstCode = 0; + lastCode = 0xFFFFL; + if(!font->mapping.mapping || + font->mapping.mapping->encoding->row_size == 0) { + /* linear indexing */ + lastCode=MIN(lastCode, + font->mapping.mapping ? + font->mapping.mapping->encoding->size-1 : + 0xFF); + if(font->mapping.mapping && font->mapping.mapping->encoding->first) + firstCode = font->mapping.mapping->encoding->first; + info->firstRow = firstCode/0x100; + info->lastRow = lastCode/0x100; + info->firstCol = + (info->firstRow || info->lastRow) ? 0 : (firstCode & 0xFF); + info->lastCol = info->lastRow ? 0xFF : (lastCode & 0xFF); + if ( firstCode == 0 ) zero_code=0; + } else { + /* matrix indexing */ + info->firstRow = font->mapping.mapping->encoding->first; + info->lastRow = MIN(font->mapping.mapping->encoding->size-1, + lastCode/0x100); + info->firstCol = font->mapping.mapping->encoding->first_col; + info->lastCol = MIN(font->mapping.mapping->encoding->row_size-1, + lastCode<0x100?lastCode:0xFF); + if( info->firstRow == 0 && info->firstCol == 0 ) zero_code=0; + } + + /* firstCode and lastCode are not valid in case of a matrix + encoding */ + + if( dynStrTTCapCodeRange ) { + restrict_code_range_by_str(0,&info->firstCol, &info->firstRow, + &info->lastCol, &info->lastRow, + dynStrTTCapCodeRange); + } + restrict_code_range(&info->firstCol, &info->firstRow, + &info->lastCol, &info->lastRow, + font->ranges, font->nranges); + } + font->info = info; + + /* zero code is frequently used. */ + if ( zero_code < 0 ) { + /* The fontenc should have the information of DefaultCh. + But we do not have such a information. + So we cannot but set 0. */ + font->zero_idx = 0; + } + else + font->zero_idx = FTRemap(face->face, + &font->mapping, zero_code); + + post = FT_Get_Sfnt_Table(face->face, ft_sfnt_post); + +#ifdef DEFAULT_VERY_LAZY + if( !( tmp_ttcap->flags & TTCAP_DISABLE_DEFAULT_VERY_LAZY ) ) + if( DEFAULT_VERY_LAZY <= 1 + info->lastRow - info->firstRow ) { + if( post ){ + tmp_ttcap->flags |= TTCAP_IS_VERY_LAZY; + } + } +#endif + /* We should always reset. */ + tmp_ttcap->flags &= ~TTCAP_DISABLE_DEFAULT_VERY_LAZY; + + if ( face->bitmap || actual_spacing == FT_CHARCELL ) + tmp_ttcap->flags &= ~TTCAP_IS_VERY_LAZY; + /* "vl=y" is available when TrueType or OpenType only */ + if ( !face->bitmap && !(FT_IS_SFNT( face->face )) ) + tmp_ttcap->flags &= ~TTCAP_IS_VERY_LAZY; + + if( post ) { + if( post->italicAngle != 0 ) + tmp_ttcap->vl_slant = -sin( (post->italicAngle/1024./5760.)*1.57079632679489661923 ); + /* fprintf(stderr,"angle=%g(%g)\n",tmp_ttcap->vl_slant,(post->italicAngle/1024./5760.)*90); */ + } + + xrc = FreeTypeOpenInstance(&font->instance, face, + FTFileName, &trans, actual_spacing, bmfmt, + tmp_ttcap, load_flags ); + return xrc; +} + +static void +adjust_min_max(xCharInfo *minc, xCharInfo *maxc, xCharInfo *tmp) +{ +#define MINMAX(field,ci) \ + if (minc->field > (ci)->field) \ + minc->field = (ci)->field; \ + if (maxc->field < (ci)->field) \ + maxc->field = (ci)->field; + + MINMAX(ascent, tmp); + MINMAX(descent, tmp); + MINMAX(leftSideBearing, tmp); + MINMAX(rightSideBearing, tmp); + MINMAX(characterWidth, tmp); + + if ((INT16)minc->attributes > (INT16)tmp->attributes) + minc->attributes = tmp->attributes; + if ((INT16)maxc->attributes < (INT16)tmp->attributes) + maxc->attributes = tmp->attributes; +#undef MINMAX +} + +static void +ft_compute_bounds(FTFontPtr font, FontInfoPtr pinfo, FontScalablePtr vals ) +{ + FTInstancePtr instance; + int row, col; + unsigned int c; + xCharInfo minchar, maxchar, *tmpchar = NULL; + int overlap, maxOverlap; + long swidth = 0; + long total_width = 0; + int num_cols, num_chars = 0; + int flags, skip_ok = 0; + int force_c_outside ; + + instance = font->instance; + force_c_outside = instance->ttcap.flags & TTCAP_FORCE_C_OUTSIDE; + + minchar.ascent = minchar.descent = + minchar.leftSideBearing = minchar.rightSideBearing = + minchar.characterWidth = minchar.attributes = 32767; + maxchar.ascent = maxchar.descent = + maxchar.leftSideBearing = maxchar.rightSideBearing = + maxchar.characterWidth = maxchar.attributes = -32767; + maxOverlap = -32767; + + /* Parse all glyphs */ + num_cols = 1 + pinfo->lastCol - pinfo->firstCol; + for (row = pinfo->firstRow; row <= pinfo->lastRow; row++) { + if ( skip_ok && tmpchar ) { + if ( !force_c_outside ) { + if ( instance->ttcap.forceConstantSpacingBegin < row<<8 + && row<<8 < (instance->ttcap.forceConstantSpacingEnd & 0x0ff00) ) { + if (tmpchar->characterWidth) { + num_chars += num_cols; + swidth += ABS(tmpchar->characterWidth)*num_cols; + total_width += tmpchar->characterWidth*num_cols; + continue; + } + } + else skip_ok=0; + } + else { /* for GB18030 proportional */ + if ( instance->ttcap.forceConstantSpacingBegin < row<<8 + || row<<8 < (instance->ttcap.forceConstantSpacingEnd & 0x0ff00) ) { + if (tmpchar->characterWidth) { + num_chars += num_cols; + swidth += ABS(tmpchar->characterWidth)*num_cols; + total_width += tmpchar->characterWidth*num_cols; + continue; + } + } + else skip_ok=0; + } + } + for (col = pinfo->firstCol; col <= pinfo->lastCol; col++) { + c = row<<8|col; + flags=0; + if ( !force_c_outside ) { + if ( c <= instance->ttcap.forceConstantSpacingEnd + && instance->ttcap.forceConstantSpacingBegin <= c ) + flags|=FT_FORCE_CONSTANT_SPACING; + } + else { /* for GB18030 proportional */ + if ( c <= instance->ttcap.forceConstantSpacingEnd + || instance->ttcap.forceConstantSpacingBegin <= c ) + flags|=FT_FORCE_CONSTANT_SPACING; + } +#if 0 + fprintf(stderr, "comp_bounds: %x ->", c); +#endif + if ( skip_ok == 0 || flags == 0 ){ + tmpchar=NULL; +#if 0 + fprintf(stderr, "%x\n", c); +#endif + if( FreeTypeFontGetGlyphMetrics(c, flags, &tmpchar, font) != Successful ) + continue; + } + if ( !tmpchar ) continue; + adjust_min_max(&minchar, &maxchar, tmpchar); + overlap = tmpchar->rightSideBearing - tmpchar->characterWidth; + if (maxOverlap < overlap) + maxOverlap = overlap; + + if (!tmpchar->characterWidth) + continue; + num_chars++; + swidth += ABS(tmpchar->characterWidth); + total_width += tmpchar->characterWidth; + + if ( flags & FT_FORCE_CONSTANT_SPACING ) skip_ok=1; + } + } + +#ifndef X_ACCEPTS_NO_SUCH_CHAR + /* Check code 0 */ + if( FreeTypeInstanceGetGlyphMetrics(font->zero_idx, 0, &tmpchar, font->instance) != Successful || tmpchar == NULL) + if( FreeTypeInstanceGetGlyphMetrics(font->zero_idx, FT_GET_DUMMY, &tmpchar, font->instance) != Successful ) + tmpchar = NULL; + if ( tmpchar ) { + adjust_min_max(&minchar, &maxchar, tmpchar); + overlap = tmpchar->rightSideBearing - tmpchar->characterWidth; + if (maxOverlap < overlap) + maxOverlap = overlap; + } +#endif + + /* AVERAGE_WIDTH ... 1/10 pixel unit */ + if (num_chars > 0) { + swidth = (swidth * 10.0 + num_chars / 2.0) / num_chars; + if (total_width < 0) + swidth = -swidth; + vals->width = swidth; + } else + vals->width = 0; + + /* + if (char_width.pixel) { + maxchar.characterWidth = char_width.pixel; + minchar.characterWidth = char_width.pixel; + } + */ + + pinfo->maxbounds = maxchar; + pinfo->minbounds = minchar; + pinfo->ink_maxbounds = maxchar; + pinfo->ink_minbounds = minchar; + pinfo->maxOverlap = maxOverlap; +} + +static int +compute_new_extents( FontScalablePtr vals, double scale, double lsb, double rsb, double desc, double asc, + int *lsb_result, int *rsb_result, int *desc_result, int *asc_result ) +{ +#define TRANSFORM_POINT(matrix, x, y, dest) \ + ((dest)[0] = (matrix)[0] * (x) + (matrix)[2] * (y), \ + (dest)[1] = (matrix)[1] * (x) + (matrix)[3] * (y)) + +#define CHECK_EXTENT(lsb, rsb, desc, asc, data) \ + ((lsb) > (data)[0] ? (lsb) = (data)[0] : 0 , \ + (rsb) < (data)[0] ? (rsb) = (data)[0] : 0, \ + (-desc) > (data)[1] ? (desc) = -(data)[1] : 0 , \ + (asc) < (data)[1] ? (asc) = (data)[1] : 0) + double newlsb, newrsb, newdesc, newasc; + double point[2]; + + /* Compute new extents for this glyph */ + TRANSFORM_POINT(vals->pixel_matrix, lsb, -desc, point); + newlsb = point[0]; + newrsb = newlsb; + newdesc = -point[1]; + newasc = -newdesc; + TRANSFORM_POINT(vals->pixel_matrix, lsb, asc, point); + CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); + TRANSFORM_POINT(vals->pixel_matrix, rsb, -desc, point); + CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); + TRANSFORM_POINT(vals->pixel_matrix, rsb, asc, point); + CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); + + /* ???: lsb = (int)floor(newlsb * scale); */ + *lsb_result = (int)floor(newlsb * scale + 0.5); + *rsb_result = (int)floor(newrsb * scale + 0.5); + *desc_result = (int)ceil(newdesc * scale - 0.5); + *asc_result = (int)floor(newasc * scale + 0.5); + + return 0; +#undef CHECK_EXTENT +#undef TRANSFORM_POINT +} + +static int +is_matrix_unit(FontScalablePtr vals) +{ + double base_size; + FT_Matrix m; + + base_size = hypot(vals->point_matrix[2], vals->point_matrix[3]); + + m.xx = vals->point_matrix[0] / base_size * 65536; + m.xy = vals->point_matrix[2] / base_size * 65536; + m.yx = vals->point_matrix[1] / base_size * 65536; + m.yy = vals->point_matrix[3] / base_size * 65536; + + return (m.xx == 65536) && (m.yx == 0) && + (m.xy == 0) && (m.yy == 65536); +} + +/* Do all the real work for OpenFont or FontInfo */ +/* xf->info is only accessed through info, and xf might be null */ + +static int +FreeTypeLoadXFont(char *fileName, + FontScalablePtr vals, FontPtr xf, FontInfoPtr info, + FontBitmapFormatPtr bmfmt, FontEntryPtr entry) +{ + FTFontPtr font = NULL; + FTFacePtr face = NULL; + FTInstancePtr instance; + FT_Size_Metrics *smetrics; + int xrc=Successful; + int charcell; + long rawWidth = 0, rawAverageWidth = 0; + int upm, minLsb, maxRsb, ascent, descent, width, averageWidth; + double scale, base_width, base_height; + Bool orig_is_matrix_unit, font_properties; + int face_number, ttcap_spacing; + struct TTCapInfo tmp_ttcap; + struct TTCapInfo *ins_ttcap; + FT_Int32 load_flags = FT_LOAD_DEFAULT; /* orig: FT_LOAD_RENDER | FT_LOAD_MONOCHROME */ + char *dynStrRealFileName = NULL; /* foo.ttc */ + char *dynStrFTFileName = NULL; /* :1:foo.ttc */ + char *dynStrTTCapCodeRange = NULL; + + font = calloc(1, sizeof(FTFontRec)); + if(font == NULL) { + xrc = AllocError; + goto quit; + } + + xrc = FreeTypeSetUpTTCap(fileName, vals, + &dynStrRealFileName, &dynStrFTFileName, + &tmp_ttcap, &face_number, + &load_flags, &ttcap_spacing, + &font_properties, &dynStrTTCapCodeRange); + if ( xrc != Successful ) { + goto quit; + } + + xrc = FreeTypeOpenFace(&face, dynStrFTFileName, dynStrRealFileName, face_number); + if(xrc != Successful) { + goto quit; + } + + if( is_matrix_unit(vals) ) + orig_is_matrix_unit = True; + else { + orig_is_matrix_unit = False; + /* Turn off EmbeddedBitmap when original matrix is not diagonal. */ + load_flags |= FT_LOAD_NO_BITMAP; + } + + if( face->bitmap ) load_flags &= ~FT_LOAD_NO_BITMAP; + + /* Slant control by TTCap */ + if(!face->bitmap) { + vals->pixel_matrix[2] += + vals->pixel_matrix[0] * tmp_ttcap.autoItalic; + vals->point_matrix[2] += + vals->point_matrix[0] * tmp_ttcap.autoItalic; + vals->pixel_matrix[3] += + vals->pixel_matrix[1] * tmp_ttcap.autoItalic; + vals->point_matrix[3] += + vals->point_matrix[1] * tmp_ttcap.autoItalic; + } + + base_width=hypot(vals->pixel_matrix[0], vals->pixel_matrix[1]); + base_height=hypot(vals->pixel_matrix[2], vals->pixel_matrix[3]); + if(MAX(base_width, base_height) < 1.0 ) { + xrc = BadFontName; + goto quit; + } + + xrc = FreeTypeLoadFont(font, info, face, dynStrFTFileName, vals, entry, bmfmt, + load_flags, &tmp_ttcap, dynStrTTCapCodeRange, + ttcap_spacing ); + if(xrc != Successful) { + goto quit; + } + + instance = font->instance; + smetrics = &instance->size->metrics; + ins_ttcap = &instance->ttcap; + + upm = face->face->units_per_EM; + if(upm == 0) { + /* Work around FreeType bug */ + upm = WORK_AROUND_UPM; + } + scale = 1.0 / upm; + + charcell = (instance->spacing == FT_CHARCELL); + + if( instance->charcellMetrics == NULL ) { + + /* New instance */ + + long force_c_rawWidth = 0; + int force_c_lsb,force_c_rsb,force_c_width; + double unit_x=0,unit_y=0,advance; + CharInfoPtr tmpglyph; + + /* + * CALCULATE HEADER'S METRICS + */ + + /* for OUTLINE fonts */ + if(!face->bitmap) { + int new_width; + double ratio,force_c_ratio; + double width_x=0,width_y=0; + double force_c_width_x, force_c_rsb_x, force_c_lsb_x; + double tmp_rsb,tmp_lsb,tmp_asc,tmp_des; + double max_advance_height; + tmp_asc = face->face->bbox.yMax; + tmp_des = -(face->face->bbox.yMin); + if ( tmp_asc < face->face->ascender ) tmp_asc = face->face->ascender; + if ( tmp_des < -(face->face->descender) ) tmp_des = -(face->face->descender); + tmp_lsb = face->face->bbox.xMin; + tmp_rsb = face->face->bbox.xMax; + if ( tmp_rsb < face->face->max_advance_width ) tmp_rsb = face->face->max_advance_width; + /* apply scaleBBoxWidth */ + /* we should not ...??? */ + tmp_lsb *= ins_ttcap->scaleBBoxWidth; + tmp_rsb *= ins_ttcap->scaleBBoxWidth; + /* transform and rescale */ + compute_new_extents( vals, scale, tmp_lsb, tmp_rsb, tmp_des, tmp_asc, + &minLsb, &maxRsb, &descent, &ascent ); + /* */ + /* Consider vertical layouts */ + if( 0 < face->face->max_advance_height ) + max_advance_height = face->face->max_advance_height; + else + max_advance_height = tmp_asc + tmp_des; + if( vals->pixel_matrix[1] == 0 ){ + unit_x = fabs(vals->pixel_matrix[0]); + unit_y = 0; + width_x = face->face->max_advance_width * ins_ttcap->scaleBBoxWidth * unit_x; + } + else if( vals->pixel_matrix[3] == 0 ){ + unit_y = fabs(vals->pixel_matrix[2]); + unit_x = 0; + width_x = max_advance_height * ins_ttcap->scaleBBoxHeight * unit_y; + } + else{ + unit_x = fabs(vals->pixel_matrix[0] - + vals->pixel_matrix[1]*vals->pixel_matrix[2]/vals->pixel_matrix[3]); + unit_y = fabs(vals->pixel_matrix[2] - + vals->pixel_matrix[3]*vals->pixel_matrix[0]/vals->pixel_matrix[1]); + width_x = face->face->max_advance_width * ins_ttcap->scaleBBoxWidth * unit_x; + width_y = max_advance_height * ins_ttcap->scaleBBoxHeight * unit_y; + if( width_y < width_x ){ + width_x = width_y; + unit_x = 0; + } + else{ + unit_y = 0; + } + } + /* calculate correction ratio */ + width = (int)floor( (advance = width_x * scale) + 0.5); + new_width = width; + if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH ) + new_width += ins_ttcap->doubleStrikeShift; + new_width += ins_ttcap->adjustBBoxWidthByPixel; + ratio = (double)new_width/width; + width = new_width; + /* force constant */ + if( unit_x != 0 ) { + force_c_width_x = face->face->max_advance_width + * ins_ttcap->force_c_scale_b_box_width * unit_x; + force_c_lsb_x = face->face->max_advance_width + * ins_ttcap->force_c_scale_lsb * unit_x; + force_c_rsb_x = face->face->max_advance_width + * ins_ttcap->force_c_scale_rsb * unit_x; + } + else { + force_c_width_x = max_advance_height + * ins_ttcap->force_c_scale_b_box_height * unit_y; + force_c_lsb_x = max_advance_height + * ins_ttcap->force_c_scale_lsb * unit_y; + force_c_rsb_x = max_advance_height + * ins_ttcap->force_c_scale_rsb * unit_y; + } + /* calculate correction ratio */ + force_c_width = (int)floor(force_c_width_x * scale + 0.5); + new_width = force_c_width; + if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH ) + force_c_width += ins_ttcap->doubleStrikeShift; + new_width += ins_ttcap->force_c_adjust_width_by_pixel; + force_c_ratio = (double)new_width/force_c_width; + force_c_width = new_width; + /* force_c_lsb, force_c_rsb */ + if( ins_ttcap->flags & TTCAP_FORCE_C_LSB_FLAG ) + force_c_lsb = (int)floor( force_c_lsb_x * scale + 0.5 ); + else + force_c_lsb = minLsb; + if( ins_ttcap->flags & TTCAP_FORCE_C_RSB_FLAG ) + force_c_rsb = (int)floor( force_c_rsb_x * scale + 0.5 ); + else + force_c_rsb = maxRsb; + /* calculate shift of BitmapAutoItalic + (when diagonal matrix only) */ + if( orig_is_matrix_unit == True ) { + if( ins_ttcap->autoItalic != 0 ) { + double ai; + int ai_lsb,ai_rsb,ai_total; + if( 0 < ins_ttcap->autoItalic ) ai=ins_ttcap->autoItalic; + else ai = -ins_ttcap->autoItalic; + ai_total = (int)( (ascent+descent) * ai + 0.5); + ai_rsb = (int)((double)ai_total * ascent / ( ascent + descent ) + 0.5 ); + ai_lsb = -(ai_total - ai_rsb); + if( 0 < ins_ttcap->autoItalic ) { + ins_ttcap->lsbShiftOfBitmapAutoItalic = ai_lsb; + ins_ttcap->rsbShiftOfBitmapAutoItalic = ai_rsb; + } + else { + ins_ttcap->lsbShiftOfBitmapAutoItalic = -ai_rsb; + ins_ttcap->rsbShiftOfBitmapAutoItalic = -ai_lsb; + } + } + } + /* integer adjustment by TTCap */ + if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE ) + maxRsb += ins_ttcap->doubleStrikeShift; + maxRsb += ins_ttcap->adjustRightSideBearingByPixel; + minLsb += ins_ttcap->adjustLeftSideBearingByPixel; + /* */ + if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE ) + force_c_rsb += ins_ttcap->doubleStrikeShift; + force_c_rsb += ins_ttcap->force_c_adjust_rsb_by_pixel; + force_c_lsb += ins_ttcap->force_c_adjust_lsb_by_pixel; + /* apply to rawWidth */ + averageWidth = (int)floor(10 * width_x * scale + * ratio + 0.5); + rawWidth = floor(width_x * scale + * ratio * 1000. / base_height + 0.5); + rawAverageWidth = floor(width_x * scale * ratio * 10. + * 1000. / base_height + 0.5); + force_c_rawWidth = floor(force_c_width_x * scale + * force_c_ratio * 1000. / base_height + 0.5); + /* */ + } + /* for BITMAP fonts [if(face->bitmap)] */ + else { + /* These values differ from actual when outline, + so we must use them ONLY FOR BITMAP. */ + width = (int)floor(smetrics->max_advance * ins_ttcap->scaleBBoxWidth / 64.0 + .5); + descent = -smetrics->descender / 64; + ascent = smetrics->ascender / 64; + /* force constant */ + force_c_width = (int)floor(smetrics->max_advance + * ins_ttcap->force_c_scale_b_box_width / 64.0 + .5); + /* Preserve average width for bitmap fonts */ + if(vals->width != 0) + averageWidth = (int)floor(vals->width * ins_ttcap->scaleBBoxWidth +.5); + else + averageWidth = (int)floor(10.0 * smetrics->max_advance + * ins_ttcap->scaleBBoxWidth / 64.0 + .5); + rawWidth = 0; + rawAverageWidth = 0; + force_c_rawWidth = 0; + /* We don't consider vertical layouts */ + advance = (int)floor(smetrics->max_advance / 64.0 +.5); + unit_x = vals->pixel_matrix[0]; + unit_y = 0; + /* We can use 'width' only when bitmap. + This should not be set when outline. */ + minLsb = 0; + maxRsb = width; + /* force constant */ + if( ins_ttcap->flags & TTCAP_FORCE_C_LSB_FLAG ) + force_c_lsb = (int)floor(smetrics->max_advance + * ins_ttcap->force_c_scale_lsb / 64.0 + .5); + else + force_c_lsb = minLsb; + if( ins_ttcap->flags & TTCAP_FORCE_C_RSB_FLAG ) + force_c_rsb = (int)floor(smetrics->max_advance + * ins_ttcap->force_c_scale_rsb / 64.0 + .5); + else + force_c_rsb = maxRsb; + /* calculate shift of BitmapAutoItalic */ + if( ins_ttcap->autoItalic != 0 ) { + double ai; + int ai_lsb,ai_rsb,ai_total; + if( 0 < ins_ttcap->autoItalic ) ai=ins_ttcap->autoItalic; + else ai = -ins_ttcap->autoItalic; + ai_total = (int)( (ascent+descent) * ai + 0.5); + ai_rsb = (int)((double)ai_total * ascent / ( ascent + descent ) + 0.5 ); + ai_lsb = -(ai_total - ai_rsb); + if( 0 < ins_ttcap->autoItalic ) { + ins_ttcap->lsbShiftOfBitmapAutoItalic = ai_lsb; + ins_ttcap->rsbShiftOfBitmapAutoItalic = ai_rsb; + } + else { + ins_ttcap->lsbShiftOfBitmapAutoItalic = -ai_rsb; + ins_ttcap->rsbShiftOfBitmapAutoItalic = -ai_lsb; + } + } + /* integer adjustment by TTCap */ + if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH ) + width += ins_ttcap->doubleStrikeShift; + if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE ) + maxRsb += ins_ttcap->doubleStrikeShift; + maxRsb += ins_ttcap->adjustRightSideBearingByPixel; + minLsb += ins_ttcap->adjustLeftSideBearingByPixel; + /* We have not carried out matrix calculation, so this is done. */ + maxRsb += ins_ttcap->rsbShiftOfBitmapAutoItalic; + minLsb += ins_ttcap->lsbShiftOfBitmapAutoItalic; + /* force constant */ + if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE ) + force_c_rsb += ins_ttcap->doubleStrikeShift; + force_c_rsb += ins_ttcap->force_c_adjust_rsb_by_pixel; + force_c_lsb += ins_ttcap->force_c_adjust_lsb_by_pixel; + force_c_rsb += ins_ttcap->rsbShiftOfBitmapAutoItalic; + force_c_lsb += ins_ttcap->lsbShiftOfBitmapAutoItalic; + } + + /* SET CALCULATED VALUES TO INSTANCE */ + + /* Set actual height and cosine */ + instance->pixel_size = base_height; + instance->advance = advance; + if ( unit_x != 0 ){ + instance->pixel_width_unit_x = unit_x/base_height; + instance->pixel_width_unit_y = 0; + } + else{ + instance->pixel_width_unit_x = 0; + instance->pixel_width_unit_y = unit_y/base_height; + } + + /* header's metrics */ + instance->charcellMetrics = malloc(sizeof(xCharInfo)); + if(instance->charcellMetrics == NULL) { + xrc = AllocError; + goto quit; + } + instance->charcellMetrics->ascent = ascent; + instance->charcellMetrics->descent = descent; + instance->charcellMetrics->attributes = rawWidth; + instance->charcellMetrics->rightSideBearing = maxRsb; + instance->charcellMetrics->leftSideBearing = minLsb; + instance->charcellMetrics->characterWidth = width; + instance->averageWidth = averageWidth; + instance->rawAverageWidth = rawAverageWidth; + + /* Check code 0 */ + if( FreeTypeInstanceGetGlyph(font->zero_idx, 0, &tmpglyph, font->instance) != Successful + || tmpglyph == NULL) + if( FreeTypeInstanceGetGlyph(font->zero_idx, FT_GET_DUMMY, &tmpglyph, font->instance) + != Successful ) + tmpglyph = NULL; + if ( !tmpglyph ) { + xrc = AllocError; + goto quit; + } + + /* FORCE CONSTANT METRICS */ + if( 0 <= ins_ttcap->forceConstantSpacingEnd ) { + xCharInfo *tmpchar = NULL; + int c = ins_ttcap->force_c_representative_metrics_char_code; + /* header's metrics */ + if( instance->forceConstantMetrics == NULL ){ + instance->forceConstantMetrics = malloc(sizeof(xCharInfo)); + if(instance->forceConstantMetrics == NULL) { + xrc = AllocError; + goto quit; + } + } + /* Get Representative Metrics */ + if ( 0 <= c ) { + if( FreeTypeFontGetGlyphMetrics(c, 0, &tmpchar, font) != Successful ) + tmpchar = NULL; + } + if ( tmpchar && 0 < tmpchar->characterWidth ) { + instance->forceConstantMetrics->leftSideBearing = tmpchar->leftSideBearing; + instance->forceConstantMetrics->rightSideBearing = tmpchar->rightSideBearing; + instance->forceConstantMetrics->characterWidth = tmpchar->characterWidth; + instance->forceConstantMetrics->ascent = tmpchar->ascent; + instance->forceConstantMetrics->descent = tmpchar->descent; + instance->forceConstantMetrics->attributes = tmpchar->attributes; + } + else { + instance->forceConstantMetrics->leftSideBearing = force_c_lsb; + instance->forceConstantMetrics->rightSideBearing = force_c_rsb; + instance->forceConstantMetrics->characterWidth = force_c_width; + instance->forceConstantMetrics->ascent = ascent; + instance->forceConstantMetrics->descent = descent; + instance->forceConstantMetrics->attributes = force_c_rawWidth; + } + /* Check code 0 */ + if( FreeTypeInstanceGetGlyph(font->zero_idx, FT_FORCE_CONSTANT_SPACING, + &tmpglyph, font->instance) != Successful + || tmpglyph == NULL) + if( FreeTypeInstanceGetGlyph(font->zero_idx, FT_FORCE_CONSTANT_SPACING | FT_GET_DUMMY, + &tmpglyph, font->instance) + != Successful ) + tmpglyph = NULL; + if ( !tmpglyph ) { + xrc = AllocError; + goto quit; + } + } + } + else{ + + /* + * CACHED VALUES + */ + + width = instance->charcellMetrics->characterWidth; + ascent = instance->charcellMetrics->ascent; + descent = instance->charcellMetrics->descent; + rawWidth = instance->charcellMetrics->attributes; + maxRsb = instance->charcellMetrics->rightSideBearing; + minLsb = instance->charcellMetrics->leftSideBearing; + averageWidth = instance->averageWidth; + rawAverageWidth = instance->rawAverageWidth; + + } + + /* + * SET maxbounds, minbounds ... + */ + + if( !charcell ) { /* NOT CHARCELL */ + if( info ){ + /* + Calculate all glyphs' metrics. + maxbounds.ascent and maxbounds.descent are quite important values + for XAA. If ascent/descent of each glyph exceeds + maxbounds.ascent/maxbounds.descent, XAA causes SERVER CRASH. + Therefore, THIS MUST BE DONE. + */ + ft_compute_bounds(font,info,vals); + } + } + else{ /* CHARCELL */ + + /* + * SET CALCULATED OR CACHED VARIABLES + */ + + vals->width = averageWidth; + + if( info ){ + + info->maxbounds.leftSideBearing = minLsb; + info->maxbounds.rightSideBearing = maxRsb; + info->maxbounds.characterWidth = width; + info->maxbounds.ascent = ascent; + info->maxbounds.descent = descent; + info->maxbounds.attributes = + (unsigned short)(short)rawWidth; + + info->minbounds = info->maxbounds; + } + } + + /* set info */ + + if( info ){ + /* + info->fontAscent = ascent; + info->fontDescent = descent; + */ + info->fontAscent = info->maxbounds.ascent; + info->fontDescent = info->maxbounds.descent; + /* Glyph metrics are accurate */ + info->inkMetrics=1; + + memcpy((char *)&info->ink_maxbounds, + (char *)&info->maxbounds, sizeof(xCharInfo)); + memcpy((char *)&info->ink_minbounds, + (char *)&info->minbounds, sizeof(xCharInfo)); + + /* XXX - hack */ + info->defaultCh=0; + + /* Set the pInfo flags */ + /* Properties set by FontComputeInfoAccelerators: + pInfo->noOverlap; + pInfo->terminalFont; + pInfo->constantMetrics; + pInfo->constantWidth; + pInfo->inkInside; + */ + /* from lib/font/util/fontaccel.c */ + FontComputeInfoAccelerators(info); + } + + if(xf) + xf->fontPrivate = (void*)font; + + if(info) { + xrc = FreeTypeAddProperties(font, vals, info, entry->name.name, + rawAverageWidth, font_properties); + if (xrc != Successful) { + goto quit; + } + } + + quit: + if ( dynStrTTCapCodeRange ) free(dynStrTTCapCodeRange); + if ( dynStrFTFileName ) free(dynStrFTFileName); + if ( dynStrRealFileName ) free(dynStrRealFileName); + if ( xrc != Successful ) { + if( font ){ + if( face && font->instance == NULL ) FreeTypeFreeFace(face); + FreeTypeFreeFont(font); + } + } + return xrc; +} + +/* Routines used by X11 to get info and glyphs from the font. */ + +static int +FreeTypeGetMetrics(FontPtr pFont, unsigned long count, unsigned char *chars, + FontEncoding charEncoding, unsigned long *metricCount, + xCharInfo **metrics) +{ + unsigned int code = 0; + int flags = 0; + FTFontPtr tf; + struct TTCapInfo *ttcap; + xCharInfo **mp, *m; + + /* MUMBLE("Get metrics for %ld characters\n", count);*/ + + tf = (FTFontPtr)pFont->fontPrivate; + ttcap = &tf->instance->ttcap; + mp = metrics; + + while (count-- > 0) { + switch (charEncoding) { + case Linear8Bit: + case TwoD8Bit: + code = *chars++; + break; + case Linear16Bit: + case TwoD16Bit: + code = (*chars++ << 8); + code |= *chars++; + /* */ + if ( !(ttcap->flags & TTCAP_FORCE_C_OUTSIDE) ) { + if ( (int)code <= ttcap->forceConstantSpacingEnd + && ttcap->forceConstantSpacingBegin <= (int)code ) + flags|=FT_FORCE_CONSTANT_SPACING; + else flags=0; + } + else { /* for GB18030 proportional */ + if ( (int)code <= ttcap->forceConstantSpacingEnd + || ttcap->forceConstantSpacingBegin <= (int)code ) + flags|=FT_FORCE_CONSTANT_SPACING; + else flags=0; + } + break; + } + + if(FreeTypeFontGetGlyphMetrics(code, flags, &m, tf) == Successful && m!=NULL) { + *mp++ = m; + } +#ifdef X_ACCEPTS_NO_SUCH_CHAR + else *mp++ = &noSuchChar.metrics; +#endif + } + + *metricCount = mp - metrics; + return Successful; +} + +static int +FreeTypeGetGlyphs(FontPtr pFont, unsigned long count, unsigned char *chars, + FontEncoding charEncoding, unsigned long *glyphCount, + CharInfoPtr *glyphs) +{ + unsigned int code = 0; + int flags = 0; + FTFontPtr tf; + CharInfoPtr *gp; + CharInfoPtr g; + struct TTCapInfo *ttcap; + + tf = (FTFontPtr)pFont->fontPrivate; + ttcap = &tf->instance->ttcap; + gp = glyphs; + + while (count-- > 0) { + switch (charEncoding) { + case Linear8Bit: case TwoD8Bit: + code = *chars++; + break; + case Linear16Bit: case TwoD16Bit: + code = *chars++ << 8; + code |= *chars++; + /* */ + if ( !(ttcap->flags & TTCAP_FORCE_C_OUTSIDE) ) { + if ( (int)code <= ttcap->forceConstantSpacingEnd + && ttcap->forceConstantSpacingBegin <= (int)code ) + flags|=FT_FORCE_CONSTANT_SPACING; + else flags=0; + } + else { /* for GB18030 proportional */ + if ( (int)code <= ttcap->forceConstantSpacingEnd + || ttcap->forceConstantSpacingBegin <= (int)code ) + flags|=FT_FORCE_CONSTANT_SPACING; + else flags=0; + } + break; + } + + if(FreeTypeFontGetGlyph(code, flags, &g, tf) == Successful && g!=NULL) { + *gp++ = g; + } +#ifdef X_ACCEPTS_NO_SUCH_CHAR + else { +#ifdef XAA_ACCEPTS_NULL_BITS + *gp++ = &noSuchChar; +#else + if ( tf->dummy_char.bits ) { + *gp++ = &tf->dummy_char; + } + else { + char *raster = NULL; + int wd_actual, ht_actual, wd, ht, bpr; + wd_actual = tf->info->maxbounds.rightSideBearing - tf->info->maxbounds.leftSideBearing; + ht_actual = tf->info->maxbounds.ascent + tf->info->maxbounds.descent; + if(wd_actual <= 0) wd = 1; + else wd=wd_actual; + if(ht_actual <= 0) ht = 1; + else ht=ht_actual; + bpr = (((wd + (tf->instance->bmfmt.glyph<<3) - 1) >> 3) & + -tf->instance->bmfmt.glyph); + raster = calloc(1, ht * bpr); + if(raster) { + tf->dummy_char.bits = raster; + *gp++ = &tf->dummy_char; + } + } +#endif + } +#endif + } + + *glyphCount = gp - glyphs; + return Successful; +} + +static int +FreeTypeSetUpFont(FontPathElementPtr fpe, FontPtr xf, FontInfoPtr info, + fsBitmapFormat format, fsBitmapFormatMask fmask, + FontBitmapFormatPtr bmfmt) +{ + int xrc; + int image; + + /* Get the default bitmap format information for this X installation. + Also update it for the client if running in the font server. */ + FontDefaultFormat(&bmfmt->bit, &bmfmt->byte, &bmfmt->glyph, &bmfmt->scan); + if ((xrc = CheckFSFormat(format, fmask, &bmfmt->bit, &bmfmt->byte, + &bmfmt->scan, &bmfmt->glyph, + &image)) != Successful) { + MUMBLE("Aborting after checking FS format: %d\n", xrc); + return xrc; + } + + if(xf) { + xf->refcnt = 0; + xf->bit = bmfmt->bit; + xf->byte = bmfmt->byte; + xf->glyph = bmfmt->glyph; + xf->scan = bmfmt->scan; + xf->format = format; + xf->get_glyphs = FreeTypeGetGlyphs; + xf->get_metrics = FreeTypeGetMetrics; + xf->unload_font = FreeTypeUnloadXFont; + xf->unload_glyphs = 0; + xf->fpe = fpe; + xf->svrPrivate = 0; + xf->fontPrivate = 0; /* we'll set it later */ + xf->fpePrivate = 0; + } + + info->defaultCh = 0; + info->noOverlap = 0; /* not updated */ + info->terminalFont = 0; /* not updated */ + info->constantMetrics = 0; /* we'll set it later */ + info->constantWidth = 0; /* we'll set it later */ + info->inkInside = 1; + info->inkMetrics = 1; + info->allExist=0; /* not updated */ + info->drawDirection = LeftToRight; /* we'll set it later */ + info->cachable = 1; /* we don't do licensing */ + info->anamorphic = 0; /* can hinting lead to anamorphic scaling? */ + info->maxOverlap = 0; /* we'll set it later. */ + info->pad = 0; /* ??? */ + return Successful; +} + +/* Functions exported by the backend */ + +static int +FreeTypeOpenScalable(FontPathElementPtr fpe, FontPtr *ppFont, int flags, + FontEntryPtr entry, char *fileName, FontScalablePtr vals, + fsBitmapFormat format, fsBitmapFormatMask fmask, + FontPtr non_cachable_font) +{ + int xrc; + FontPtr xf; + FontBitmapFormatRec bmfmt; + + MUMBLE("Open Scalable %s, XLFD=%s\n",fileName, entry->name.length ? entry->name.name : ""); + + xf = CreateFontRec(); + if (xf == NULL) + return AllocError; + + xrc = FreeTypeSetUpFont(fpe, xf, &xf->info, format, fmask, &bmfmt); + if(xrc != Successful) { + DestroyFontRec(xf); + return xrc; + } + xrc = FreeTypeLoadXFont(fileName, vals, xf, &xf->info, &bmfmt, entry); + if(xrc != Successful) { + MUMBLE("Error during load: %d\n",xrc); + DestroyFontRec(xf); + return xrc; + } + + *ppFont = xf; + + return xrc; +} + +/* Routine to get requested font info. */ + +static int +FreeTypeGetInfoScalable(FontPathElementPtr fpe, FontInfoPtr info, + FontEntryPtr entry, FontNamePtr fontName, + char *fileName, FontScalablePtr vals) +{ + int xrc; + FontBitmapFormatRec bmfmt; + + MUMBLE("Get info, XLFD=%s\n", entry->name.length ? entry->name.name : ""); + + xrc = FreeTypeSetUpFont(fpe, 0, info, 0, 0, &bmfmt); + if(xrc != Successful) { + return xrc; + } + + bmfmt.glyph <<= 3; + + xrc = FreeTypeLoadXFont(fileName, vals, 0, info, &bmfmt, entry); + if(xrc != Successful) { + MUMBLE("Error during load: %d\n", xrc); + return xrc; + } + + return Successful; +} + +/* Renderer registration. */ + +/* Set the capabilities of this renderer. */ +#define CAPABILITIES (CAP_CHARSUBSETTING | CAP_MATRIX) + +/* Set it up so file names with either upper or lower case can be + loaded. We don't support compressed fonts. */ +static FontRendererRec renderers[] = { + {".ttf", 4, 0, FreeTypeOpenScalable, 0, + FreeTypeGetInfoScalable, 0, CAPABILITIES}, + {".ttc", 4, 0, FreeTypeOpenScalable, 0, + FreeTypeGetInfoScalable, 0, CAPABILITIES}, + {".otf", 4, 0, FreeTypeOpenScalable, 0, + FreeTypeGetInfoScalable, 0, CAPABILITIES}, + {".otc", 4, 0, FreeTypeOpenScalable, 0, + FreeTypeGetInfoScalable, 0, CAPABILITIES}, + {".pfa", 4, 0, FreeTypeOpenScalable, 0, + FreeTypeGetInfoScalable, 0, CAPABILITIES}, + {".pfb", 4, 0, FreeTypeOpenScalable, 0, + FreeTypeGetInfoScalable, 0, CAPABILITIES}, +}; +static int num_renderers = sizeof(renderers) / sizeof(renderers[0]); + +static FontRendererRec alt_renderers[] = { + {".bdf", 4, 0, FreeTypeOpenScalable, 0, + FreeTypeGetInfoScalable, 0, CAPABILITIES}, + {".pcf", 4, 0, FreeTypeOpenScalable, 0, + FreeTypeGetInfoScalable, 0, CAPABILITIES}, +}; + +static int num_alt_renderers = +sizeof(alt_renderers) / sizeof(alt_renderers[0]); + + +void +FreeTypeRegisterFontFileFunctions(void) +{ + int i; + + for (i = 0; i < num_renderers; i++) + FontFileRegisterRenderer(&renderers[i]); + + for (i = 0; i < num_alt_renderers; i++) + FontFilePriorityRegisterRenderer(&alt_renderers[i], -10); +} diff --git a/src/FreeType/ftfuncs.h b/src/FreeType/ftfuncs.h new file mode 100755 index 0000000..068a595 --- /dev/null +++ b/src/FreeType/ftfuncs.h @@ -0,0 +1,189 @@ +/* +Copyright (c) 1998-2002 by Juliusz Chroboczek +Copyright (c) 2003 After X-TT Project, All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/* Number of buckets in the hashtable holding faces */ +#define NUMFACEBUCKETS 32 + +/* Glyphs are held in segments of this size */ +#define FONTSEGMENTSIZE 16 + +/* A structure that holds bitmap order and padding info. */ + +typedef struct { + int bit; /* bit order */ + int byte; /* byte order */ + int glyph; /* glyph pad size */ + int scan; /* machine word size */ +} FontBitmapFormatRec, *FontBitmapFormatPtr; + +struct FTSize_s; + +/* At the lowest level, there is face; FTFaces are in one-to-one + correspondence with TrueType faces. Multiple instance may share + the same face. */ + +typedef struct _FTFace { + char *filename; + FT_Face face; + int bitmap; + FT_UInt num_hmetrics; + struct _FTInstance *instances; + struct _FTInstance *active_instance; + struct _FTFace *next; /* link to next face in bucket */ +} FTFaceRec, *FTFacePtr; + +/* A transformation matrix with resolution information */ +typedef struct _FTNormalisedTransformation { + double scale; + int nonIdentity; /* if 0, matrix is the identity */ + FT_Matrix matrix; + int xres, yres; +} FTNormalisedTransformationRec, *FTNormalisedTransformationPtr; + +#define FT_PROPORTIONAL 0 +#define FT_MONOSPACED 1 +#define FT_CHARCELL 2 + +#define FT_AVAILABLE_UNKNOWN 0 +#define FT_AVAILABLE_NO 1 +#define FT_AVAILABLE_METRICS 2 +#define FT_AVAILABLE_RASTERISED 3 + +#define FT_GET_GLYPH_BOTH 0x01 +#define FT_GET_GLYPH_METRICS_ONLY 0x02 +#define FT_GET_DUMMY 0x04 +#define FT_FORCE_CONSTANT_SPACING 0x08 + +#define TTCAP_DOUBLE_STRIKE 0x0001 +#define TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT 0x0002 +#define TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH 0x0008 +#define TTCAP_IS_VERY_LAZY 0x0010 +#define TTCAP_DISABLE_DEFAULT_VERY_LAZY 0x0020 +#define TTCAP_FORCE_C_LSB_FLAG 0x0100 +#define TTCAP_FORCE_C_RSB_FLAG 0x0200 +#define TTCAP_FORCE_C_OUTSIDE 0x0400 +#define TTCAP_MONO_CENTER 0x0800 + +/* TTCap */ +struct TTCapInfo { + long flags; + double autoItalic; + double scaleWidth; + double scaleBBoxWidth; + double scaleBBoxHeight; + int doubleStrikeShift; + int adjustBBoxWidthByPixel; + int adjustLeftSideBearingByPixel; + int adjustRightSideBearingByPixel; + double scaleBitmap; + int forceConstantSpacingBegin; + int forceConstantSpacingEnd; + /* We don't compare */ + int force_c_adjust_width_by_pixel; + int force_c_adjust_lsb_by_pixel; + int force_c_adjust_rsb_by_pixel; + int force_c_representative_metrics_char_code; + double force_c_scale_b_box_width; + double force_c_scale_b_box_height; + double force_c_scale_lsb; + double force_c_scale_rsb; + double vl_slant; + int lsbShiftOfBitmapAutoItalic; + int rsbShiftOfBitmapAutoItalic; +}; + +/* An instance builds on a face by specifying the transformation + matrix. Multiple fonts may share the same instance. */ + +/* This structure caches bitmap data */ +typedef struct _FTInstance { + FTFacePtr face; /* the associated face */ + FT_Size size; + FTNormalisedTransformationRec transformation; + FT_Int32 load_flags; + FT_ULong strike_index; + int spacing; /* actual spacing */ + double pixel_size; /* to calc attributes (actual height) */ + double pixel_width_unit_x; /* to calc horiz. width (cosine) */ + double pixel_width_unit_y; /* to calc vert. width (cosine) */ + xCharInfo *charcellMetrics; /* the header's metrics */ + int averageWidth; /* the header's metrics */ + long rawAverageWidth; /* the header's metrics */ + double advance; /* the header's metrics */ + xCharInfo *forceConstantMetrics; + FontBitmapFormatRec bmfmt; + unsigned nglyphs; + CharInfoPtr *glyphs; /* glyphs and available are used in parallel */ + int **available; + struct TTCapInfo ttcap; + int refcount; + struct _FTInstance *next; /* link to next instance */ +} FTInstanceRec, *FTInstancePtr; + +/* A font is an instance with coding information; fonts are in + one-to-one correspondence with X fonts */ +typedef struct _FTFont{ + FTInstancePtr instance; + FTMappingRec mapping; + unsigned zero_idx; + FontInfoPtr info; + int nranges; + CharInfoRec dummy_char; + fsRange *ranges; +} FTFontRec, *FTFontPtr; + +#ifndef NOT_IN_FTFUNCS + +/* Prototypes for some local functions */ + +static int FreeTypeOpenFace(FTFacePtr *facep, char *FTFileName, char *realFileName, int faceNumber); +static void FreeTypeFreeFace(FTFacePtr face); +static int +FreeTypeOpenInstance(FTInstancePtr *instancep, FTFacePtr face, + char *FTFileName, FTNormalisedTransformationPtr trans, + int spacing, FontBitmapFormatPtr bmfmt, + struct TTCapInfo *tmp_ttcap, FT_Int32 load_flags); +static void FreeTypeFreeInstance(FTInstancePtr instance); +static int +FreeTypeInstanceGetGlyph(unsigned idx, int flags, CharInfoPtr *g, FTInstancePtr instance); +static int +FreeTypeInstanceGetGlyphMetrics(unsigned idx, int flags, + xCharInfo **metrics, FTInstancePtr instance ); +static int +FreeTypeRasteriseGlyph(unsigned idx, int flags, CharInfoPtr tgp, + FTInstancePtr instance, int hasMetrics ); +static void FreeTypeFreeFont(FTFontPtr font); +static void FreeTypeFreeXFont(FontPtr pFont, int freeProps); +static void FreeTypeUnloadXFont(FontPtr pFont); +static int +FreeTypeAddProperties(FTFontPtr font, FontScalablePtr vals, FontInfoPtr info, + char *fontname, int rawAverageWidth, Bool font_properties); +static int FreeTypeFontGetGlyph(unsigned code, int flags, CharInfoPtr *g, FTFontPtr font); +static int +FreeTypeLoadFont(FTFontPtr font, FontInfoPtr info, FTFacePtr face, + char *FTFileName, FontScalablePtr vals, FontEntryPtr entry, + FontBitmapFormatPtr bmfmt, FT_Int32 load_flags, + struct TTCapInfo *tmp_ttcap, char *dynStrTTCapCodeRange, + int ttcap_spacing ); + +#endif /* NOT_IN_FTFUNCS */ diff --git a/src/FreeType/fttools.c b/src/FreeType/fttools.c new file mode 100755 index 0000000..bc75b7e --- /dev/null +++ b/src/FreeType/fttools.c @@ -0,0 +1,140 @@ +/* + Copyright (c) 1997 by Mark Leisher + Copyright (c) 1998-2002 by Juliusz Chroboczek + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include + +#include +#include +#include FT_FREETYPE_H +#include FT_SFNT_NAMES_H +#include FT_TRUETYPE_IDS_H +#include "ft.h" + +#ifndef LSBFirst +#define LSBFirst 0 +#define MSBFirst 1 +#endif + +#define LOBYTE(s,byte) ((byte)==LSBFirst?*(char*)(s):*((char*)(s)+1)) +#define HIBYTE(s,byte) ((byte)==LSBFirst?*((char*)(s)+1):*(char*)(s)) + +int FTtoXReturnCode(int rc) +{ + if(rc == 0x40) + return AllocError; + /* Anything else stops the font matching mechanism */ + else return BadFontName; + +} + +/* Convert slen bytes from UCS-2 to ISO 8859-1. Byte specifies the + endianness of the string, max the maximum number of bytes written into + to. */ +static int +FTu2a(int slen, FT_Byte *from, char *to, int byte, int max) +{ + int i, n; + + n = 0; + for (i = 0; i < slen; i += 2) { + if(n >= max - 1) + break; + if(HIBYTE(from+i, byte)!=0) + *to++='?'; + else + *to++ = LOBYTE(from+i,byte); + n++; + } + *to = 0; + return n; +} + +static int +FTGetName(FT_Face face, int nid, int pid, int eid, FT_SfntName *name_return) +{ + FT_SfntName name; + int n, i; + + n = FT_Get_Sfnt_Name_Count(face); + if(n <= 0) + return 0; + + for(i = 0; i < n; i++) { + if(FT_Get_Sfnt_Name(face, i, &name)) + continue; + if(name.name_id == nid && + name.platform_id == pid && + (eid < 0 || name.encoding_id == eid)) { + switch(name.platform_id) { + case TT_PLATFORM_APPLE_UNICODE: + case TT_PLATFORM_MACINTOSH: + if(name.language_id != TT_MAC_LANGID_ENGLISH) + continue; + break; + case TT_PLATFORM_MICROSOFT: + if(name.language_id != TT_MS_LANGID_ENGLISH_UNITED_STATES && + name.language_id != TT_MS_LANGID_ENGLISH_UNITED_KINGDOM) + break; + continue; + break; + default: + break; + } + *name_return = name; + return 1; + } + } + return 0; +} + +int +FTGetEnglishName(FT_Face face, int nid, char *name_return, int name_len) +{ + FT_SfntName name; + int len; + + if(FTGetName(face, nid, + TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, &name) || + FTGetName(face, nid, + TT_PLATFORM_APPLE_UNICODE, -1, &name)) + return FTu2a(name.string_len, name.string, name_return, + MSBFirst, name_len); + + /* Pretend that Apple Roman is ISO 8859-1. */ + if(FTGetName(face, nid, TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, &name)) { + len = name.string_len; + if(len > name_len - 1) + len = name_len - 1; + memcpy(name_return, name.string, len); + name_return[len] = '\0'; /* ensure nul terminaison */ + return len; + } + + /* Must be some font that can only be named in Polish or something. */ + return -1; +} diff --git a/src/FreeType/xttcap.c b/src/FreeType/xttcap.c new file mode 100755 index 0000000..c2a4120 --- /dev/null +++ b/src/FreeType/xttcap.c @@ -0,0 +1,705 @@ +/* ===EmacsMode: -*- Mode: C; tab-width:4; c-basic-offset: 4; -*- === */ +/* ===FileName: === + Copyright (c) 1998 Takuya SHIOZAKI, All Rights reserved. + Copyright (c) 1998 X-TrueType Server Project, All rights reserved. + Copyright (c) 2003 After X-TT Project, All rights reserved. + +===Notice + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + Major Release ID: X-TrueType Server Version 1.4 [Charles's Wain Release 0] + +Notice=== + */ + +/* +#include "xttversion.h" + +static char const * const releaseID = + _XTT_RELEASE_NAME; +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +#ifndef True +#define True (-1) +#endif /* True */ +#ifndef False +#define False (0) +#endif /* False */ + +#include "xttcap.h" + + +/************************************************************************** + Private Data Types + */ + +/* Property Record List */ +/* List Node */ +typedef struct TagSPropRecValListNodeP +{ + SPropRecValContainerEntityP containerE; + struct TagSPropRecValListNodeP *nextNode; +} SPropRecValListNodeP; + + +/************************************************************************** + Tables + */ + +/* valid record field */ +static SPropertyRecord const validRecords[] = +{ + { "FontFile", eRecTypeString }, + { "FaceNumber", eRecTypeString }, + { "AutoItalic", eRecTypeDouble }, + { "DoubleStrike", eRecTypeString }, + { "FontProperties", eRecTypeBool }, + { "ForceSpacing", eRecTypeString }, + { "ScaleBBoxWidth", eRecTypeString }, + { "ScaleWidth", eRecTypeDouble }, + { "EncodingOptions", eRecTypeString }, + { "Hinting", eRecTypeBool }, + { "VeryLazyMetrics", eRecTypeBool }, + { "CodeRange", eRecTypeString }, + { "EmbeddedBitmap", eRecTypeString }, + { "VeryLazyBitmapWidthScale", eRecTypeDouble }, + { "ForceConstantSpacingCodeRange", eRecTypeString }, + { "ForceConstantSpacingMetrics", eRecTypeString }, + { "Dummy", eRecTypeVoid } +}; +static int const +numOfValidRecords = sizeof(validRecords)/sizeof(validRecords[0]); + +/* correspondence between record name and cap variable name */ +static struct { + char const * capVariable; + char const * recordName; +} const correspondRelations[] = { + { "fn", "FaceNumber" }, + { "ai", "AutoItalic" }, + { "ds", "DoubleStrike" }, + { "fp", "FontProperties" }, + { "fs", "ForceSpacing" }, + { "bw", "ScaleBBoxWidth" }, + { "sw", "ScaleWidth" }, + { "eo", "EncodingOptions" }, + { "vl", "VeryLazyMetrics" }, + { "bs", "VeryLazyBitmapWidthScale" }, + { "cr", "CodeRange" }, + { "eb", "EmbeddedBitmap" }, + { "hi", "Hinting" }, + { "fc", "ForceConstantSpacingCodeRange" }, + { "fm", "ForceConstantSpacingMetrics" } +}; +static int const +numOfCorrespondRelations += sizeof(correspondRelations)/sizeof(correspondRelations[0]); + +/************************************************************************** + Functions + */ + +/* get property record type by record name */ +static Bool /* True == Found, False == Not Found */ +get_record_type_by_name(SPropertyRecord const ** const refRefRecord, /*result*/ + char const *strName) +{ + Bool result = False; + int i; + + *refRefRecord = NULL; + for (i=0; irecordType) { + case eRecTypeInteger: + { + int val; + char *endPtr; + + val = strtol(strValue, &endPtr, 0); + if ('\0' != *endPtr) { + fprintf(stderr, + "truetype font property : " + "%s record needs integer value.\n", + recordName); + result = True; + goto quit; + } + SPropContainer_value_int(&tmpContainerE) = val; + } + break; + case eRecTypeDouble: + { + double val; + char *endPtr; + + val = strtod(strValue, &endPtr); + if ('\0' != *endPtr) { + fprintf(stderr, + "truetype font property : " + "%s record needs floating point value.\n", + recordName); + result = True; + goto quit; + } + SPropContainer_value_dbl(&tmpContainerE) = val; + } + break; + case eRecTypeBool: + { + Bool val; + + if (!strcasecmp(strValue, "yes")) + val = True; + else if (!strcasecmp(strValue, "y")) + val = True; + else if (!strcasecmp(strValue, "on")) + val = True; + else if (!strcasecmp(strValue, "true")) + val = True; + else if (!strcasecmp(strValue, "t")) + val = True; + else if (!strcasecmp(strValue, "ok")) + val = True; + else if (!strcasecmp(strValue, "no")) + val = False; + else if (!strcasecmp(strValue, "n")) + val = False; + else if (!strcasecmp(strValue, "off")) + val = False; + else if (!strcasecmp(strValue, "false")) + val = False; + else if (!strcasecmp(strValue, "f")) + val = False; + else if (!strcasecmp(strValue, "bad")) + val = False; + else { + fprintf(stderr, + "truetype font property : " + "%s record needs boolean value.\n", + recordName); + result = True; + goto quit; + } + SPropContainer_value_bool(&tmpContainerE) = val; + } + break; + case eRecTypeString: + { + char *p; + + if (NULL == (p = malloc(strlen(strValue)+1))) { + fprintf(stderr, + "truetype font property : " + "cannot allocate memory.\n"); + result = True; + goto quit; + } + strcpy(p, strValue); + SPropContainer_value_str(&tmpContainerE) = p; + } + break; + case eRecTypeVoid: + if ('\0' != *strValue) { + fprintf(stderr, + "truetype font property : " + "%s record needs void.\n", recordName); + result = True; + } + break; + } + { + /* add to list */ + SPropRecValListNodeP *newNode; + + if (NULL == (newNode = malloc(sizeof(*newNode)))) { + fprintf(stderr, + "truetype font property : " + "cannot allocate memory.\n"); + result = True; + goto quit; + } + newNode->nextNode = pThisList->headNode; + newNode->containerE = tmpContainerE; + tmpContainerE.refRecordType = NULL; /* invalidate -- + disown value handle. */ + pThisList->headNode = newNode; + } + } else { + /* invalid record name */ + fprintf(stderr, + "truetype font : " + "invalid record name \"%s.\"\n", recordName); + result = True; + } + + quit: + return result; +} + +#ifdef USE_TTP_FILE + +#ifndef LEN_LINEBUF +#define LEN_LINEBUF 2048 +#endif /* !def LEN_LINEBUF */ + +/* get one line */ +static Bool /* True == Error, False == Success */ +get_one_line(FILE *is, char *buf) +{ + Bool result = False; + int count = 0; + Bool flHead = True; + Bool flSpace = False; + Bool flInSingleQuote = False; + Bool flInDoubleQuote = False; + Bool flBackSlash = False; + Bool flFirstElement = True; + + *buf = '\0'; + for (;;) { + int c = fgetc(is); + + if (ferror(is)) { + fprintf(stderr, "truetype font property file : read error.\n"); + result = True; + break; + } + + if (EOF == c) { + if (flInSingleQuote || flInDoubleQuote) { + fprintf(stderr, + "truetype font property file : unmatched quote.\n"); + result = True; + } + break; + } + if (flInSingleQuote) { + if ('\'' == c) { + /* end of single quoted string */ + flInSingleQuote = False; + c = -1; /* NOT extract to buffer. */ + } else + /* others, extract all character to buffer unconditionally. */ + ; + goto trans; + } + if (flBackSlash) { + /* escape --- when just before character is backslash, + next character is escaped. */ + flBackSlash = False; + if ('n' == c) + /* newline */ + c = '\n'; + if ('\n' == c) + /* ignore newline */ + c = -1; + else + /* others, extract all character to buffer unconditionally. */ + ; + goto trans; + } + if ('\\' == c) { + /* set flag to escape next character. */ + flBackSlash = True; + c = -1; /* NOT extract to buffer. */ + goto trans; + } + if (flInDoubleQuote) { + if ('"' == c) { + /* end of double quoted string */ + flInDoubleQuote = False; + c = -1; /* NOT extract to buffer. */ + } else + /* others, extract all character to buffer unconditionally. */ + ; + goto trans; + } + if ('#' == c) { + /* skip comment till end of line. */ + while ('\n' != c) { + c = fgetc(is); + if (ferror(is)) { + fprintf(stderr, + "truetype font property file : read error.\n"); + result = True; + break; + } + if (EOF == c) { + break; + } + } + break; + } + if ('\'' == c) { + /* into single quoted string */ + flInSingleQuote = True; + c = -1; /* NOT extract to buffer. */ + goto trans; + } + if ('"' == c) { + /* into double quoted string */ + flInDoubleQuote = True; + c = -1; /* NOT extract to buffer. */ + goto trans; + } + if ('\n' == c) + /* End of Line */ + break; + if (isspace(c)) { + /* convine multiple spaces */ + if (!flHead) + /* except space at the head of line */ + flSpace = True; + continue; + } + trans: + /* set flHead to False, since current character is not white space + when reaches here. */ + flHead = False; + do { + if (count>=LEN_LINEBUF-1) { + /* overflow */ + fprintf(stderr, + "truetype font property file : too long line.\n"); + result = True; + goto quit; + } + if (flSpace) { + /* just before characters is white space, but + current character is not WS. */ + if (flFirstElement) { + /* this spaces is the first cell(?) of white spaces. */ + flFirstElement = False; + /* separate record name and record value */ + *buf = (char)0xff; + } else + *buf = ' '; + flSpace = False; + } else + if (-1 != c) { + *buf = c; + c = -1; /* invalidate */ + } else + /* skip */ + buf--; + buf++; + } while (-1 != c); /* when 'c' is not -1, it means + that 'c' contains an untreated character. */ + } + *buf = '\0'; + + quit: + return result; +} + +/* parse one line */ +static Bool /* True == Error, False == Success */ +parse_one_line(SDynPropRecValList *pThisList, FILE *is) +{ + Bool result = False; + char *buf = NULL; + char *recordHead, *valueHead = NULL; + + if (NULL == (buf = malloc(LEN_LINEBUF))) { + fprintf(stderr, + "truetype font property file : cannot allocate memory.\n"); + result = True; + goto abort; + } + { + recordHead = buf; +/* refRecordValue->refRecordType = NULL;*/ + do { + if (get_one_line(is, buf)) { + result = True; + goto quit; + } + if (feof(is)) { + if ('\0' == *buf) + goto quit; + break; + } + } while ('\0' == *buf); + + if (NULL != (valueHead = strchr(buf, 0xff))) { + *valueHead = '\0'; + valueHead++; + } else + valueHead = buf+strlen(buf); +#if 0 + fprintf(stderr, + "truetype font property file : \n" + "recName:\"%s\"\nvalue:\"%s\"\n", + recordHead, valueHead); +#endif + result = SPropRecValList_add_record(pThisList, recordHead, valueHead); + } + quit: + free(buf); + abort: + return result; +} + +/* Read Property File */ +Bool /* True == Error, False == Success */ +SPropRecValList_read_prop_file(SDynPropRecValList *pThisList, + char const * const strFileName) +{ + Bool result = False; + FILE *is; + +#if 1 + if (!strcmp(strFileName, "-")) + is = stdin; + else +#endif + is = fopen(strFileName, "r"); + if (NULL == is) { + fprintf(stderr, "truetype font property : cannot open file %s.\n", + strFileName); + result = True; + goto abort; + } + { + for (;;) { + if (False != (result = parse_one_line(pThisList, is))) + goto quit; + if (feof(is)) + break; + } + } + quit: +#if 1 + if (strcmp(strFileName, "-")) +#endif + fclose(is); + abort: + return result; +} +#endif /* USE_TTP_FILE */ + +/* Constructor for Container Node */ +Bool /* True == Error, False == Success */ +SPropRecValList_new(SDynPropRecValList *pThisList) +{ + Bool result = False; + + pThisList->headNode = NULL; + + return result; +} + +#ifdef DUMP +void +SPropRecValList_dump(SRefPropRecValList *pThisList) +{ + SPropRecValListNodeP *p; + for (p=pThisList->headNode; NULL!=p; p=p->nextNode) { + switch (p->containerE.refRecordType->recordType) { + case eRecTypeInteger: + fprintf(stderr, "%s = %d\n", + p->containerE.refRecordType->strRecordName, + p->containerE.uValue.integerValue); + break; + case eRecTypeDouble: + fprintf(stderr, "%s = %f\n", + p->containerE.refRecordType->strRecordName, + p->containerE.uValue.doubleValue); + break; + case eRecTypeBool: + fprintf(stderr, "%s = %s\n", + p->containerE.refRecordType->strRecordName, + p->containerE.uValue.boolValue + ? "True":"False"); + break; + case eRecTypeString: + fprintf(stderr, "%s = \"%s\"\n", + p->containerE.refRecordType->strRecordName, + p->containerE.uValue.dynStringValue); + break; + case eRecTypeVoid: + fprintf(stderr, "%s = void\n", + p->containerE.refRecordType->strRecordName); + break; + } + } +} +#endif + + +/* Search Property Record */ +Bool /* True == Hit, False == Miss */ +SPropRecValList_search_record(SRefPropRecValList *pThisList, + SPropRecValContainer *refRecValue, + char const * const recordName) +{ + Bool result = False; + SPropRecValListNodeP *p; + + *refRecValue = NULL; + for (p=pThisList->headNode; NULL!=p; p=p->nextNode) { + if (!strcasecmp(p->containerE.refRecordType->strRecordName, + recordName)) { + *refRecValue = &p->containerE; + result = True; + break; + } + } + + return result; +} + + +/* Parse TTCap */ +Bool /* True == Error, False == Success */ +SPropRecValList_add_by_font_cap(SDynPropRecValList *pThisList, + char const *strCapHead) +{ + Bool result = False; + /* SPropertyRecord const *refRecordType; */ + char const *term; + + if (NULL == (term = strrchr(strCapHead, ':'))) + goto abort; + + { + /* for xfsft compatible */ + char const *p; + for (p=term-1; p>=strCapHead; p--) { + if ( ':'==*p ) { + /* + * :num:filename + * ^p ^term + */ + if ( p!=term ) { + int len = term-p-1; + char *value; + + len = term-p-1; + value=malloc(len+1); + memcpy(value, p+1, len); + value[len]='\0'; + SPropRecValList_add_record(pThisList, + "FaceNumber", + value); + free(value); + term=p; + } + break; + } + if ( !isdigit(*p) ) + break; + } + } + + while (strCapHead + +/******************************************************************* + Data Types + */ + +/* Record Type */ +typedef enum +{ + eRecTypeInteger, + eRecTypeDouble, + eRecTypeBool, + eRecTypeString, + eRecTypeVoid=-1 +} ERecType; + +/* Record Name vs Record Type */ +typedef struct +{ + char const *strRecordName; + ERecType const recordType; +} SPropertyRecord; + +/* Record Value Container */ +typedef struct +{ + SPropertyRecord const *refRecordType; + union { + int integerValue; + double doubleValue; + Bool boolValue; + char *dynStringValue; + } uValue; +} SPropRecValContainerEntityP, *SPropRecValContainer; + +/* Record Value List */ +typedef struct TagSPropRecValListNodeP SPropRecValListNode; +typedef struct +{ + SPropRecValListNode *headNode; +} SDynPropRecValList; +typedef SDynPropRecValList const SRefPropRecValList; + + +/******************************************************************* + Functions + */ + +/* Constructor for Rec Val List */ +extern Bool /* True == Error, False == Success */ +SPropRecValList_new(SDynPropRecValList *pThisList); +/* Destructor for Rec Val List */ +extern Bool /* True == Error, False == Success */ +SPropRecValList_delete(SDynPropRecValList *pThisList); +/* Read Property File */ +extern Bool /* True == Error, False == Success */ +SPropRecValList_read_prop_file(SDynPropRecValList *pThisList, + char const * const strFileName); +/* Search Property Record */ +extern Bool /* True == Hit, False == Miss */ +SPropRecValList_search_record(SRefPropRecValList *pThisList, + SPropRecValContainer *refContRecVal, + char const * const recordName); +/* Add by Font Cap */ +extern Bool /* True == Error, False == Success */ +SPropRecValList_add_by_font_cap(SDynPropRecValList *pThisList, + char const *strCapHead); + +#ifdef DUMP +void +SPropRecValList_dump(SRefPropRecValList *refList); +#endif + +#define SPropContainer_value_int(contRecVal)\ + ((contRecVal)->uValue.integerValue) +#define SPropContainer_value_dbl(contRecVal)\ + ((contRecVal)->uValue.doubleValue) +#define SPropContainer_value_bool(contRecVal)\ + ((contRecVal)->uValue.boolValue) +#define SPropContainer_value_str(contRecVal)\ + ((contRecVal)->uValue.dynStringValue) + +/****************************************************** + Prototypes (xttmisc) + */ + +/* strdup clone */ +char * XttXstrdup(char const *str); +#undef xstrdup +#define xstrdup(s) XttXstrdup((char const*)s) + +#endif /* !def _XTTCAP_H_ */ + +/* end of file */ diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100755 index 0000000..26551bc --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,68 @@ +# +# Copyright © 2003 Keith Packard, Noah Levitt +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of Keith Packard not be used in +# advertising or publicity pertaining to distribution of the software without +# specific, written prior permission. Keith Packard makes no +# representations about the suitability of this software for any purpose. It +# is provided "as is" without express or implied warranty. +# +# KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +lib_LTLIBRARIES = libXfont.la + +AM_CFLAGS = $(OS_CFLAGS) $(CWARNFLAGS) + +if XFONT_FONTFILE +FONTFILE_DIR = fontfile +FONTFILE_LIB = fontfile/libfontfile.la +endif + +if XFONT_FREETYPE +FREETYPE_DIR = FreeType +FREETYPE_LIB = FreeType/libft.la +endif + +if XFONT_BITMAP +BITMAP_DIR = bitmap +BITMAP_LIB = bitmap/libbitmap.la +endif + +if XFONT_BUILTINS +BUILTINS_DIR = builtins +BUILTINS_LIB = builtins/libbuiltins.la +endif + +if XFONT_FC +FC_DIR = fc +FC_LIB = fc/libfc.la +endif + +UTIL_DIR = util +UTIL_LIB = util/libutil.la + +STUBS_LIB = stubs/libstubs.la +STUBS_DIR = stubs + +SUBDIRS=\ + $(FONTFILE_DIR) $(FREETYPE_DIR) $(BITMAP_DIR) \ + $(BUILTINS_DIR) $(FC_DIR) $(UTIL_DIR) $(STUBS_DIR) + +libXfont_la_LIBADD = \ + $(FONTFILE_LIB) $(FREETYPE_LIB) $(BITMAP_LIB) \ + $(BUILTINS_LIB) $(FC_LIB) $(UTIL_LIB) $(STUBS_LIB) \ + $(FREETYPE_LIBS) $(Z_LIBS) $(MATH_LIBS) $(XFONT_LIBS) + +libXfont_la_SOURCES = dummy.c + +libXfont_la_LDFLAGS = -version-number 1:4:1 diff --git a/src/bitmap/Makefile.am b/src/bitmap/Makefile.am new file mode 100755 index 0000000..b5b9674 --- /dev/null +++ b/src/bitmap/Makefile.am @@ -0,0 +1,19 @@ +INCLUDES = \ + -I${top_srcdir}/include + +AM_CFLAGS = $(XFONT_CFLAGS) $(OS_CFLAGS) $(CWARNFLAGS) + +noinst_LTLIBRARIES = libbitmap.la + +libbitmap_la_SOURCES = \ + bdfread.c \ + bdfutils.c \ + bitmap.c \ + bitmapfunc.c \ + bitmaputil.c \ + bitscale.c \ + fontink.c \ + pcfread.c \ + pcfwrite.c \ + snfread.c \ + snfstr.h diff --git a/src/bitmap/bdfread.c b/src/bitmap/bdfread.c new file mode 100755 index 0000000..2464c03 --- /dev/null +++ b/src/bitmap/bdfread.c @@ -0,0 +1,955 @@ +/************************************************************************ +Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ + +/* + +Copyright 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +/* use bitmap structure */ +#include +#include + +#if HAVE_STDINT_H +#include +#elif !defined(INT32_MAX) +#define INT32_MAX 0x7fffffff +#endif + +#define INDICES 256 +#define MAXENCODING 0xFFFF +#define BDFLINELEN 1024 + +static Bool bdfPadToTerminal(FontPtr pFont); +extern int bdfFileLineNum; + +/***====================================================================***/ + +static Bool +bdfReadBitmap(CharInfoPtr pCI, FontFilePtr file, int bit, int byte, + int glyph, int scan, CARD32 *sizes) +{ + int widthBits, + widthBytes, + widthHexChars; + int height, + row; + int i, + inLineLen, + nextByte; + unsigned char *pInBits, + *picture, + *line = NULL; + unsigned char lineBuf[BDFLINELEN]; + + widthBits = GLYPHWIDTHPIXELS(pCI); + height = GLYPHHEIGHTPIXELS(pCI); + + widthBytes = BYTES_PER_ROW(widthBits, glyph); + if (widthBytes * height > 0) { + picture = malloc(widthBytes * height); + if (!picture) { + bdfError("Couldn't allocate picture (%d*%d)\n", widthBytes, height); + goto BAILOUT; + } + } else + picture = NULL; + pCI->bits = (char *) picture; + + if (sizes) { + for (i = 0; i < GLYPHPADOPTIONS; i++) + sizes[i] += BYTES_PER_ROW(widthBits, (1 << i)) * height; + } + nextByte = 0; + widthHexChars = BYTES_PER_ROW(widthBits, 1); + +/* 5/31/89 (ef) -- hack, hack, hack. what *am* I supposed to do with */ +/* 0 width characters? */ + + for (row = 0; row < height; row++) { + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (!line) + break; + + if (widthBits == 0) { + if ((!line) || (bdfIsPrefix(line, "ENDCHAR"))) + break; + else + continue; + } + pInBits = line; + inLineLen = strlen((char *) pInBits); + + if (inLineLen & 1) { + bdfError("odd number of characters in hex encoding\n"); + line[inLineLen++] = '0'; + line[inLineLen] = '\0'; + } + inLineLen >>= 1; + i = inLineLen; + if (i > widthHexChars) + i = widthHexChars; + for (; i > 0; i--, pInBits += 2) + picture[nextByte++] = bdfHexByte(pInBits); + + /* pad if line is too short */ + if (inLineLen < widthHexChars) { + for (i = widthHexChars - inLineLen; i > 0; i--) + picture[nextByte++] = 0; + } else { + unsigned char mask; + + mask = 0xff << (8 - (widthBits & 0x7)); + if (mask && picture[nextByte - 1] & ~mask) { + picture[nextByte - 1] &= mask; + } + } + + if (widthBytes > widthHexChars) { + i = widthBytes - widthHexChars; + while (i-- > 0) + picture[nextByte++] = 0; + } + } + + if ((line && (!bdfIsPrefix(line, "ENDCHAR"))) || (height == 0)) + line = bdfGetLine(file, lineBuf, BDFLINELEN); + + if ((!line) || (!bdfIsPrefix(line, "ENDCHAR"))) { + bdfError("missing 'ENDCHAR'\n"); + goto BAILOUT; + } + if (nextByte != height * widthBytes) { + bdfError("bytes != rows * bytes_per_row (%d != %d * %d)\n", + nextByte, height, widthBytes); + goto BAILOUT; + } + if (picture != NULL) { + if (bit == LSBFirst) + BitOrderInvert(picture, nextByte); + if (bit != byte) { + if (scan == 2) + TwoByteSwap(picture, nextByte); + else if (scan == 4) + FourByteSwap(picture, nextByte); + } + } + return (TRUE); +BAILOUT: + if (picture) + free(picture); + pCI->bits = NULL; + return (FALSE); +} + +/***====================================================================***/ + +static Bool +bdfSkipBitmap(FontFilePtr file, int height) +{ + unsigned char *line; + int i = 0; + unsigned char lineBuf[BDFLINELEN]; + + do { + line = bdfGetLine(file, lineBuf, BDFLINELEN); + i++; + } while (line && !bdfIsPrefix(line, "ENDCHAR") && i <= height); + + if (i > 1 && line && !bdfIsPrefix(line, "ENDCHAR")) { + bdfError("Error in bitmap, missing 'ENDCHAR'\n"); + return (FALSE); + } + return (TRUE); +} + +/***====================================================================***/ + +static void +bdfFreeFontBits(FontPtr pFont) +{ + BitmapFontPtr bitmapFont; + BitmapExtraPtr bitmapExtra; + int i, nencoding; + + bitmapFont = (BitmapFontPtr) pFont->fontPrivate; + bitmapExtra = (BitmapExtraPtr) bitmapFont->bitmapExtra; + free(bitmapFont->ink_metrics); + if(bitmapFont->encoding) { + nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * + (pFont->info.lastRow - pFont->info.firstRow + 1); + for(i=0; iencoding[i]); + } + free(bitmapFont->encoding); + for (i = 0; i < bitmapFont->num_chars; i++) + free(bitmapFont->metrics[i].bits); + free(bitmapFont->metrics); + if (bitmapExtra) + { + free (bitmapExtra->glyphNames); + free (bitmapExtra->sWidths); + free (bitmapExtra); + } + free(pFont->info.props); + free(bitmapFont); +} + + +static Bool +bdfReadCharacters(FontFilePtr file, FontPtr pFont, bdfFileState *pState, + int bit, int byte, int glyph, int scan) +{ + unsigned char *line; + register CharInfoPtr ci; + int i, + ndx, + nchars, + nignored; + unsigned int char_row, char_col; + int numEncodedGlyphs = 0; + CharInfoPtr *bdfEncoding[256]; + BitmapFontPtr bitmapFont; + BitmapExtraPtr bitmapExtra; + CARD32 *bitmapsSizes; + unsigned char lineBuf[BDFLINELEN]; + int nencoding; + + bitmapFont = (BitmapFontPtr) pFont->fontPrivate; + bitmapExtra = (BitmapExtraPtr) bitmapFont->bitmapExtra; + + if (bitmapExtra) { + bitmapsSizes = bitmapExtra->bitmapsSizes; + for (i = 0; i < GLYPHPADOPTIONS; i++) + bitmapsSizes[i] = 0; + } else + bitmapsSizes = NULL; + + bzero(bdfEncoding, sizeof(bdfEncoding)); + bitmapFont->metrics = NULL; + ndx = 0; + + line = bdfGetLine(file, lineBuf, BDFLINELEN); + + if ((!line) || (sscanf((char *) line, "CHARS %d", &nchars) != 1)) { + bdfError("bad 'CHARS' in bdf file\n"); + return (FALSE); + } + if (nchars < 1) { + bdfError("invalid number of CHARS in BDF file\n"); + return (FALSE); + } + if (nchars > INT32_MAX / sizeof(CharInfoRec)) { + bdfError("Couldn't allocate pCI (%d*%d)\n", nchars, + sizeof(CharInfoRec)); + goto BAILOUT; + } + ci = calloc(nchars, sizeof(CharInfoRec)); + if (!ci) { + bdfError("Couldn't allocate pCI (%d*%d)\n", nchars, + sizeof(CharInfoRec)); + goto BAILOUT; + } + bitmapFont->metrics = ci; + + if (bitmapExtra) { + bitmapExtra->glyphNames = malloc(nchars * sizeof(Atom)); + if (!bitmapExtra->glyphNames) { + bdfError("Couldn't allocate glyphNames (%d*%d)\n", + nchars, sizeof(Atom)); + goto BAILOUT; + } + } + if (bitmapExtra) { + bitmapExtra->sWidths = malloc(nchars * sizeof(int)); + if (!bitmapExtra->sWidths) { + bdfError("Couldn't allocate sWidth (%d *%d)\n", + nchars, sizeof(int)); + return FALSE; + } + } + line = bdfGetLine(file, lineBuf, BDFLINELEN); + pFont->info.firstRow = 256; + pFont->info.lastRow = 0; + pFont->info.firstCol = 256; + pFont->info.lastCol = 0; + nignored = 0; + for (ndx = 0; (ndx < nchars) && (line) && (bdfIsPrefix(line, "STARTCHAR"));) { + int t; + int wx; /* x component of width */ + int wy; /* y component of width */ + int bw; /* bounding-box width */ + int bh; /* bounding-box height */ + int bl; /* bounding-box left */ + int bb; /* bounding-box bottom */ + int enc, + enc2; /* encoding */ + unsigned char *p; /* temp pointer into line */ + char charName[100]; + int ignore; + + if (sscanf((char *) line, "STARTCHAR %s", charName) != 1) { + bdfError("bad character name in BDF file\n"); + goto BAILOUT; /* bottom of function, free and return error */ + } + if (bitmapExtra) + bitmapExtra->glyphNames[ndx] = bdfForceMakeAtom(charName, NULL); + + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (!line || (t = sscanf((char *) line, "ENCODING %d %d", &enc, &enc2)) < 1) { + bdfError("bad 'ENCODING' in BDF file\n"); + goto BAILOUT; + } + if (enc < -1 || (t == 2 && enc2 < -1)) { + bdfError("bad ENCODING value"); + goto BAILOUT; + } + if (t == 2 && enc == -1) + enc = enc2; + ignore = 0; + if (enc == -1) { + if (!bitmapExtra) { + nignored++; + ignore = 1; + } + } else if (enc > MAXENCODING) { + bdfError("char '%s' has encoding too large (%d)\n", + charName, enc); + } else { + char_row = (enc >> 8) & 0xFF; + char_col = enc & 0xFF; + if (char_row < pFont->info.firstRow) + pFont->info.firstRow = char_row; + if (char_row > pFont->info.lastRow) + pFont->info.lastRow = char_row; + if (char_col < pFont->info.firstCol) + pFont->info.firstCol = char_col; + if (char_col > pFont->info.lastCol) + pFont->info.lastCol = char_col; + if (bdfEncoding[char_row] == (CharInfoPtr *) NULL) { + bdfEncoding[char_row] = malloc(256 * sizeof(CharInfoPtr)); + if (!bdfEncoding[char_row]) { + bdfError("Couldn't allocate row %d of encoding (%d*%d)\n", + char_row, INDICES, sizeof(CharInfoPtr)); + goto BAILOUT; + } + for (i = 0; i < 256; i++) + bdfEncoding[char_row][i] = (CharInfoPtr) NULL; + } + if (bdfEncoding[char_row] != NULL) { + bdfEncoding[char_row][char_col] = ci; + numEncodedGlyphs++; + } + } + + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if ((!line) || (sscanf((char *) line, "SWIDTH %d %d", &wx, &wy) != 2)) { + bdfError("bad 'SWIDTH'\n"); + goto BAILOUT; + } + if (wy != 0) { + bdfError("SWIDTH y value must be zero\n"); + goto BAILOUT; + } + if (bitmapExtra) + bitmapExtra->sWidths[ndx] = wx; + +/* 5/31/89 (ef) -- we should be able to ditch the character and recover */ +/* from all of these. */ + + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if ((!line) || (sscanf((char *) line, "DWIDTH %d %d", &wx, &wy) != 2)) { + bdfError("bad 'DWIDTH'\n"); + goto BAILOUT; + } + if (wy != 0) { + bdfError("DWIDTH y value must be zero\n"); + goto BAILOUT; + } + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if ((!line) || (sscanf((char *) line, "BBX %d %d %d %d", &bw, &bh, &bl, &bb) != 4)) { + bdfError("bad 'BBX'\n"); + goto BAILOUT; + } + if ((bh < 0) || (bw < 0)) { + bdfError("character '%s' has a negative sized bitmap, %dx%d\n", + charName, bw, bh); + goto BAILOUT; + } + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if ((line) && (bdfIsPrefix(line, "ATTRIBUTES"))) { + for (p = line + strlen("ATTRIBUTES "); + (*p == ' ') || (*p == '\t'); + p++) + /* empty for loop */ ; + ci->metrics.attributes = (bdfHexByte(p) << 8) + bdfHexByte(p + 2); + line = bdfGetLine(file, lineBuf, BDFLINELEN); + } else + ci->metrics.attributes = 0; + + if (!line || !bdfIsPrefix(line, "BITMAP")) { + bdfError("missing 'BITMAP'\n"); + goto BAILOUT; + } + /* collect data for generated properties */ + if ((strlen(charName) == 1)) { + if ((charName[0] >= '0') && (charName[0] <= '9')) { + pState->digitWidths += wx; + pState->digitCount++; + } else if (charName[0] == 'x') { + pState->exHeight = (bh + bb) <= 0 ? bh : bh + bb; + } + } + if (!ignore) { + ci->metrics.leftSideBearing = bl; + ci->metrics.rightSideBearing = bl + bw; + ci->metrics.ascent = bh + bb; + ci->metrics.descent = -bb; + ci->metrics.characterWidth = wx; + ci->bits = NULL; + bdfReadBitmap(ci, file, bit, byte, glyph, scan, bitmapsSizes); + ci++; + ndx++; + } else + bdfSkipBitmap(file, bh); + + line = bdfGetLine(file, lineBuf, BDFLINELEN); /* get STARTCHAR or + * ENDFONT */ + } + + if (ndx + nignored != nchars) { + bdfError("%d too few characters\n", nchars - (ndx + nignored)); + goto BAILOUT; + } + nchars = ndx; + bitmapFont->num_chars = nchars; + if ((line) && (bdfIsPrefix(line, "STARTCHAR"))) { + bdfError("more characters than specified\n"); + goto BAILOUT; + } + if ((!line) || (!bdfIsPrefix(line, "ENDFONT"))) { + bdfError("missing 'ENDFONT'\n"); + goto BAILOUT; + } + if (numEncodedGlyphs == 0) + bdfWarning("No characters with valid encodings\n"); + + nencoding = (pFont->info.lastRow - pFont->info.firstRow + 1) * + (pFont->info.lastCol - pFont->info.firstCol + 1); + bitmapFont->encoding = calloc(NUM_SEGMENTS(nencoding),sizeof(CharInfoPtr*)); + if (!bitmapFont->encoding) { + bdfError("Couldn't allocate ppCI (%d,%d)\n", + NUM_SEGMENTS(nencoding), + sizeof(CharInfoPtr*)); + goto BAILOUT; + } + pFont->info.allExist = TRUE; + i = 0; + for (char_row = pFont->info.firstRow; + char_row <= pFont->info.lastRow; + char_row++) { + if (bdfEncoding[char_row] == (CharInfoPtr *) NULL) { + pFont->info.allExist = FALSE; + i += pFont->info.lastCol - pFont->info.firstCol + 1; + } else { + for (char_col = pFont->info.firstCol; + char_col <= pFont->info.lastCol; + char_col++) { + if (!bdfEncoding[char_row][char_col]) + pFont->info.allExist = FALSE; + else { + if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) { + bitmapFont->encoding[SEGMENT_MAJOR(i)]= + calloc(BITMAP_FONT_SEGMENT_SIZE, + sizeof(CharInfoPtr)); + if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) + goto BAILOUT; + } + ACCESSENCODINGL(bitmapFont->encoding,i) = + bdfEncoding[char_row][char_col]; + } + i++; + } + } + } + for (i = 0; i < 256; i++) + if (bdfEncoding[i]) + free(bdfEncoding[i]); + return (TRUE); +BAILOUT: + for (i = 0; i < 256; i++) + if (bdfEncoding[i]) + free(bdfEncoding[i]); + /* bdfFreeFontBits will clean up the rest */ + return (FALSE); +} + +/***====================================================================***/ + +static Bool +bdfReadHeader(FontFilePtr file, bdfFileState *pState) +{ + unsigned char *line; + char namebuf[BDFLINELEN]; + unsigned char lineBuf[BDFLINELEN]; + + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (!line || sscanf((char *) line, "STARTFONT %s", namebuf) != 1 || + !bdfStrEqual(namebuf, "2.1")) { + bdfError("bad 'STARTFONT'\n"); + return (FALSE); + } + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (!line || sscanf((char *) line, "FONT %[^\n]", pState->fontName) != 1) { + bdfError("bad 'FONT'\n"); + return (FALSE); + } + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (!line || !bdfIsPrefix(line, "SIZE")) { + bdfError("missing 'SIZE'\n"); + return (FALSE); + } + if (sscanf((char *) line, "SIZE %f%d%d", &pState->pointSize, + &pState->resolution_x, &pState->resolution_y) != 3) { + bdfError("bad 'SIZE'\n"); + return (FALSE); + } + if (pState->pointSize < 1 || + pState->resolution_x < 1 || pState->resolution_y < 1) { + bdfError("SIZE values must be > 0\n"); + return (FALSE); + } + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (!line || !bdfIsPrefix(line, "FONTBOUNDINGBOX")) { + bdfError("missing 'FONTBOUNDINGBOX'\n"); + return (FALSE); + } + return (TRUE); +} + +/***====================================================================***/ + +static Bool +bdfReadProperties(FontFilePtr file, FontPtr pFont, bdfFileState *pState) +{ + int nProps, props_left, + nextProp; + char *stringProps; + FontPropPtr props; + char namebuf[BDFLINELEN], + secondbuf[BDFLINELEN], + thirdbuf[BDFLINELEN]; + unsigned char *line; + unsigned char lineBuf[BDFLINELEN]; + BitmapFontPtr bitmapFont = (BitmapFontPtr) pFont->fontPrivate; + + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (!line || !bdfIsPrefix(line, "STARTPROPERTIES")) { + bdfError("missing 'STARTPROPERTIES'\n"); + return (FALSE); + } + if (sscanf((char *) line, "STARTPROPERTIES %d", &nProps) != 1) { + bdfError("bad 'STARTPROPERTIES'\n"); + return (FALSE); + } + pFont->info.isStringProp = NULL; + pFont->info.props = NULL; + pFont->info.nprops = 0; + + stringProps = malloc((nProps + BDF_GENPROPS) * sizeof(char)); + pFont->info.isStringProp = stringProps; + if (stringProps == NULL) { + bdfError("Couldn't allocate stringProps (%d*%d)\n", + (nProps + BDF_GENPROPS), sizeof(Bool)); + goto BAILOUT; + } + pFont->info.props = props = calloc(nProps + BDF_GENPROPS, + sizeof(FontPropRec)); + if (props == NULL) { + bdfError("Couldn't allocate props (%d*%d)\n", nProps + BDF_GENPROPS, + sizeof(FontPropRec)); + goto BAILOUT; + } + + nextProp = 0; + props_left = nProps; + while (props_left-- > 0) { + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (line == NULL || bdfIsPrefix(line, "ENDPROPERTIES")) { + bdfError("\"STARTPROPERTIES %d\" followed by only %d properties\n", + nProps, nProps - props_left - 1); + goto BAILOUT; + } + while (*line && isspace(*line)) + line++; + + switch (sscanf((char *) line, "%s%s%s", namebuf, secondbuf, thirdbuf)) { + default: + bdfError("missing '%s' parameter value\n", namebuf); + goto BAILOUT; + + case 2: + /* + * Possibilites include: valid quoted string with no white space + * valid integer value invalid value + */ + if (secondbuf[0] == '"') { + stringProps[nextProp] = TRUE; + props[nextProp].value = + bdfGetPropertyValue((char *)line + strlen(namebuf) + 1); + if (!props[nextProp].value) + goto BAILOUT; + break; + } else if (bdfIsInteger(secondbuf)) { + stringProps[nextProp] = FALSE; + props[nextProp].value = atoi(secondbuf); + break; + } else { + bdfError("invalid '%s' parameter value\n", namebuf); + goto BAILOUT; + } + + case 3: + /* + * Possibilites include: valid quoted string with some white space + * invalid value (reject even if second string is integer) + */ + if (secondbuf[0] == '"') { + stringProps[nextProp] = TRUE; + props[nextProp].value = + bdfGetPropertyValue((char *)line + strlen(namebuf) + 1); + if (!props[nextProp].value) + goto BAILOUT; + break; + } else { + bdfError("invalid '%s' parameter value\n", namebuf); + goto BAILOUT; + } + } + props[nextProp].name = bdfForceMakeAtom(namebuf, NULL); + if (props[nextProp].name == None) { + bdfError("Empty property name.\n"); + goto BAILOUT; + } + if (!bdfSpecialProperty(pFont, &props[nextProp], + stringProps[nextProp], pState)) + nextProp++; + } + + line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (!line || !bdfIsPrefix(line, "ENDPROPERTIES")) { + bdfError("missing 'ENDPROPERTIES'\n"); + goto BAILOUT; + } + if (!pState->haveFontAscent || !pState->haveFontDescent) { + bdfError("missing 'FONT_ASCENT' or 'FONT_DESCENT' properties\n"); + goto BAILOUT; + } + if (bitmapFont->bitmapExtra) { + bitmapFont->bitmapExtra->info.fontAscent = pFont->info.fontAscent; + bitmapFont->bitmapExtra->info.fontDescent = pFont->info.fontDescent; + } + if (!pState->pointSizeProp) { + props[nextProp].name = bdfForceMakeAtom("POINT_SIZE", NULL); + props[nextProp].value = (INT32) (pState->pointSize * 10.0); + stringProps[nextProp] = FALSE; + pState->pointSizeProp = &props[nextProp]; + nextProp++; + } + if (!pState->fontProp) { + props[nextProp].name = bdfForceMakeAtom("FONT", NULL); + props[nextProp].value = (INT32) bdfForceMakeAtom(pState->fontName, NULL); + stringProps[nextProp] = TRUE; + pState->fontProp = &props[nextProp]; + nextProp++; + } + if (!pState->weightProp) { + props[nextProp].name = bdfForceMakeAtom("WEIGHT", NULL); + props[nextProp].value = -1; /* computed later */ + stringProps[nextProp] = FALSE; + pState->weightProp = &props[nextProp]; + nextProp++; + } + if (!pState->resolutionProp && + pState->resolution_x == pState->resolution_y) { + props[nextProp].name = bdfForceMakeAtom("RESOLUTION", NULL); + props[nextProp].value = (INT32) ((pState->resolution_x * 100.0) / 72.27); + stringProps[nextProp] = FALSE; + pState->resolutionProp = &props[nextProp]; + nextProp++; + } + if (!pState->resolutionXProp) { + props[nextProp].name = bdfForceMakeAtom("RESOLUTION_X", NULL); + props[nextProp].value = (INT32) pState->resolution_x; + stringProps[nextProp] = FALSE; + pState->resolutionProp = &props[nextProp]; + nextProp++; + } + if (!pState->resolutionYProp) { + props[nextProp].name = bdfForceMakeAtom("RESOLUTION_Y", NULL); + props[nextProp].value = (INT32) pState->resolution_y; + stringProps[nextProp] = FALSE; + pState->resolutionProp = &props[nextProp]; + nextProp++; + } + if (!pState->xHeightProp) { + props[nextProp].name = bdfForceMakeAtom("X_HEIGHT", NULL); + props[nextProp].value = -1; /* computed later */ + stringProps[nextProp] = FALSE; + pState->xHeightProp = &props[nextProp]; + nextProp++; + } + if (!pState->quadWidthProp) { + props[nextProp].name = bdfForceMakeAtom("QUAD_WIDTH", NULL); + props[nextProp].value = -1; /* computed later */ + stringProps[nextProp] = FALSE; + pState->quadWidthProp = &props[nextProp]; + nextProp++; + } + pFont->info.nprops = nextProp; + return (TRUE); +BAILOUT: + if (pFont->info.isStringProp) { + free(pFont->info.isStringProp); + pFont->info.isStringProp = NULL; + } + if (pFont->info.props) { + free(pFont->info.props); + pFont->info.props = NULL; + } + while (line && bdfIsPrefix(line, "ENDPROPERTIES")) + line = bdfGetLine(file, lineBuf, BDFLINELEN); + return (FALSE); +} + +/***====================================================================***/ + +static void +bdfUnloadFont(FontPtr pFont) +{ + bdfFreeFontBits (pFont); + DestroyFontRec(pFont); +} + +int +bdfReadFont(FontPtr pFont, FontFilePtr file, + int bit, int byte, int glyph, int scan) +{ + bdfFileState state; + xCharInfo *min, + *max; + BitmapFontPtr bitmapFont; + + pFont->fontPrivate = 0; + + bzero(&state, sizeof(bdfFileState)); + bdfFileLineNum = 0; + + if (!bdfReadHeader(file, &state)) + goto BAILOUT; + + bitmapFont = calloc(1, sizeof(BitmapFontRec)); + if (!bitmapFont) { + bdfError("Couldn't allocate bitmapFontRec (%d)\n", sizeof(BitmapFontRec)); + goto BAILOUT; + } + + pFont->fontPrivate = (pointer) bitmapFont; + bitmapFont->metrics = 0; + bitmapFont->ink_metrics = 0; + bitmapFont->bitmaps = 0; + bitmapFont->encoding = 0; + bitmapFont->pDefault = NULL; + + bitmapFont->bitmapExtra = calloc(1, sizeof(BitmapExtraRec)); + if (!bitmapFont->bitmapExtra) { + bdfError("Couldn't allocate bitmapExtra (%d)\n", sizeof(BitmapExtraRec)); + goto BAILOUT; + } + + bitmapFont->bitmapExtra->glyphNames = 0; + bitmapFont->bitmapExtra->sWidths = 0; + + if (!bdfReadProperties(file, pFont, &state)) + goto BAILOUT; + + if (!bdfReadCharacters(file, pFont, &state, bit, byte, glyph, scan)) + goto BAILOUT; + + if (state.haveDefaultCh) { + unsigned int r, c, cols; + + r = pFont->info.defaultCh >> 8; + c = pFont->info.defaultCh & 0xFF; + if (pFont->info.firstRow <= r && r <= pFont->info.lastRow && + pFont->info.firstCol <= c && c <= pFont->info.lastCol) { + cols = pFont->info.lastCol - pFont->info.firstCol + 1; + r = r - pFont->info.firstRow; + c = c - pFont->info.firstCol; + bitmapFont->pDefault = ACCESSENCODING(bitmapFont->encoding, + r * cols + c); + } + } + pFont->bit = bit; + pFont->byte = byte; + pFont->glyph = glyph; + pFont->scan = scan; + pFont->info.anamorphic = FALSE; + pFont->info.cachable = TRUE; + bitmapComputeFontBounds(pFont); + if (FontCouldBeTerminal(&pFont->info)) { + bdfPadToTerminal(pFont); + bitmapComputeFontBounds(pFont); + } + FontComputeInfoAccelerators(&pFont->info); + if (bitmapFont->bitmapExtra) + FontComputeInfoAccelerators(&bitmapFont->bitmapExtra->info); + if (pFont->info.constantMetrics) { + if (!bitmapAddInkMetrics(pFont)) { + bdfError("Failed to add bitmap ink metrics\n"); + goto BAILOUT; + } + } + if (bitmapFont->bitmapExtra) + bitmapFont->bitmapExtra->info.inkMetrics = pFont->info.inkMetrics; + + bitmapComputeFontInkBounds(pFont); +/* ComputeFontAccelerators (pFont); */ + + /* generate properties */ + min = &pFont->info.ink_minbounds; + max = &pFont->info.ink_maxbounds; + if (state.xHeightProp && (state.xHeightProp->value == -1)) + state.xHeightProp->value = state.exHeight ? + state.exHeight : min->ascent; + + if (state.quadWidthProp && (state.quadWidthProp->value == -1)) + state.quadWidthProp->value = state.digitCount ? + (INT32) (state.digitWidths / state.digitCount) : + (min->characterWidth + max->characterWidth) / 2; + + if (state.weightProp && (state.weightProp->value == -1)) + state.weightProp->value = bitmapComputeWeight(pFont); + + pFont->get_glyphs = bitmapGetGlyphs; + pFont->get_metrics = bitmapGetMetrics; + pFont->unload_font = bdfUnloadFont; + pFont->unload_glyphs = NULL; + return Successful; +BAILOUT: + if (pFont->fontPrivate) + bdfFreeFontBits (pFont); + return AllocError; +} + +int +bdfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file) +{ + FontRec font; + int ret; + + bzero(&font, sizeof (FontRec)); + + ret = bdfReadFont(&font, file, MSBFirst, LSBFirst, 1, 1); + if (ret == Successful) { + *pFontInfo = font.info; + font.info.props = 0; + font.info.isStringProp = 0; + font.info.nprops = 0; + bdfFreeFontBits (&font); + } + return ret; +} + +static Bool +bdfPadToTerminal(FontPtr pFont) +{ + BitmapFontPtr bitmapFont; + BitmapExtraPtr bitmapExtra; + int i; + int new_size; + CharInfoRec new; + int w, + h; + + bitmapFont = (BitmapFontPtr) pFont->fontPrivate; + + bzero(&new, sizeof(CharInfoRec)); + new.metrics.ascent = pFont->info.fontAscent; + new.metrics.descent = pFont->info.fontDescent; + new.metrics.leftSideBearing = 0; + new.metrics.rightSideBearing = pFont->info.minbounds.characterWidth; + new.metrics.characterWidth = new.metrics.rightSideBearing; + new_size = BYTES_FOR_GLYPH(&new, pFont->glyph); + + for (i = 0; i < bitmapFont->num_chars; i++) { + new.bits = malloc(new_size); + if (!new.bits) { + bdfError("Couldn't allocate bits (%d)\n", new_size); + return FALSE; + } + FontCharReshape(pFont, &bitmapFont->metrics[i], &new); + new.metrics.attributes = bitmapFont->metrics[i].metrics.attributes; + free(bitmapFont->metrics[i].bits); + bitmapFont->metrics[i] = new; + } + bitmapExtra = bitmapFont->bitmapExtra; + if (bitmapExtra) { + w = GLYPHWIDTHPIXELS(&new); + h = GLYPHHEIGHTPIXELS(&new); + for (i = 0; i < GLYPHPADOPTIONS; i++) + bitmapExtra->bitmapsSizes[i] = bitmapFont->num_chars * + (BYTES_PER_ROW(w, 1 << i) * h); + } + return TRUE; +} diff --git a/src/bitmap/bdfutils.c b/src/bitmap/bdfutils.c new file mode 100755 index 0000000..1d6cc72 --- /dev/null +++ b/src/bitmap/bdfutils.c @@ -0,0 +1,336 @@ +/************************************************************************ +Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ + +/* + +Copyright 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include +/* use bitmap structure */ +#include +#include + +int bdfFileLineNum; + +/***====================================================================***/ + +void +bdfError(char* message, ...) +{ + va_list args; + + va_start (args, message); + fprintf(stderr, "BDF Error on line %d: ", bdfFileLineNum); + vfprintf(stderr, message, args); + va_end (args); +} + +/***====================================================================***/ + +void +bdfWarning(char *message, ...) +{ + va_list args; + + va_start (args, message); + fprintf(stderr, "BDF Warning on line %d: ", bdfFileLineNum); + vfprintf(stderr, message, args); + va_end (args); +} + +/* + * read the next (non-comment) line and keep a count for error messages. + * Returns buf, or NULL if EOF. + */ + +unsigned char * +bdfGetLine(FontFilePtr file, unsigned char *buf, int len) +{ + int c; + unsigned char *b; + + for (;;) { + b = buf; + while ((c = FontFileGetc(file)) != FontFileEOF) { + if (c == '\r') + continue; + if (c == '\n') { + bdfFileLineNum++; + break; + } + if (b - buf >= (len - 1)) + break; + *b++ = c; + } + *b = '\0'; + if (c == FontFileEOF) + return NULL; + if (b != buf && !bdfIsPrefix(buf, "COMMENT")) + break; + } + return buf; +} + +/***====================================================================***/ + +Atom +bdfForceMakeAtom(char *str, int *size) +{ + register int len = strlen(str); + Atom the_atom; + + if (size != NULL) + *size += len + 1; + the_atom = MakeAtom(str, len, TRUE); + if (the_atom == None) + bdfError("Atom allocation failed\n"); + return the_atom; +} + +/***====================================================================***/ + +/* + * Handle quoted strings. + */ + +Atom +bdfGetPropertyValue(char *s) +{ + register char *p, + *pp; + char *orig_s = s; + Atom atom; + + /* strip leading white space */ + while (*s && (*s == ' ' || *s == '\t')) + s++; + if (*s == 0) { + return bdfForceMakeAtom(s, NULL); + } + if (*s != '"') { + pp = s; + /* no white space in value */ + for (pp = s; *pp; pp++) + if (*pp == ' ' || *pp == '\t' || *pp == '\015' || *pp == '\n') { + *pp = 0; + break; + } + return bdfForceMakeAtom(s, NULL); + } + /* quoted string: strip outer quotes and undouble inner quotes */ + s++; + pp = p = malloc((unsigned) strlen(s) + 1); + if (pp == NULL) { + bdfError("Couldn't allocate property value string (%d)\n", strlen(s) + 1); + return None; + } + while (*s) { + if (*s == '"') { + if (*(s + 1) != '"') { + *p++ = 0; + atom = bdfForceMakeAtom(pp, NULL); + free(pp); + return atom; + } else { + s++; + } + } + *p++ = *s++; + } + free (pp); + bdfError("unterminated quoted string property: %s\n", (pointer) orig_s); + return None; +} + +/***====================================================================***/ + +/* + * return TRUE if string is a valid integer + */ +int +bdfIsInteger(char *str) +{ + char c; + + c = *str++; + if (!(isdigit(c) || c == '-' || c == '+')) + return (FALSE); + + while ((c = *str++)) + if (!isdigit(c)) + return (FALSE); + + return (TRUE); +} + +/***====================================================================***/ + +/* + * make a byte from the first two hex characters in glyph picture + */ + +unsigned char +bdfHexByte(unsigned char *s) +{ + unsigned char b = 0; + register char c; + int i; + + for (i = 2; i; i--) { + c = *s++; + if ((c >= '0') && (c <= '9')) + b = (b << 4) + (c - '0'); + else if ((c >= 'A') && (c <= 'F')) + b = (b << 4) + 10 + (c - 'A'); + else if ((c >= 'a') && (c <= 'f')) + b = (b << 4) + 10 + (c - 'a'); + else + bdfError("bad hex char '%c'", c); + } + return b; +} + +/***====================================================================***/ + +/* + * check for known special property values + */ + +static char *SpecialAtoms[] = { + "FONT_ASCENT", +#define BDF_FONT_ASCENT 0 + "FONT_DESCENT", +#define BDF_FONT_DESCENT 1 + "DEFAULT_CHAR", +#define BDF_DEFAULT_CHAR 2 + "POINT_SIZE", +#define BDF_POINT_SIZE 3 + "RESOLUTION", +#define BDF_RESOLUTION 4 + "X_HEIGHT", +#define BDF_X_HEIGHT 5 + "WEIGHT", +#define BDF_WEIGHT 6 + "QUAD_WIDTH", +#define BDF_QUAD_WIDTH 7 + "FONT", +#define BDF_FONT 8 + "RESOLUTION_X", +#define BDF_RESOLUTION_X 9 + "RESOLUTION_Y", +#define BDF_RESOLUTION_Y 10 + 0, +}; + +Bool +bdfSpecialProperty(FontPtr pFont, FontPropPtr prop, + char isString, bdfFileState *bdfState) +{ + char **special; + char *name; + + name = NameForAtom(prop->name); + for (special = SpecialAtoms; *special; special++) + if (!strcmp(name, *special)) + break; + + switch (special - SpecialAtoms) { + case BDF_FONT_ASCENT: + if (!isString) { + pFont->info.fontAscent = prop->value; + bdfState->haveFontAscent = TRUE; + } + return TRUE; + case BDF_FONT_DESCENT: + if (!isString) { + pFont->info.fontDescent = prop->value; + bdfState->haveFontDescent = TRUE; + } + return TRUE; + case BDF_DEFAULT_CHAR: + if (!isString) { + pFont->info.defaultCh = prop->value; + bdfState->haveDefaultCh = TRUE; + } + return TRUE; + case BDF_POINT_SIZE: + bdfState->pointSizeProp = prop; + return FALSE; + case BDF_RESOLUTION: + bdfState->resolutionProp = prop; + return FALSE; + case BDF_X_HEIGHT: + bdfState->xHeightProp = prop; + return FALSE; + case BDF_WEIGHT: + bdfState->weightProp = prop; + return FALSE; + case BDF_QUAD_WIDTH: + bdfState->quadWidthProp = prop; + return FALSE; + case BDF_FONT: + bdfState->fontProp = prop; + return FALSE; + case BDF_RESOLUTION_X: + bdfState->resolutionXProp = prop; + return FALSE; + case BDF_RESOLUTION_Y: + bdfState->resolutionYProp = prop; + return FALSE; + default: + return FALSE; + } +} diff --git a/src/bitmap/bitmap.c b/src/bitmap/bitmap.c new file mode 100755 index 0000000..1ceb4bb --- /dev/null +++ b/src/bitmap/bitmap.c @@ -0,0 +1,157 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +int +bitmapGetGlyphs(FontPtr pFont, unsigned long count, unsigned char *chars, + FontEncoding charEncoding, + unsigned long *glyphCount, /* RETURN */ + CharInfoPtr *glyphs) /* RETURN */ +{ + BitmapFontPtr bitmapFont; + unsigned int firstCol; + register unsigned int numCols; + unsigned int firstRow; + unsigned int numRows; + CharInfoPtr *glyphsBase; + register unsigned int c; + register CharInfoPtr pci; + unsigned int r; + CharInfoPtr **encoding; + CharInfoPtr pDefault; + + bitmapFont = (BitmapFontPtr) pFont->fontPrivate; + encoding = bitmapFont->encoding; + pDefault = bitmapFont->pDefault; + firstCol = pFont->info.firstCol; + numCols = pFont->info.lastCol - firstCol + 1; + glyphsBase = glyphs; + switch (charEncoding) { + + case Linear8Bit: + case TwoD8Bit: + if (pFont->info.firstRow > 0) + break; + if (pFont->info.allExist && pDefault) { + while (count--) { + c = (*chars++) - firstCol; + if (c < numCols) + *glyphs++ = ACCESSENCODING(encoding,c); + else + *glyphs++ = pDefault; + } + } else { + while (count--) { + c = (*chars++) - firstCol; + if (c < numCols && (pci = ACCESSENCODING(encoding,c))) + *glyphs++ = pci; + else if (pDefault) + *glyphs++ = pDefault; + } + } + break; + case Linear16Bit: + if (pFont->info.allExist && pDefault) { + while (count--) { + c = *chars++ << 8; + c = (c | *chars++) - firstCol; + if (c < numCols) + *glyphs++ = ACCESSENCODING(encoding,c); + else + *glyphs++ = pDefault; + } + } else { + while (count--) { + c = *chars++ << 8; + c = (c | *chars++) - firstCol; + if (c < numCols && (pci = ACCESSENCODING(encoding,c))) + *glyphs++ = pci; + else if (pDefault) + *glyphs++ = pDefault; + } + } + break; + + case TwoD16Bit: + firstRow = pFont->info.firstRow; + numRows = pFont->info.lastRow - firstRow + 1; + while (count--) { + r = (*chars++) - firstRow; + c = (*chars++) - firstCol; + if (r < numRows && c < numCols && + (pci = ACCESSENCODING(encoding, r * numCols + c))) + *glyphs++ = pci; + else if (pDefault) + *glyphs++ = pDefault; + } + break; + } + *glyphCount = glyphs - glyphsBase; + return Successful; +} + +static CharInfoRec nonExistantChar; + +int +bitmapGetMetrics(FontPtr pFont, unsigned long count, unsigned char *chars, + FontEncoding charEncoding, + unsigned long *glyphCount, /* RETURN */ + xCharInfo **glyphs) /* RETURN */ +{ + int ret; + xCharInfo *ink_metrics; + CharInfoPtr metrics; + BitmapFontPtr bitmapFont; + CharInfoPtr oldDefault; + int i; + + bitmapFont = (BitmapFontPtr) pFont->fontPrivate; + oldDefault = bitmapFont->pDefault; + bitmapFont->pDefault = &nonExistantChar; + ret = bitmapGetGlyphs(pFont, count, chars, charEncoding, glyphCount, (CharInfoPtr *) glyphs); + if (ret == Successful) { + if (bitmapFont->ink_metrics) { + metrics = bitmapFont->metrics; + ink_metrics = bitmapFont->ink_metrics; + for (i = 0; i < *glyphCount; i++) { + if (glyphs[i] != (xCharInfo *) & nonExistantChar) + glyphs[i] = ink_metrics + (((CharInfoPtr) glyphs[i]) - metrics); + } + } + } + bitmapFont->pDefault = oldDefault; + return ret; +} diff --git a/src/bitmap/bitmapfunc.c b/src/bitmap/bitmapfunc.c new file mode 100755 index 0000000..47ce488 --- /dev/null +++ b/src/bitmap/bitmapfunc.c @@ -0,0 +1,254 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +/* + * Translate monolithic #defines to modular definitions + */ + +#ifdef PCFFORMAT +#define XFONT_PCFFORMAT 1 +#endif + +#ifdef SNFFORMAT +#define XFONT_SNFFORMAT 1 +#endif + +#ifdef BDFFORMAT +#define XFONT_BDFFORMAT 1 +#endif + +#include +#include +#include +#include +#include +#include "snfstr.h" + +typedef struct _BitmapFileFunctions { + int (*ReadFont) (FontPtr /* pFont */, FontFilePtr /* file */, + int /* bit */, int /* byte */, + int /* glyph */, int /* scan */); + int (*ReadInfo) ( FontInfoPtr /* pFontInfo */, + FontFilePtr /* file */ ); +} BitmapFileFunctionsRec, *BitmapFileFunctionsPtr; + +static int BitmapGetRenderIndex(FontRendererPtr renderer); + +/* + * the readers[] and renderers[] arrays must be in the same order, + * and also in the same order as scale[] and find_scale[] in bitscale.c + * + */ +static BitmapFileFunctionsRec readers[] = { +#if XFONT_PCFFORMAT + { pcfReadFont, pcfReadFontInfo} , + { pcfReadFont, pcfReadFontInfo} , +# ifdef X_GZIP_FONT_COMPRESSION + { pcfReadFont, pcfReadFontInfo} , +# endif +# ifdef X_BZIP2_FONT_COMPRESSION + { pcfReadFont, pcfReadFontInfo} , +# endif +#endif +#if XFONT_SNFFORMAT + { snfReadFont, snfReadFontInfo}, + { snfReadFont, snfReadFontInfo}, +# ifdef X_GZIP_FONT_COMPRESSION + { snfReadFont, snfReadFontInfo} , +# endif +# ifdef X_BZIP2_FONT_COMPRESSION + { snfReadFont, snfReadFontInfo} , +# endif +#endif +#if XFONT_BDFFORMAT + { bdfReadFont, bdfReadFontInfo} , + { bdfReadFont, bdfReadFontInfo} , +# ifdef X_GZIP_FONT_COMPRESSION + { bdfReadFont, bdfReadFontInfo} , +# endif +# ifdef X_BZIP2_FONT_COMPRESSION + { bdfReadFont, bdfReadFontInfo} , +# endif +#endif +}; + + +#define CAPABILITIES (CAP_MATRIX | CAP_CHARSUBSETTING) + +static int +BitmapOpenBitmap (FontPathElementPtr fpe, FontPtr *ppFont, int flags, + FontEntryPtr entry, char *fileName, + fsBitmapFormat format, fsBitmapFormatMask fmask, + FontPtr non_cachable_font) /* We don't do licensing */ +{ + FontFilePtr file; + FontPtr pFont; + int i; + int ret; + int bit, + byte, + glyph, + scan, + image; + + i = BitmapGetRenderIndex(entry->u.bitmap.renderer); + file = FontFileOpen (fileName); + if (!file) + return BadFontName; + if (!(pFont = CreateFontRec())) { + fprintf(stderr, "Error: Couldn't allocate pFont (%ld)\n", + (unsigned long)sizeof(FontRec)); + FontFileClose (file); + return AllocError; + } + /* set up default values */ + FontDefaultFormat(&bit, &byte, &glyph, &scan); + /* get any changes made from above */ + ret = CheckFSFormat(format, fmask, &bit, &byte, &scan, &glyph, &image); + + /* Fill in font record. Data format filled in by reader. */ + pFont->refcnt = 0; + + ret = (*readers[i].ReadFont) (pFont, file, bit, byte, glyph, scan); + + FontFileClose (file); + if (ret != Successful) { + free(pFont); + } else { + *ppFont = pFont; + } + return ret; +} + +static int +BitmapGetInfoBitmap (FontPathElementPtr fpe, FontInfoPtr pFontInfo, + FontEntryPtr entry, char *fileName) +{ + FontFilePtr file; + int i; + int ret; + FontRendererPtr renderer; + + renderer = FontFileMatchRenderer (fileName); + if (!renderer) + return BadFontName; + i = BitmapGetRenderIndex(renderer); + file = FontFileOpen (fileName); + if (!file) + return BadFontName; + ret = (*readers[i].ReadInfo) (pFontInfo, file); + FontFileClose (file); + return ret; +} + +static FontRendererRec renderers[] = { +#if XFONT_PCFFORMAT + { ".pcf", 4, BitmapOpenBitmap, BitmapOpenScalable, + BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES }, + { ".pcf.Z", 6, BitmapOpenBitmap, BitmapOpenScalable, + BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES }, +# ifdef X_GZIP_FONT_COMPRESSION + { ".pcf.gz", 7, + BitmapOpenBitmap, BitmapOpenScalable, + BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES }, +# endif +# ifdef X_BZIP2_FONT_COMPRESSION + { ".pcf.bz2", 8, + BitmapOpenBitmap, BitmapOpenScalable, + BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES }, +# endif +#endif +#if XFONT_SNFFORMAT + { ".snf", 4, BitmapOpenBitmap, BitmapOpenScalable, + BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES }, + { ".snf.Z", 6, BitmapOpenBitmap, BitmapOpenScalable, + BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES }, +# ifdef X_GZIP_FONT_COMPRESSION + { ".snf.gz", 7, BitmapOpenBitmap, BitmapOpenScalable, + BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES }, +# endif +# ifdef X_BZIP2_FONT_COMPRESSION + { ".snf.bz2", 8, BitmapOpenBitmap, BitmapOpenScalable, + BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES }, +# endif +#endif +#if XFONT_BDFFORMAT + { ".bdf", 4, BitmapOpenBitmap, BitmapOpenScalable, + BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES }, + { ".bdf.Z", 6, BitmapOpenBitmap, BitmapOpenScalable, + BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES }, +# ifdef X_GZIP_FONT_COMPRESSION + { ".bdf.gz", 7, BitmapOpenBitmap, BitmapOpenScalable, + BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES }, +# endif +# ifdef X_BZIP2_FONT_COMPRESSION + { ".bdf.bz2", 8, BitmapOpenBitmap, BitmapOpenScalable, + BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, + CAPABILITIES }, +# endif +#endif +}; + +#define numRenderers (sizeof renderers / sizeof renderers[0]) + +void +BitmapRegisterFontFileFunctions (void) +{ + int i; + + for (i = 0; i < numRenderers; i++) + FontFileRegisterRenderer (&renderers[i]); +} + +/* + * compute offset into renderers array - used to find the font reader, + * the font info reader, and the bitmap scaling routine. All users + * of this routine must be kept in step with the renderer array. + */ +static int +BitmapGetRenderIndex(FontRendererPtr renderer) +{ + return renderer - renderers; +} diff --git a/src/bitmap/bitmaputil.c b/src/bitmap/bitmaputil.c new file mode 100755 index 0000000..0a1c87e --- /dev/null +++ b/src/bitmap/bitmaputil.c @@ -0,0 +1,229 @@ +/* + +Copyright 1990, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#ifndef MAXSHORT +#define MAXSHORT 32767 +#endif + +#ifndef MINSHORT +#define MINSHORT -32768 +#endif + +static xCharInfo initMinMetrics = { +MAXSHORT, MAXSHORT, MAXSHORT, MAXSHORT, MAXSHORT, 0xFFFF}; +static xCharInfo initMaxMetrics = { +MINSHORT, MINSHORT, MINSHORT, MINSHORT, MINSHORT, 0x0000}; + +#define MINMAX(field,ci) \ + if (minbounds->field > (ci)->field) \ + minbounds->field = (ci)->field; \ + if (maxbounds->field < (ci)->field) \ + maxbounds->field = (ci)->field; + +#define COMPUTE_MINMAX(ci) \ + if ((ci)->ascent || (ci)->descent || \ + (ci)->leftSideBearing || (ci)->rightSideBearing || \ + (ci)->characterWidth) \ + { \ + MINMAX(ascent, (ci)); \ + MINMAX(descent, (ci)); \ + MINMAX(leftSideBearing, (ci)); \ + MINMAX(rightSideBearing, (ci)); \ + MINMAX(characterWidth, (ci)); \ + } + +void +bitmapComputeFontBounds(FontPtr pFont) +{ + BitmapFontPtr bitmapFont = (BitmapFontPtr) pFont->fontPrivate; + int nchars; + int r, + c; + CharInfoPtr ci; + int maxOverlap; + int overlap; + xCharInfo *minbounds, + *maxbounds; + int i; + int numneg = 0, numpos = 0; + + if (bitmapFont->bitmapExtra) { + minbounds = &bitmapFont->bitmapExtra->info.minbounds; + maxbounds = &bitmapFont->bitmapExtra->info.maxbounds; + } else { + minbounds = &pFont->info.minbounds; + maxbounds = &pFont->info.maxbounds; + } + *minbounds = initMinMetrics; + *maxbounds = initMaxMetrics; + maxOverlap = MINSHORT; + nchars = bitmapFont->num_chars; + for (i = 0, ci = bitmapFont->metrics; i < nchars; i++, ci++) { + COMPUTE_MINMAX(&ci->metrics); + if (ci->metrics.characterWidth < 0) + numneg++; + else + numpos++; + minbounds->attributes &= ci->metrics.attributes; + maxbounds->attributes |= ci->metrics.attributes; + overlap = ci->metrics.rightSideBearing - ci->metrics.characterWidth; + if (maxOverlap < overlap) + maxOverlap = overlap; + } + if (bitmapFont->bitmapExtra) { + if (numneg > numpos) + bitmapFont->bitmapExtra->info.drawDirection = RightToLeft; + else + bitmapFont->bitmapExtra->info.drawDirection = LeftToRight; + bitmapFont->bitmapExtra->info.maxOverlap = maxOverlap; + minbounds = &pFont->info.minbounds; + maxbounds = &pFont->info.maxbounds; + *minbounds = initMinMetrics; + *maxbounds = initMaxMetrics; + i = 0; + maxOverlap = MINSHORT; + for (r = pFont->info.firstRow; r <= pFont->info.lastRow; r++) { + for (c = pFont->info.firstCol; c <= pFont->info.lastCol; c++) { + ci = ACCESSENCODING(bitmapFont->encoding, i); + if (ci) { + COMPUTE_MINMAX(&ci->metrics); + if (ci->metrics.characterWidth < 0) + numneg++; + else + numpos++; + minbounds->attributes &= ci->metrics.attributes; + maxbounds->attributes |= ci->metrics.attributes; + overlap = ci->metrics.rightSideBearing - + ci->metrics.characterWidth; + if (maxOverlap < overlap) + maxOverlap = overlap; + } + i++; + } + } + } + if (numneg > numpos) + pFont->info.drawDirection = RightToLeft; + else + pFont->info.drawDirection = LeftToRight; + pFont->info.maxOverlap = maxOverlap; +} + +void +bitmapComputeFontInkBounds(FontPtr pFont) +{ + BitmapFontPtr bitmapFont = (BitmapFontPtr) pFont->fontPrivate; + int nchars; + int r, + c; + CharInfoPtr cit; + xCharInfo *ci; + int offset; + xCharInfo *minbounds, + *maxbounds; + int i; + + if (!bitmapFont->ink_metrics) { + if (bitmapFont->bitmapExtra) { + bitmapFont->bitmapExtra->info.ink_minbounds = bitmapFont->bitmapExtra->info.minbounds; + bitmapFont->bitmapExtra->info.ink_maxbounds = bitmapFont->bitmapExtra->info.maxbounds; + } + pFont->info.ink_minbounds = pFont->info.minbounds; + pFont->info.ink_maxbounds = pFont->info.maxbounds; + } else { + if (bitmapFont->bitmapExtra) { + minbounds = &bitmapFont->bitmapExtra->info.ink_minbounds; + maxbounds = &bitmapFont->bitmapExtra->info.ink_maxbounds; + } else { + minbounds = &pFont->info.ink_minbounds; + maxbounds = &pFont->info.ink_maxbounds; + } + *minbounds = initMinMetrics; + *maxbounds = initMaxMetrics; + nchars = bitmapFont->num_chars; + for (i = 0, ci = bitmapFont->ink_metrics; i < nchars; i++, ci++) { + COMPUTE_MINMAX(ci); + minbounds->attributes &= ci->attributes; + maxbounds->attributes |= ci->attributes; + } + if (bitmapFont->bitmapExtra) { + minbounds = &pFont->info.ink_minbounds; + maxbounds = &pFont->info.ink_maxbounds; + *minbounds = initMinMetrics; + *maxbounds = initMaxMetrics; + i=0; + for (r = pFont->info.firstRow; r <= pFont->info.lastRow; r++) { + for (c = pFont->info.firstCol; c <= pFont->info.lastCol; c++) { + cit = ACCESSENCODING(bitmapFont->encoding, i); + if (cit) { + offset = cit - bitmapFont->metrics; + ci = &bitmapFont->ink_metrics[offset]; + COMPUTE_MINMAX(ci); + minbounds->attributes &= ci->attributes; + maxbounds->attributes |= ci->attributes; + } + i++; + } + } + } + } +} + +Bool +bitmapAddInkMetrics(FontPtr pFont) +{ + BitmapFontPtr bitmapFont; + int i; + + bitmapFont = (BitmapFontPtr) pFont->fontPrivate; + bitmapFont->ink_metrics = malloc(bitmapFont->num_chars * sizeof(xCharInfo)); + if (!bitmapFont->ink_metrics) { + fprintf(stderr, "Error: Couldn't allocate ink_metrics (%d*%ld)\n", + bitmapFont->num_chars, (unsigned long)sizeof(xCharInfo)); + return FALSE; + } + for (i = 0; i < bitmapFont->num_chars; i++) + FontCharInkMetrics(pFont, &bitmapFont->metrics[i], &bitmapFont->ink_metrics[i]); + pFont->info.inkMetrics = TRUE; + return TRUE; +} + +/* ARGSUSED */ +int +bitmapComputeWeight(FontPtr pFont) +{ + return 10; +} diff --git a/src/bitmap/bitscale.c b/src/bitmap/bitscale.c new file mode 100755 index 0000000..cf16bff --- /dev/null +++ b/src/bitmap/bitscale.c @@ -0,0 +1,1691 @@ +/* + +Copyright 1991, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +/* + * Translate monolithic #defines to modular definitions + */ + +#ifdef PCFFORMAT +#define XFONT_PCFFORMAT 1 +#endif + +#ifdef SNFFORMAT +#define XFONT_SNFFORMAT 1 +#endif + +#ifdef BDFFORMAT +#define XFONT_BDFFORMAT 1 +#endif + +#include +#include +#include +#include + +#ifndef MAX +#define MAX(a,b) (((a)>(b)) ? a : b) +#endif + +/* Should get this from elsewhere */ +extern unsigned long serverGeneration; + +static void bitmapUnloadScalable (FontPtr pFont); +static void ScaleBitmap ( FontPtr pFont, CharInfoPtr opci, + CharInfoPtr pci, double *inv_xform, + double widthMult, double heightMult ); +static FontPtr BitmapScaleBitmaps(FontPtr pf, FontPtr opf, + double widthMult, double heightMult, + FontScalablePtr vals); + +enum scaleType { + atom, truncate_atom, pixel_size, point_size, resolution_x, + resolution_y, average_width, scaledX, scaledY, unscaled, fontname, + raw_ascent, raw_descent, raw_pixelsize, raw_pointsize, + raw_average_width, uncomputed +}; + +typedef struct _fontProp { + char *name; + Atom atom; + enum scaleType type; +} fontProp; + +static FontEntryPtr FindBestToScale ( FontPathElementPtr fpe, + FontEntryPtr entry, + FontScalablePtr vals, + FontScalablePtr best, + double *dxp, double *dyp, + double *sdxp, double *sdyp, + FontPathElementPtr *fpep ); + +static unsigned long bitscaleGeneration = 0; /* initialization flag */ + +static fontProp fontNamePropTable[] = { + { "FOUNDRY", 0, atom }, + { "FAMILY_NAME", 0, atom }, + { "WEIGHT_NAME", 0, atom }, + { "SLANT", 0, atom }, + { "SETWIDTH_NAME", 0, atom }, + { "ADD_STYLE_NAME", 0, atom }, + { "PIXEL_SIZE", 0, pixel_size }, + { "POINT_SIZE", 0, point_size }, + { "RESOLUTION_X", 0, resolution_x }, + { "RESOLUTION_Y", 0, resolution_y }, + { "SPACING", 0, atom }, + { "AVERAGE_WIDTH", 0, average_width }, + { "CHARSET_REGISTRY", 0, atom }, + { "CHARSET_ENCODING", 0, truncate_atom }, + { "FONT", 0, fontname }, + { "RAW_ASCENT", 0, raw_ascent }, + { "RAW_DESCENT", 0, raw_descent }, + { "RAW_PIXEL_SIZE", 0, raw_pixelsize }, + { "RAW_POINT_SIZE", 0, raw_pointsize }, + { "RAW_AVERAGE_WIDTH", 0, raw_average_width } +}; + +#define TRANSFORM_POINT(matrix, x, y, dest) \ + ((dest)[0] = (matrix)[0] * (x) + (matrix)[2] * (y), \ + (dest)[1] = (matrix)[1] * (x) + (matrix)[3] * (y)) + +#define CHECK_EXTENT(lsb, rsb, desc, asc, data) \ + ((lsb) > (data)[0] ? (lsb) = (data)[0] : 0 , \ + (rsb) < (data)[0] ? (rsb) = (data)[0] : 0, \ + (-desc) > (data)[1] ? (desc) = -(data)[1] : 0 , \ + (asc) < (data)[1] ? (asc) = (data)[1] : 0) + +#define NPROPS (sizeof(fontNamePropTable) / sizeof(fontProp)) + +/* Warning: order of the next two tables is critically interdependent. + Location of "unscaled" properties at the end of fontPropTable[] + is important. */ + +static fontProp fontPropTable[] = { + { "MIN_SPACE", 0, scaledX }, + { "NORM_SPACE", 0, scaledX }, + { "MAX_SPACE", 0, scaledX }, + { "END_SPACE", 0, scaledX }, + { "AVG_CAPITAL_WIDTH", 0, scaledX }, + { "AVG_LOWERCASE_WIDTH", 0, scaledX }, + { "QUAD_WIDTH", 0, scaledX }, + { "FIGURE_WIDTH", 0, scaledX }, + { "SUPERSCRIPT_X", 0, scaledX }, + { "SUPERSCRIPT_Y", 0, scaledY }, + { "SUBSCRIPT_X", 0, scaledX }, + { "SUBSCRIPT_Y", 0, scaledY }, + { "SUPERSCRIPT_SIZE", 0, scaledY }, + { "SUBSCRIPT_SIZE", 0, scaledY }, + { "SMALL_CAP_SIZE", 0, scaledY }, + { "UNDERLINE_POSITION", 0, scaledY }, + { "UNDERLINE_THICKNESS", 0, scaledY }, + { "STRIKEOUT_ASCENT", 0, scaledY }, + { "STRIKEOUT_DESCENT", 0, scaledY }, + { "CAP_HEIGHT", 0, scaledY }, + { "X_HEIGHT", 0, scaledY }, + { "ITALIC_ANGLE", 0, unscaled }, + { "RELATIVE_SETWIDTH", 0, unscaled }, + { "RELATIVE_WEIGHT", 0, unscaled }, + { "WEIGHT", 0, unscaled }, + { "DESTINATION", 0, unscaled }, + { "PCL_FONT_NAME", 0, unscaled }, + { "_ADOBE_POSTSCRIPT_FONTNAME", 0, unscaled } +}; + +static fontProp rawFontPropTable[] = { + { "RAW_MIN_SPACE", 0, }, + { "RAW_NORM_SPACE", 0, }, + { "RAW_MAX_SPACE", 0, }, + { "RAW_END_SPACE", 0, }, + { "RAW_AVG_CAPITAL_WIDTH", 0, }, + { "RAW_AVG_LOWERCASE_WIDTH", 0, }, + { "RAW_QUAD_WIDTH", 0, }, + { "RAW_FIGURE_WIDTH", 0, }, + { "RAW_SUPERSCRIPT_X", 0, }, + { "RAW_SUPERSCRIPT_Y", 0, }, + { "RAW_SUBSCRIPT_X", 0, }, + { "RAW_SUBSCRIPT_Y", 0, }, + { "RAW_SUPERSCRIPT_SIZE", 0, }, + { "RAW_SUBSCRIPT_SIZE", 0, }, + { "RAW_SMALL_CAP_SIZE", 0, }, + { "RAW_UNDERLINE_POSITION", 0, }, + { "RAW_UNDERLINE_THICKNESS", 0, }, + { "RAW_STRIKEOUT_ASCENT", 0, }, + { "RAW_STRIKEOUT_DESCENT", 0, }, + { "RAW_CAP_HEIGHT", 0, }, + { "RAW_X_HEIGHT", 0, } +}; + +static void +initFontPropTable(void) +{ + int i; + fontProp *t; + + i = sizeof(fontNamePropTable) / sizeof(fontProp); + for (t = fontNamePropTable; i; i--, t++) + t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE); + + i = sizeof(fontPropTable) / sizeof(fontProp); + for (t = fontPropTable; i; i--, t++) + t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE); + + i = sizeof(rawFontPropTable) / sizeof(fontProp); + for (t = rawFontPropTable; i; i--, t++) + t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE); +} + +#if 0 +static FontEntryPtr +GetScalableEntry (FontPathElementPtr fpe, FontNamePtr name) +{ + FontDirectoryPtr dir; + + dir = (FontDirectoryPtr) fpe->private; + return FontFileFindNameInDir (&dir->scalable, name); +} +#endif + +static double +get_matrix_horizontal_component(double *matrix) +{ + return hypot(matrix[0], matrix[1]); +} + +static double +get_matrix_vertical_component(double *matrix) +{ + return hypot(matrix[2], matrix[3]); +} + + +static Bool +ComputeScaleFactors(FontScalablePtr from, FontScalablePtr to, + double *dx, double *dy, double *sdx, double *sdy, + double *rescale_x) +{ + double srcpixelset, destpixelset, srcpixel, destpixel; + + srcpixelset = get_matrix_horizontal_component(from->pixel_matrix); + destpixelset = get_matrix_horizontal_component(to->pixel_matrix); + srcpixel = get_matrix_vertical_component(from->pixel_matrix); + destpixel = get_matrix_vertical_component(to->pixel_matrix); + + if (srcpixelset >= EPS) + { + *dx = destpixelset / srcpixelset; + *sdx = 1000.0 / srcpixelset; + } + else + *sdx = *dx = 0; + + *rescale_x = 1.0; + + /* If client specified a width, it overrides setsize; in this + context, we interpret width as applying to the font before any + rotation, even though that's not what is ultimately returned in + the width field. */ + if (from->width > 0 && to->width > 0 && fabs(*dx) > EPS) + { + double rescale = (double)to->width / (double)from->width; + + /* If the client specified a transformation matrix, the rescaling + for width does *not* override the setsize. Instead, just check + for consistency between the setsize from the matrix and the + setsize that would result from rescaling according to the width. + This assumes (perhaps naively) that the width is correctly + reported in the name. As an interesting side effect, this test + may result in choosing a different source bitmap (one that + scales consistently between the setsize *and* the width) than it + would choose if a width were not specified. Sort of a hidden + multiple-master functionality. */ + if ((to->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY || + (to->values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY) + { + /* Reject if resulting width difference is >= 1 pixel */ + if (fabs(rescale * from->width - *dx * from->width) >= 10) + return FALSE; + } + else + { + *rescale_x = rescale/(*dx); + *dx = rescale; + } + } + + if (srcpixel >= EPS) + { + *dy = destpixel / srcpixel; + *sdy = 1000.0 / srcpixel; + } + else + *sdy = *dy = 0; + + return TRUE; +} + +/* favor enlargement over reduction because of aliasing resulting + from reduction */ +#define SCORE(m,s) \ +if (m >= 1.0) { \ + if (m == 1.0) \ + score += (16 * s); \ + else if (m == 2.0) \ + score += (4 * s); \ + else \ + score += (int)(((double)(3 * s)) / m); \ +} else { \ + score += (int)(((double)(2 * s)) * m); \ +} + +/* don't need to favor enlargement when looking for bitmap that can + be used unscalable */ +#define SCORE2(m,s) \ +if (m >= 1.0) \ + score += (int)(((double)(8 * s)) / m); \ +else \ + score += (int)(((double)(8 * s)) * m); + +static FontEntryPtr +FindBestToScale(FontPathElementPtr fpe, FontEntryPtr entry, + FontScalablePtr vals, FontScalablePtr best, + double *dxp, double *dyp, + double *sdxp, double *sdyp, + FontPathElementPtr *fpep) +{ + FontScalableRec temp; + int source, i; + int best_score, best_unscaled_score, + score; + double dx = 0.0, sdx = 0.0, dx_amount = 0.0, + dy = 0.0, sdy = 0.0, dy_amount = 0.0, + best_dx = 0.0, best_sdx = 0.0, best_dx_amount = 0.0, + best_dy = 0.0, best_sdy = 0.0, best_dy_amount = 0.0, + best_unscaled_sdx = 0.0, best_unscaled_sdy = 0.0, + rescale_x = 0.0, best_rescale_x = 0.0, + best_unscaled_rescale_x = 0.0; + FontEntryPtr zero; + FontNameRec zeroName; + char zeroChars[MAXFONTNAMELEN]; + FontDirectoryPtr dir; + FontScaledPtr scaled; + FontScalableExtraPtr extra; + FontScaledPtr best_scaled, best_unscaled; + FontPathElementPtr best_fpe = NULL, best_unscaled_fpe = NULL; + FontEntryPtr bitmap = NULL; + FontEntryPtr result; + int aliascount = 20; + FontPathElementPtr bitmap_fpe = NULL; + FontNameRec xlfdName; + + /* find the best match */ + rescale_x = 1.0; + best_scaled = 0; + best_score = 0; + best_unscaled = 0; + best_unscaled_score = -1; + best_dx_amount = best_dy_amount = HUGE_VAL; + memcpy (zeroChars, entry->name.name, entry->name.length); + zeroChars[entry->name.length] = '\0'; + zeroName.name = zeroChars; + FontParseXLFDName (zeroChars, &temp, FONT_XLFD_REPLACE_ZERO); + zeroName.length = strlen (zeroChars); + zeroName.ndashes = entry->name.ndashes; + xlfdName.name = vals->xlfdName; + xlfdName.length = strlen(xlfdName.name); + xlfdName.ndashes = FontFileCountDashes(xlfdName.name, xlfdName.length); + restart_bestscale_loop: ; + /* + * Look through all the registered bitmap sources for + * the same zero name as ours; entries along that one + * can be scaled as desired. + */ + for (source = 0; source < FontFileBitmapSources.count; source++) + { + /* There might already be a bitmap that satisfies the request + but didn't have a zero name that was found by the scalable + font matching logic. Keep track if there is. */ + if (bitmap == NULL && vals->xlfdName != NULL) + { + bitmap_fpe = FontFileBitmapSources.fpe[source]; + dir = (FontDirectoryPtr) bitmap_fpe->private; + bitmap = FontFileFindNameInDir (&dir->nonScalable, &xlfdName); + if (bitmap && bitmap->type != FONT_ENTRY_BITMAP) + { + if (bitmap->type == FONT_ENTRY_ALIAS && aliascount > 0) + { + aliascount--; + xlfdName.name = bitmap->u.alias.resolved; + xlfdName.length = strlen(xlfdName.name); + xlfdName.ndashes = FontFileCountDashes(xlfdName.name, + xlfdName.length); + bitmap = NULL; + goto restart_bestscale_loop; + } + else + bitmap = NULL; + } + } + + if (FontFileBitmapSources.fpe[source] == fpe) + zero = entry; + else + { + dir = (FontDirectoryPtr) FontFileBitmapSources.fpe[source]->private; + zero = FontFileFindNameInDir (&dir->scalable, &zeroName); + if (!zero) + continue; + } + extra = zero->u.scalable.extra; + for (i = 0; i < extra->numScaled; i++) + { + scaled = &extra->scaled[i]; + if (!scaled->bitmap) + continue; + if (!ComputeScaleFactors(&scaled->vals, vals, &dx, &dy, &sdx, &sdy, + &rescale_x)) + continue; + score = 0; + dx_amount = dx; + dy_amount = dy; + SCORE(dy_amount, 10); + SCORE(dx_amount, 1); + if ((score > best_score) || + ((score == best_score) && + ((dy_amount < best_dy_amount) || + ((dy_amount == best_dy_amount) && + (dx_amount < best_dx_amount))))) + { + best_fpe = FontFileBitmapSources.fpe[source]; + best_scaled = scaled; + best_score = score; + best_dx = dx; + best_dy = dy; + best_sdx = sdx; + best_sdy = sdy; + best_dx_amount = dx_amount; + best_dy_amount = dy_amount; + best_rescale_x = rescale_x; + } + /* Is this font a candidate for use without ugly rescaling? */ + if (fabs(dx) > EPS && fabs(dy) > EPS && + fabs(vals->pixel_matrix[0] * rescale_x - + scaled->vals.pixel_matrix[0]) < 1 && + fabs(vals->pixel_matrix[1] * rescale_x - + scaled->vals.pixel_matrix[1]) < EPS && + fabs(vals->pixel_matrix[2] - + scaled->vals.pixel_matrix[2]) < EPS && + fabs(vals->pixel_matrix[3] - + scaled->vals.pixel_matrix[3]) < 1) + { + /* Yes. The pixel sizes are close on the diagonal and + extremely close off the diagonal. */ + score = 0; + SCORE2(vals->pixel_matrix[3] / + scaled->vals.pixel_matrix[3], 10); + SCORE2(vals->pixel_matrix[0] * rescale_x / + scaled->vals.pixel_matrix[0], 1); + if (score > best_unscaled_score) + { + best_unscaled_fpe = FontFileBitmapSources.fpe[source]; + best_unscaled = scaled; + best_unscaled_sdx = sdx / dx; + best_unscaled_sdy = sdy / dy; + best_unscaled_score = score; + best_unscaled_rescale_x = rescale_x; + } + } + } + } + if (best_unscaled) + { + *best = best_unscaled->vals; + *fpep = best_unscaled_fpe; + *dxp = 1.0; + *dyp = 1.0; + *sdxp = best_unscaled_sdx; + *sdyp = best_unscaled_sdy; + rescale_x = best_unscaled_rescale_x; + result = best_unscaled->bitmap; + } + else if (best_scaled) + { + *best = best_scaled->vals; + *fpep = best_fpe; + *dxp = best_dx; + *dyp = best_dy; + *sdxp = best_sdx; + *sdyp = best_sdy; + rescale_x = best_rescale_x; + result = best_scaled->bitmap; + } + else + result = NULL; + + if (bitmap != NULL && (result == NULL || *dxp != 1.0 || *dyp != 1.0)) + { + *fpep = bitmap_fpe; + FontParseXLFDName (bitmap->name.name, best, FONT_XLFD_REPLACE_NONE); + if (ComputeScaleFactors(best, best, dxp, dyp, sdxp, sdyp, &rescale_x)) + result = bitmap; + else + result = NULL; + } + + if (result && rescale_x != 1.0) + { + /* We have rescaled horizontally due to an XLFD width field. Change + the matrix appropriately */ + vals->pixel_matrix[0] *= rescale_x; + vals->pixel_matrix[1] *= rescale_x; + vals->values_supplied = vals->values_supplied & ~POINTSIZE_MASK; + /* Recompute and reround the FontScalablePtr values after + rescaling for the new width. */ + FontFileCompleteXLFD(vals, vals); + } + + return result; +} + +static long +doround(double x) +{ + return (x >= 0) ? (long)(x + .5) : (long)(x - .5); +} + +static int +computeProps(FontPropPtr pf, char *wasStringProp, + FontPropPtr npf, char *isStringProp, + unsigned int nprops, double xfactor, double yfactor, + double sXfactor, double sYfactor) +{ + int n; + int count; + fontProp *t; + double rawfactor = 0.0; + + for (count = 0; nprops > 0; nprops--, pf++, wasStringProp++) { + n = sizeof(fontPropTable) / sizeof(fontProp); + for (t = fontPropTable; n && (t->atom != pf->name); n--, t++); + if (!n) + continue; + + switch (t->type) { + case scaledX: + npf->value = doround(xfactor * (double)pf->value); + rawfactor = sXfactor; + break; + case scaledY: + npf->value = doround(yfactor * (double)pf->value); + rawfactor = sYfactor; + break; + case unscaled: + npf->value = pf->value; + npf->name = pf->name; + npf++; + count++; + *isStringProp++ = *wasStringProp; + break; + default: + break; + } + if (t->type != unscaled) + { + npf->name = pf->name; + npf++; + count++; + npf->value = doround(rawfactor * (double)pf->value); + npf->name = rawFontPropTable[t - fontPropTable].atom; + npf++; + count++; + *isStringProp++ = *wasStringProp; + *isStringProp++ = *wasStringProp; + } + } + return count; +} + + +static int +ComputeScaledProperties(FontInfoPtr sourceFontInfo, /* the font to be scaled */ + char *name, /* name of resulting font */ + FontScalablePtr vals, + double dx, double dy, /* scale factors in x and y */ + double sdx, double sdy, /* directions */ + long sWidth, /* 1000-pixel average width */ + FontPropPtr *pProps, /* returns properties; + preallocated */ + char **pIsStringProp) /* return booleans; + preallocated */ +{ + int n; + char *ptr1 = NULL, *ptr2 = NULL; + char *ptr3; + FontPropPtr fp; + fontProp *fpt; + char *isStringProp; + int nProps; + + if (bitscaleGeneration != serverGeneration) { + initFontPropTable(); + bitscaleGeneration = serverGeneration; + } + nProps = NPROPS + 1 + sizeof(fontPropTable) / sizeof(fontProp) + + sizeof(rawFontPropTable) / sizeof(fontProp); + fp = malloc(sizeof(FontPropRec) * nProps); + *pProps = fp; + if (!fp) { + fprintf(stderr, "Error: Couldn't allocate font properties (%ld*%d)\n", + (unsigned long)sizeof(FontPropRec), nProps); + return 1; + } + isStringProp = malloc (nProps); + *pIsStringProp = isStringProp; + if (!isStringProp) + { + fprintf(stderr, "Error: Couldn't allocate isStringProp (%d)\n", nProps); + free (fp); + return 1; + } + ptr2 = name; + for (fpt = fontNamePropTable, n = NPROPS; + n; + fp++, fpt++, n--, isStringProp++) + { + + if (*ptr2) + { + ptr1 = ptr2 + 1; + if (!(ptr2 = strchr(ptr1, '-'))) ptr2 = strchr(ptr1, '\0'); + } + + *isStringProp = 0; + switch (fpt->type) { + case atom: + fp->value = MakeAtom(ptr1, ptr2 - ptr1, TRUE); + *isStringProp = 1; + break; + case truncate_atom: + for (ptr3 = ptr1; *ptr3; ptr3++) + if (*ptr3 == '[') + break; + if (!*ptr3) ptr3 = ptr2; + fp->value = MakeAtom(ptr1, ptr3 - ptr1, TRUE); + *isStringProp = 1; + break; + case pixel_size: + fp->value = doround(vals->pixel_matrix[3]); + break; + case point_size: + fp->value = doround(vals->point_matrix[3] * 10.0); + break; + case resolution_x: + fp->value = vals->x; + break; + case resolution_y: + fp->value = vals->y; + break; + case average_width: + fp->value = vals->width; + break; + case fontname: + fp->value = MakeAtom(name, strlen(name), TRUE); + *isStringProp = 1; + break; + case raw_ascent: + fp->value = sourceFontInfo->fontAscent * sdy; + break; + case raw_descent: + fp->value = sourceFontInfo->fontDescent * sdy; + break; + case raw_pointsize: + fp->value = (long)(72270.0 / (double)vals->y + .5); + break; + case raw_pixelsize: + fp->value = 1000; + break; + case raw_average_width: + fp->value = sWidth; + break; + default: + break; + } + fp->name = fpt->atom; + } + n = NPROPS; + n += computeProps(sourceFontInfo->props, sourceFontInfo->isStringProp, + fp, isStringProp, sourceFontInfo->nprops, dx, dy, + sdx, sdy); + return n; +} + + +static int +compute_xform_matrix(FontScalablePtr vals, double dx, double dy, + double *xform, double *inv_xform, + double *xmult, double *ymult) +{ + double det; + double pixel = get_matrix_vertical_component(vals->pixel_matrix); + double pixelset = get_matrix_horizontal_component(vals->pixel_matrix); + + if (pixel < EPS || pixelset < EPS) return 0; + + /* Initialize the transformation matrix to the scaling factors */ + xform[0] = dx / pixelset; + xform[1] = xform[2] = 0.0; + xform[3] = dy / pixel; + +/* Inline matrix multiply -- somewhat ugly to minimize register usage */ +#define MULTIPLY_XFORM(a,b,c,d) \ +{ \ + register double aa = (a), bb = (b), cc = (c), dd = (d); \ + register double temp; \ + temp = aa * xform[0] + cc * xform[1]; \ + aa = aa * xform[2] + cc * xform[3]; \ + xform[1] = bb * xform[0] + dd * xform[1]; \ + xform[3] = bb * xform[2] + dd * xform[3]; \ + xform[0] = temp; \ + xform[2] = aa; \ +} + + /* Rescale the transformation matrix for size of source font */ + MULTIPLY_XFORM(vals->pixel_matrix[0], + vals->pixel_matrix[1], + vals->pixel_matrix[2], + vals->pixel_matrix[3]); + + *xmult = xform[0]; + *ymult = xform[3]; + + + if (inv_xform == NULL) return 1; + + /* Compute the determinant for use in inverting the matrix. */ + det = xform[0] * xform[3] - xform[1] * xform[2]; + + /* If the determinant is tiny or zero, give up */ + if (fabs(det) < EPS) return 0; + + /* Compute the inverse */ + inv_xform[0] = xform[3] / det; + inv_xform[1] = -xform[1] / det; + inv_xform[2] = -xform[2] / det; + inv_xform[3] = xform[0] / det; + + return 1; +} + +/* + * ScaleFont + * returns a pointer to the new scaled font, or NULL (due to AllocError). + */ +static FontPtr +ScaleFont(FontPtr opf, /* originating font */ + double widthMult, /* glyphs width scale factor */ + double heightMult, /* glyphs height scale factor */ + double sWidthMult, /* scalable glyphs width scale factor */ + double sHeightMult, /* scalable glyphs height scale factor */ + FontScalablePtr vals, + double *newWidthMult, /* return: X component of glyphs width + scale factor */ + double *newHeightMult, /* return: Y component of glyphs height + scale factor */ + long *sWidth) /* return: average 1000-pixel width */ +{ + FontPtr pf; + FontInfoPtr pfi, + opfi; + BitmapFontPtr bitmapFont, + obitmapFont; + CharInfoPtr pci, + opci; + int nchars = 0; /* how many characters in the font */ + int i; + int firstCol, lastCol, firstRow, lastRow; + double xform[4], inv_xform[4]; + double xmult, ymult; + int totalwidth = 0, totalchars = 0; +#define OLDINDEX(i) (((i)/(lastCol - firstCol + 1) + \ + firstRow - opf->info.firstRow) * \ + (opf->info.lastCol - opf->info.firstCol + 1) + \ + (i)%(lastCol - firstCol + 1) + \ + firstCol - opf->info.firstCol) + + *sWidth = 0; + + opfi = &opf->info; + obitmapFont = (BitmapFontPtr) opf->fontPrivate; + + bitmapFont = 0; + if (!(pf = CreateFontRec())) { + fprintf(stderr, "Error: Couldn't allocate FontRec (%ld)\n", + (unsigned long)sizeof(FontRec)); + goto bail; + } + pf->refcnt = 0; + pf->bit = opf->bit; + pf->byte = opf->byte; + pf->glyph = opf->glyph; + pf->scan = opf->scan; + + pf->get_glyphs = bitmapGetGlyphs; + pf->get_metrics = bitmapGetMetrics; + pf->unload_font = bitmapUnloadScalable; + pf->unload_glyphs = NULL; + + pfi = &pf->info; + *pfi = *opfi; + /* If charset subsetting specified in vals, determine what our range + needs to be for the output font */ + if (vals->nranges) + { + int i; + + pfi->allExist = 0; + firstCol = 255; + lastCol = 0; + firstRow = 255; + lastRow = 0; + + for (i = 0; i < vals->nranges; i++) + { + if (vals->ranges[i].min_char_high != vals->ranges[i].max_char_high) + { + firstCol = opfi->firstCol; + lastCol = opfi->lastCol; + } + if (firstCol > vals->ranges[i].min_char_low) + firstCol = vals->ranges[i].min_char_low; + if (lastCol < vals->ranges[i].max_char_low) + lastCol = vals->ranges[i].max_char_low; + if (firstRow > vals->ranges[i].min_char_high) + firstRow = vals->ranges[i].min_char_high; + if (lastRow < vals->ranges[i].max_char_high) + lastRow = vals->ranges[i].max_char_high; + } + + if (firstCol > lastCol || firstRow > lastRow) + goto bail; + + if (firstCol < opfi->firstCol) + firstCol = opfi->firstCol; + if (lastCol > opfi->lastCol) + lastCol = opfi->lastCol; + if (firstRow < opfi->firstRow) + firstRow = opfi->firstRow; + if (lastRow > opfi->lastRow) + lastRow = opfi->lastRow; + } + else + { + firstCol = opfi->firstCol; + lastCol = opfi->lastCol; + firstRow = opfi->firstRow; + lastRow = opfi->lastRow; + } + + bitmapFont = malloc(sizeof(BitmapFontRec)); + if (!bitmapFont) { + fprintf(stderr, "Error: Couldn't allocate bitmapFont (%ld)\n", + (unsigned long)sizeof(BitmapFontRec)); + goto bail; + } + nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1); + pfi->firstRow = firstRow; + pfi->lastRow = lastRow; + pfi->firstCol = firstCol; + pfi->lastCol = lastCol; + pf->fontPrivate = (pointer) bitmapFont; + bitmapFont->version_num = obitmapFont->version_num; + bitmapFont->num_chars = nchars; + bitmapFont->num_tables = obitmapFont->num_tables; + bitmapFont->metrics = 0; + bitmapFont->ink_metrics = 0; + bitmapFont->bitmaps = 0; + bitmapFont->encoding = 0; + bitmapFont->bitmapExtra = 0; + bitmapFont->pDefault = 0; + bitmapFont->metrics = malloc(nchars * sizeof(CharInfoRec)); + if (!bitmapFont->metrics) { + fprintf(stderr, "Error: Couldn't allocate metrics (%d*%ld)\n", + nchars, (unsigned long)sizeof(CharInfoRec)); + goto bail; + } + bitmapFont->encoding = calloc(NUM_SEGMENTS(nchars), sizeof(CharInfoPtr*)); + if (!bitmapFont->encoding) { + fprintf(stderr, "Error: Couldn't allocate encoding (%d*%ld)\n", + nchars, (unsigned long)sizeof(CharInfoPtr)); + goto bail; + } + +#undef MAXSHORT +#define MAXSHORT 32767 +#undef MINSHORT +#define MINSHORT -32768 + + pfi->anamorphic = FALSE; + if (heightMult != widthMult) + pfi->anamorphic = TRUE; + pfi->cachable = TRUE; + + if (!compute_xform_matrix(vals, widthMult, heightMult, xform, + inv_xform, &xmult, &ymult)) + goto bail; + + pfi->fontAscent = opfi->fontAscent * ymult; + pfi->fontDescent = opfi->fontDescent * ymult; + + pfi->minbounds.leftSideBearing = MAXSHORT; + pfi->minbounds.rightSideBearing = MAXSHORT; + pfi->minbounds.ascent = MAXSHORT; + pfi->minbounds.descent = MAXSHORT; + pfi->minbounds.characterWidth = MAXSHORT; + pfi->minbounds.attributes = MAXSHORT; + + pfi->maxbounds.leftSideBearing = MINSHORT; + pfi->maxbounds.rightSideBearing = MINSHORT; + pfi->maxbounds.ascent = MINSHORT; + pfi->maxbounds.descent = MINSHORT; + pfi->maxbounds.characterWidth = MINSHORT; + pfi->maxbounds.attributes = MINSHORT; + + /* Compute the transformation and inverse transformation matrices. + Can fail if the determinant is zero. */ + + pci = bitmapFont->metrics; + for (i = 0; i < nchars; i++) + { + if ((opci = ACCESSENCODING(obitmapFont->encoding,OLDINDEX(i)))) + { + double newlsb, newrsb, newdesc, newasc, point[2]; + +#define minchar(p) ((p).min_char_low + ((p).min_char_high << 8)) +#define maxchar(p) ((p).max_char_low + ((p).max_char_high << 8)) + + if (vals->nranges) + { + int row = i / (lastCol - firstCol + 1) + firstRow; + int col = i % (lastCol - firstCol + 1) + firstCol; + int ch = (row << 8) + col; + int j; + for (j = 0; j < vals->nranges; j++) + if (ch >= minchar(vals->ranges[j]) && + ch <= maxchar(vals->ranges[j])) + break; + if (j == vals->nranges) + { + continue; + } + } + + if (opci->metrics.leftSideBearing == 0 && + opci->metrics.rightSideBearing == 0 && + opci->metrics.ascent == 0 && + opci->metrics.descent == 0 && + opci->metrics.characterWidth == 0) + { + continue; + } + + if(!bitmapFont->encoding[SEGMENT_MAJOR(i)]) { + bitmapFont->encoding[SEGMENT_MAJOR(i)]= + calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr)); + if(!bitmapFont->encoding[SEGMENT_MAJOR(i)]) + goto bail; + } + ACCESSENCODINGL(bitmapFont->encoding, i) = pci; + + /* Compute new extents for this glyph */ + TRANSFORM_POINT(xform, + opci->metrics.leftSideBearing, + -opci->metrics.descent, + point); + newlsb = point[0]; + newrsb = newlsb; + newdesc = -point[1]; + newasc = -newdesc; + TRANSFORM_POINT(xform, + opci->metrics.leftSideBearing, + opci->metrics.ascent, + point); + CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); + TRANSFORM_POINT(xform, + opci->metrics.rightSideBearing, + -opci->metrics.descent, + point); + CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); + TRANSFORM_POINT(xform, + opci->metrics.rightSideBearing, + opci->metrics.ascent, + point); + CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); + + pci->metrics.leftSideBearing = (int)floor(newlsb); + pci->metrics.rightSideBearing = (int)floor(newrsb + .5); + pci->metrics.descent = (int)ceil(newdesc); + pci->metrics.ascent = (int)floor(newasc + .5); + /* Accumulate total width of characters before transformation, + to ascertain predominant direction of font. */ + totalwidth += opci->metrics.characterWidth; + pci->metrics.characterWidth = + doround((double)opci->metrics.characterWidth * xmult); + pci->metrics.attributes = + doround((double)opci->metrics.characterWidth * sWidthMult); + if (!pci->metrics.characterWidth) + { + /* Since transformation may shrink width, height, and + escapement to zero, make sure existing characters + are not mistaken for undefined characters. */ + + if (pci->metrics.rightSideBearing == + pci->metrics.leftSideBearing) + pci->metrics.rightSideBearing++; + if (pci->metrics.ascent == -pci->metrics.descent) + pci->metrics.ascent++; + } + + pci++; + } + } + + + /* + * For each character, set the per-character metrics, scale the glyph, and + * check per-font minbounds and maxbounds character information. + */ + + pci = bitmapFont->metrics; + for (i = 0; i < nchars; i++) + { + if ((pci = ACCESSENCODING(bitmapFont->encoding,i)) && + (opci = ACCESSENCODING(obitmapFont->encoding,OLDINDEX(i)))) + { + totalchars++; + *sWidth += abs((int)(INT16)pci->metrics.attributes); +#define MINMAX(field) \ + if (pfi->minbounds.field > pci->metrics.field) \ + pfi->minbounds.field = pci->metrics.field; \ + if (pfi->maxbounds.field < pci->metrics.field) \ + pfi->maxbounds.field = pci->metrics.field + + MINMAX(leftSideBearing); + MINMAX(rightSideBearing); + MINMAX(ascent); + MINMAX(descent); + MINMAX(characterWidth); + + /* Hack: Cast attributes into a signed quantity. Tread lightly + for now and don't go changing the global Xproto.h file */ + if ((INT16)pfi->minbounds.attributes > + (INT16)pci->metrics.attributes) + pfi->minbounds.attributes = pci->metrics.attributes; + if ((INT16)pfi->maxbounds.attributes < + (INT16)pci->metrics.attributes) + pfi->maxbounds.attributes = pci->metrics.attributes; +#undef MINMAX + } + } + pfi->ink_minbounds = pfi->minbounds; + pfi->ink_maxbounds = pfi->maxbounds; + if (totalchars) + { + *sWidth = (*sWidth * 10 + totalchars / 2) / totalchars; + if (totalwidth < 0) + { + /* Dominant direction is R->L */ + *sWidth = -*sWidth; + } + + if (pfi->minbounds.characterWidth == pfi->maxbounds.characterWidth) + vals->width = pfi->minbounds.characterWidth * 10; + else + vals->width = doround((double)*sWidth * vals->pixel_matrix[0] / + 1000.0); + } + else + { + vals->width = 0; + *sWidth = 0; + } + FontComputeInfoAccelerators (pfi); + + if (pfi->defaultCh != (unsigned short) NO_SUCH_CHAR) { + unsigned int r, + c, + cols; + + r = pfi->defaultCh >> 8; + c = pfi->defaultCh & 0xFF; + if (pfi->firstRow <= r && r <= pfi->lastRow && + pfi->firstCol <= c && c <= pfi->lastCol) { + cols = pfi->lastCol - pfi->firstCol + 1; + r = r - pfi->firstRow; + c = c - pfi->firstCol; + bitmapFont->pDefault = + ACCESSENCODING(bitmapFont->encoding, r * cols + c); + } + } + + *newWidthMult = xmult; + *newHeightMult = ymult; + return pf; +bail: + if (pf) + free(pf); + if (bitmapFont) { + free(bitmapFont->metrics); + free(bitmapFont->ink_metrics); + free(bitmapFont->bitmaps); + if(bitmapFont->encoding) + for(i=0; iencoding[i]); + free(bitmapFont->encoding); + } + return NULL; +} + +static void +ScaleBitmap(FontPtr pFont, CharInfoPtr opci, CharInfoPtr pci, + double *inv_xform, double widthMult, double heightMult) +{ + register char *bitmap, /* The bits */ + *newBitmap; + register int bpr, /* Padding information */ + newBpr; + int width, /* Extents information */ + height, + newWidth, + newHeight; + register int row, /* Loop variables */ + col; + INT32 deltaX, /* Increments for resampling loop */ + deltaY; + INT32 xValue, /* Subscripts for resampling loop */ + yValue; + double point[2]; + unsigned char *char_grayscale = 0; + INT32 *diffusion_workspace = NULL, *thisrow = NULL, + *nextrow = NULL, pixmult = 0; + int box_x = 0, box_y = 0; + + static unsigned char masklsb[] = + { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 }; + static unsigned char maskmsb[] = + { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 }; + unsigned char *mask = (pFont->bit == LSBFirst ? masklsb : maskmsb); + + + bitmap = opci->bits; + newBitmap = pci->bits; + width = GLYPHWIDTHPIXELS(opci); + height = GLYPHHEIGHTPIXELS(opci); + newWidth = GLYPHWIDTHPIXELS(pci); + newHeight = GLYPHHEIGHTPIXELS(pci); + if (!newWidth || !newHeight || !width || !height) + return; + + bpr = BYTES_PER_ROW(width, pFont->glyph); + newBpr = BYTES_PER_ROW(newWidth, pFont->glyph); + + if (widthMult > 0.0 && heightMult > 0.0 && + (widthMult < 1.0 || heightMult < 1.0)) + { + /* We are reducing in one or both dimensions. In an attempt to + reduce aliasing, we'll antialias by passing the original + glyph through a low-pass box filter (which results in a + grayscale image), then use error diffusion to create bitonal + output in the resampling loop. */ + + /* First compute the sizes of the box filter */ + widthMult = ceil(1.0 / widthMult); + heightMult = ceil(1.0 / heightMult); + box_x = width / 2; + box_y = height / 2; + if (widthMult < (double)box_x) box_x = (int)widthMult; + if (heightMult < (double)box_y) box_y = (int)heightMult; + /* The pixmult value (below) is used to darken the image before + we perform error diffusion: a necessary concession to the + fact that it's very difficult to generate readable halftoned + glyphs. The degree of darkening is proportional to the size + of the blurring filter, hence inversely proportional to the + darkness of the lightest gray that results from antialiasing. + The result is that characters that exercise this logic (those + generated by reducing from a larger source font) tend to err + on the side of being too bold instead of being too light to + be readable. */ + pixmult = box_x * box_y * 192; + + if (box_x > 1 || box_y > 1) + { + /* Looks like we need to anti-alias. Create a workspace to + contain the grayscale character plus an additional row and + column for scratch */ + char_grayscale = malloc((width + 1) * (height + 1)); + if (char_grayscale) + { + diffusion_workspace = calloc((newWidth + 2) * 2, sizeof(int)); + if (!diffusion_workspace) + { + fprintf(stderr, "Warning: Couldn't allocate diffusion" + " workspace (%ld)\n", + (newWidth + 2) * 2 * (unsigned long)sizeof(int)); + free(char_grayscale); + char_grayscale = (unsigned char *)0; + } + /* Initialize our error diffusion workspace for later use */ + thisrow = diffusion_workspace + 1; + nextrow = diffusion_workspace + newWidth + 3; + } else { + fprintf(stderr, "Warning: Couldn't allocate character grayscale (%d)\n", (width + 1) * (height + 1)); + } + } + } + + if (char_grayscale) + { + /* We will be doing antialiasing. First copy the bitmap into + our buffer, mapping input range [0,1] to output range + [0,255]. */ + register unsigned char *srcptr, *dstptr; + srcptr = (unsigned char *)bitmap; + dstptr = char_grayscale; + for (row = 0; row < height; row++) + { + for (col = 0; col < width; col++) + *dstptr++ = (srcptr[col >> 3] & mask[col & 0x7]) ? 255 : 0; + srcptr += bpr; /* On to next row of source */ + dstptr++; /* Skip scratch column in dest */ + } + if (box_x > 1) + { + /* Our box filter has a width > 1... let's filter the rows */ + + int right_width = box_x / 2; + int left_width = box_x - right_width - 1; + + for (row = 0; row < height; row++) + { + int sum = 0; + int left_size = 0, right_size = 0; + + srcptr = char_grayscale + (width + 1) * row; + dstptr = char_grayscale + (width + 1) * height; /* scratch */ + + /* We've computed the shape of our full box filter. Now + compute the right-hand part of the moving sum */ + for (right_size = 0; right_size < right_width; right_size++) + sum += srcptr[right_size]; + + /* Now start moving the sum, growing the box filter, and + dropping averages into our scratch buffer */ + for (left_size = 0; left_size < left_width; left_size++) + { + sum += srcptr[right_width]; + *dstptr++ = sum / (left_size + right_width + 1); + srcptr++; + } + + /* The box filter has reached full width... continue + computation of moving average until the right side + hits the wall. */ + for (col = left_size; col + right_size < width; col++) + { + sum += srcptr[right_width]; + *dstptr++ = sum / box_x; + sum -= srcptr[-left_width]; + srcptr++; + } + + /* Collapse the right side of the box filter */ + for (; right_size > 0; right_size--) + { + *dstptr++ = sum / (left_width + right_size); + sum -= srcptr[-left_width]; + srcptr++; + } + + /* Done with the row... copy dest back over source */ + memmove(char_grayscale + (width + 1) * row, + char_grayscale + (width + 1) * height, + width); + } + } + if (box_y > 1) + { + /* Our box filter has a height > 1... let's filter the columns */ + + int bottom_height = box_y / 2; + int top_height = box_y - bottom_height - 1; + + for (col = 0; col < width; col++) + { + int sum = 0; + int top_size = 0, bottom_size = 0; + + srcptr = char_grayscale + col; + dstptr = char_grayscale + width; /* scratch */ + + /* We've computed the shape of our full box filter. Now + compute the bottom part of the moving sum */ + for (bottom_size = 0; + bottom_size < bottom_height; + bottom_size++) + sum += srcptr[bottom_size * (width + 1)]; + + /* Now start moving the sum, growing the box filter, and + dropping averages into our scratch buffer */ + for (top_size = 0; top_size < top_height; top_size++) + { + sum += srcptr[bottom_height * (width + 1)]; + *dstptr = sum / (top_size + bottom_height + 1); + dstptr += width + 1; + srcptr += width + 1; + } + + /* The box filter has reached full height... continue + computation of moving average until the bottom + hits the wall. */ + for (row = top_size; row + bottom_size < height; row++) + { + sum += srcptr[bottom_height * (width + 1)]; + *dstptr = sum / box_y; + dstptr += width + 1; + sum -= srcptr[-top_height * (width + 1)]; + srcptr += width + 1; + } + + /* Collapse the bottom of the box filter */ + for (; bottom_size > 0; bottom_size--) + { + *dstptr = sum / (top_height + bottom_size); + dstptr += width + 1; + sum -= srcptr[-top_height * (width + 1)]; + srcptr += width + 1; + } + + /* Done with the column... copy dest back over source */ + + dstptr = char_grayscale + col; + srcptr = char_grayscale + width; /* scratch */ + for (row = 0; row < height; row++) + { + *dstptr = *srcptr; + dstptr += width + 1; + srcptr += width + 1; + } + } + } + + /* Increase the grayvalue to increase ink a bit */ + srcptr = char_grayscale; + for (row = 0; row < height; row++) + { + for (col = 0; col < width; col++) + { + register int pixvalue = (int)*srcptr * pixmult / 256; + if (pixvalue > 255) pixvalue = 255; + *srcptr = pixvalue; + srcptr++; + } + srcptr++; + } + } + + /* Compute the increment values for the resampling loop */ + TRANSFORM_POINT(inv_xform, 1, 0, point); + deltaX = (INT32)(point[0] * 65536.0); + deltaY = (INT32)(-point[1] * 65536.0); + + /* Resampling loop: resamples original glyph for generation of new + glyph in transformed coordinate system. */ + + for (row = 0; row < newHeight; row++) + { + /* Compute inverse transformation for start of this row */ + TRANSFORM_POINT(inv_xform, + (double)(pci->metrics.leftSideBearing) + .5, + (double)(pci->metrics.ascent - row) - .5, + point); + + /* Adjust for coordinate system to get resampling point */ + point[0] -= opci->metrics.leftSideBearing; + point[1] = opci->metrics.ascent - point[1]; + + /* Convert to integer coordinates */ + xValue = (INT32)(point[0] * 65536.0); + yValue = (INT32)(point[1] * 65536.0); + + if (char_grayscale) + { + INT32 *temp; + for (col = 0; col < newWidth; col++) + { + register int x = xValue >> 16, y = yValue >> 16; + int pixvalue, error; + + pixvalue = ((x >= 0 && x < width && y >= 0 && y < height) ? + char_grayscale[x + y * (width + 1)] : 0) + + thisrow[col] / 16; + if (pixvalue > 255) pixvalue = 255; + else if (pixvalue < 0) pixvalue = 0; + + /* Choose the bit value and set resulting error value */ + if (pixvalue >= 128) + { + newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7]; + error = pixvalue - 255; + } + else + error = -pixvalue; + + /* Diffuse the error */ + thisrow[col + 1] += error * 7; + nextrow[col - 1] += error * 3; + nextrow[col] += error * 5; + nextrow[col + 1] = error; + + xValue += deltaX; + yValue += deltaY; + } + + /* Add in error values that fell off either end */ + nextrow[0] += nextrow[-1]; + nextrow[newWidth - 2] += thisrow[newWidth]; + nextrow[newWidth - 1] += nextrow[newWidth]; + nextrow[newWidth] = 0; + + temp = nextrow; + nextrow = thisrow; + thisrow = temp; + nextrow[-1] = nextrow[0] = 0; + } + else + { + for (col = 0; col < newWidth; col++) + { + register int x = xValue >> 16, y = yValue >> 16; + + if (x >= 0 && x < width && y >= 0 && y < height) + { + /* Use point-sampling for rescaling. */ + + if (bitmap[(x >> 3) + y * bpr] & mask[x & 0x7]) + newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7]; + } + + xValue += deltaX; + yValue += deltaY; + } + } + } + + + if (char_grayscale) + { + free(char_grayscale); + free(diffusion_workspace); + } +} + +static FontPtr +BitmapScaleBitmaps(FontPtr pf, /* scaled font */ + FontPtr opf, /* originating font */ + double widthMult, /* glyphs width scale factor */ + double heightMult, /* glyphs height scale factor */ + FontScalablePtr vals) +{ + register int i; + int nchars = 0; + char *glyphBytes; + BitmapFontPtr bitmapFont, + obitmapFont; + CharInfoPtr pci, + opci; + FontInfoPtr pfi; + int glyph; + unsigned bytestoalloc = 0; + int firstCol, lastCol, firstRow, lastRow; + + double xform[4], inv_xform[4]; + double xmult, ymult; + + bitmapFont = (BitmapFontPtr) pf->fontPrivate; + obitmapFont = (BitmapFontPtr) opf->fontPrivate; + + if (!compute_xform_matrix(vals, widthMult, heightMult, xform, + inv_xform, &xmult, &ymult)) + goto bail; + + pfi = &pf->info; + firstCol = pfi->firstCol; + lastCol = pfi->lastCol; + firstRow = pfi->firstRow; + lastRow = pfi->lastRow; + + nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1); + glyph = pf->glyph; + for (i = 0; i < nchars; i++) + { + if ((pci = ACCESSENCODING(bitmapFont->encoding, i))) + bytestoalloc += BYTES_FOR_GLYPH(pci, glyph); + } + + /* Do we add the font malloc stuff for VALUE ADDED ? */ + /* Will need to remember to free in the Unload routine */ + + + bitmapFont->bitmaps = calloc(1, bytestoalloc); + if (!bitmapFont->bitmaps) { + fprintf(stderr, "Error: Couldn't allocate bitmaps (%d)\n", bytestoalloc); + goto bail; + } + + glyphBytes = bitmapFont->bitmaps; + for (i = 0; i < nchars; i++) + { + if ((pci = ACCESSENCODING(bitmapFont->encoding, i)) && + (opci = ACCESSENCODING(obitmapFont->encoding, OLDINDEX(i)))) + { + pci->bits = glyphBytes; + ScaleBitmap (pf, opci, pci, inv_xform, + widthMult, heightMult); + glyphBytes += BYTES_FOR_GLYPH(pci, glyph); + } + } + return pf; + +bail: + if (pf) + free(pf); + if (bitmapFont) { + free(bitmapFont->metrics); + free(bitmapFont->ink_metrics); + free(bitmapFont->bitmaps); + if(bitmapFont->encoding) + for(i=0; iencoding[i]); + free(bitmapFont->encoding); + } + return NULL; +} + +/* ARGSUSED */ +int +BitmapOpenScalable (FontPathElementPtr fpe, + FontPtr *pFont, + int flags, + FontEntryPtr entry, + char *fileName, /* unused */ + FontScalablePtr vals, + fsBitmapFormat format, + fsBitmapFormatMask fmask, + FontPtr non_cachable_font) /* We don't do licensing */ +{ + FontScalableRec best; + FontPtr font = NullFont; + double dx, sdx, + dy, sdy, + savedX, savedY; + FontPropPtr props; + char *isStringProp = NULL; + int propCount; + int status; + long sWidth; + + FontEntryPtr scaleFrom; + FontPathElementPtr scaleFPE = NULL; + FontPtr sourceFont; + char fontName[MAXFONTNAMELEN]; + + /* Can't deal with mix-endian fonts yet */ + + + /* Reject outrageously small font sizes to keep the math from + blowing up. */ + if (get_matrix_vertical_component(vals->pixel_matrix) < 1.0 || + get_matrix_horizontal_component(vals->pixel_matrix) < 1.0) + return BadFontName; + + scaleFrom = FindBestToScale(fpe, entry, vals, &best, &dx, &dy, &sdx, &sdy, + &scaleFPE); + + if (!scaleFrom) + return BadFontName; + + status = FontFileOpenBitmap(scaleFPE, &sourceFont, LoadAll, scaleFrom, + format, fmask); + + if (status != Successful) + return BadFontName; + + if (!vals->width) + vals->width = best.width * dx; + + /* Compute the scaled font */ + + savedX = dx; + savedY = dy; + font = ScaleFont(sourceFont, dx, dy, sdx, sdy, vals, &dx, &dy, &sWidth); + if (font) + font = BitmapScaleBitmaps(font, sourceFont, savedX, savedY, vals); + + if (!font) + { + if (!sourceFont->refcnt) + FontFileCloseFont((FontPathElementPtr) 0, sourceFont); + return AllocError; + } + + /* Prepare font properties for the new font */ + + strcpy (fontName, scaleFrom->name.name); + FontParseXLFDName (fontName, vals, FONT_XLFD_REPLACE_VALUE); + + propCount = ComputeScaledProperties(&sourceFont->info, fontName, vals, + dx, dy, sdx, sdy, sWidth, &props, + &isStringProp); + + if (!sourceFont->refcnt) + FontFileCloseFont((FontPathElementPtr) 0, sourceFont); + + if (propCount && (!props || !isStringProp)) + { + font->info.nprops = 0; + font->info.props = (FontPropPtr)0; + font->info.isStringProp = (char *)0; + bitmapUnloadScalable(font); + return AllocError; + } + + font->info.props = props; + font->info.nprops = propCount; + font->info.isStringProp = isStringProp; + + *pFont = font; + return Successful; +} + +int +BitmapGetInfoScalable (FontPathElementPtr fpe, + FontInfoPtr pFontInfo, + FontEntryPtr entry, + FontNamePtr fontName, + char *fileName, + FontScalablePtr vals) +{ + FontPtr pfont; + int flags = 0; + long format = 0; /* It doesn't matter what format for just info */ + long fmask = 0; + int ret; + + ret = BitmapOpenScalable(fpe, &pfont, flags, entry, fileName, vals, + format, fmask, NULL); + if (ret != Successful) + return ret; + *pFontInfo = pfont->info; + + pfont->info.nprops = 0; + pfont->info.props = NULL; + pfont->info.isStringProp = NULL; + + (*pfont->unload_font)(pfont); + return Successful; +} + +static void +bitmapUnloadScalable (FontPtr pFont) +{ + BitmapFontPtr bitmapFont; + FontInfoPtr pfi; + int i, nencoding; + + bitmapFont = (BitmapFontPtr) pFont->fontPrivate; + pfi = &pFont->info; + free (pfi->props); + free (pfi->isStringProp); + if(bitmapFont->encoding) { + nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * + (pFont->info.lastRow - pFont->info.firstRow + 1); + for(i=0; iencoding[i]); + } + free (bitmapFont->encoding); + free (bitmapFont->bitmaps); + free (bitmapFont->ink_metrics); + free (bitmapFont->metrics); + free (pFont->fontPrivate); + DestroyFontRec (pFont); +} diff --git a/src/bitmap/fontink.c b/src/bitmap/fontink.c new file mode 100755 index 0000000..ad7091f --- /dev/null +++ b/src/bitmap/fontink.c @@ -0,0 +1,216 @@ +/* + +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +static unsigned char ink_mask_msb[8] = { + 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, +}; + +static unsigned char ink_mask_lsb[8] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, +}; + +void +FontCharInkMetrics(FontPtr pFont, CharInfoPtr pCI, xCharInfo *pInk) +{ + int leftBearing, + ascent, + descent; + register int vpos, + hpos, + bpos = 0; + int bitmapByteWidth, + bitmapByteWidthPadded; + int bitmapBitWidth; + int span; + register unsigned char *p; + unsigned char *ink_mask = 0; + register int bmax; + register unsigned char charbits; + + if (pFont->bit == MSBFirst) + ink_mask = ink_mask_msb; + else if (pFont->bit == LSBFirst) + ink_mask = ink_mask_lsb; + pInk->characterWidth = pCI->metrics.characterWidth; + pInk->attributes = pCI->metrics.attributes; + + leftBearing = pCI->metrics.leftSideBearing; + ascent = pCI->metrics.ascent; + descent = pCI->metrics.descent; + bitmapBitWidth = GLYPHWIDTHPIXELS(pCI); + bitmapByteWidth = GLYPHWIDTHBYTES(pCI); + bitmapByteWidthPadded = BYTES_PER_ROW(bitmapBitWidth, pFont->glyph); + span = bitmapByteWidthPadded - bitmapByteWidth; + + p = (unsigned char *) pCI->bits; + for (vpos = descent + ascent; --vpos >= 0;) { + for (hpos = bitmapByteWidth; --hpos >= 0;) { + if (*p++ != 0) + goto found_ascent; + } + p += span; + } + /* + * special case -- font with no bits gets all zeros + */ + pInk->leftSideBearing = leftBearing; + pInk->rightSideBearing = leftBearing; + pInk->ascent = 0; + pInk->descent = 0; + return; +found_ascent: + pInk->ascent = vpos - descent + 1; + + p = ((unsigned char *) pCI->bits) + bitmapByteWidthPadded * + (descent + ascent - 1) + bitmapByteWidth; + + for (vpos = descent + ascent; --vpos >= 0;) { + for (hpos = bitmapByteWidth; --hpos >= 0;) { + if (*--p != 0) + goto found_descent; + } + p -= span; + } +found_descent: + pInk->descent = vpos - ascent + 1; + + bmax = 8; + for (hpos = 0; hpos < bitmapByteWidth; hpos++) { + charbits = 0; + p = (unsigned char *) pCI->bits + hpos; + for (vpos = descent + ascent; --vpos >= 0; p += bitmapByteWidthPadded) + charbits |= *p; + if (charbits) { + if (hpos == bitmapByteWidth - 1) + bmax = bitmapBitWidth - (hpos << 3); + p = ink_mask; + for (bpos = bmax; --bpos >= 0;) { + if (charbits & *p++) + goto found_left; + } + } + } +found_left: + pInk->leftSideBearing = leftBearing + (hpos << 3) + bmax - bpos - 1; + + bmax = bitmapBitWidth - ((bitmapByteWidth - 1) << 3); + for (hpos = bitmapByteWidth; --hpos >= 0;) { + charbits = 0; + p = (unsigned char *) pCI->bits + hpos; + for (vpos = descent + ascent; --vpos >= 0; p += bitmapByteWidthPadded) + charbits |= *p; + if (charbits) { + p = ink_mask + bmax; + for (bpos = bmax; --bpos >= 0;) { + if (charbits & *--p) + goto found_right; + } + } + bmax = 8; + } +found_right: + pInk->rightSideBearing = leftBearing + (hpos << 3) + bpos + 1; +} + +#define ISBITONMSB(x, line) ((line)[(x)/8] & (1 << (7-((x)%8)))) +#define SETBITMSB(x, line) ((line)[(x)/8] |= (1 << (7-((x)%8)))) +#define ISBITONLSB(x, line) ((line)[(x)/8] & (1 << ((x)%8))) +#define SETBITLSB(x, line) ((line)[(x)/8] |= (1 << ((x)%8))) + +#define Min(a,b) ((a)<(b)?(a):(b)) +#define Max(a,b) ((a)>(b)?(a):(b)) + +void +FontCharReshape(FontPtr pFont, CharInfoPtr pSrc, CharInfoPtr pDst) +{ + int x, + y; + unsigned char *in_line, + *out_line; + unsigned char *oldglyph, + *newglyph; + int inwidth; + int outwidth, + outheight; + int out_bytes, + in_bytes; + int y_min, + y_max, + x_min, + x_max; + + newglyph = (unsigned char *) pDst->bits; + outwidth = pDst->metrics.rightSideBearing - pDst->metrics.leftSideBearing; + outheight = pDst->metrics.descent + pDst->metrics.ascent; + out_bytes = BYTES_PER_ROW(outwidth, pFont->glyph); + + oldglyph = (unsigned char *) pSrc->bits; + inwidth = pSrc->metrics.rightSideBearing - pSrc->metrics.leftSideBearing; + in_bytes = BYTES_PER_ROW(inwidth, pFont->glyph); + + bzero(newglyph, out_bytes * outheight); + in_line = oldglyph; + out_line = newglyph; + y_min = Max(-pSrc->metrics.ascent, -pDst->metrics.ascent); + y_max = Min(pSrc->metrics.descent, pDst->metrics.descent); + x_min = Max(pSrc->metrics.leftSideBearing, pDst->metrics.leftSideBearing); + x_max = Min(pSrc->metrics.rightSideBearing, pDst->metrics.rightSideBearing); + in_line += (y_min + pSrc->metrics.ascent) * in_bytes; + out_line += (y_min + pDst->metrics.ascent) * out_bytes; + if (pFont->bit == MSBFirst) { + for (y = y_min; y < y_max; y++) { + for (x = x_min; x < x_max; x++) { + if (ISBITONMSB(x - pSrc->metrics.leftSideBearing, in_line)) + SETBITMSB(x - pDst->metrics.leftSideBearing, out_line); + } + in_line += in_bytes; + out_line += out_bytes; + } + } else { + for (y = y_min; y < y_max; y++) { + for (x = x_min; x < x_max; x++) { + if (ISBITONLSB(x - pSrc->metrics.leftSideBearing, in_line)) + SETBITLSB(x - pDst->metrics.leftSideBearing, out_line); + } + in_line += in_bytes; + out_line += out_bytes; + } + } +} diff --git a/src/bitmap/pcfread.c b/src/bitmap/pcfread.c new file mode 100755 index 0000000..32f9856 --- /dev/null +++ b/src/bitmap/pcfread.c @@ -0,0 +1,780 @@ +/* + +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#ifndef MAX +#define MAX(a,b) (((a)>(b)) ? a : b) +#endif + +#include +#include + +void +pcfError(const char* message, ...) +{ + va_list args; + + va_start(args, message); + + fprintf(stderr, "PCF Error: "); + vfprintf(stderr, message, args); + va_end(args); +} + +/* Read PCF font files */ + +static void pcfUnloadFont ( FontPtr pFont ); +static int position; + + +#define IS_EOF(file) ((file)->eof == BUFFILEEOF) + +#define FONT_FILE_GETC_ERR(f) (tmp = FontFileGetc(f), BAIL_ON_EOF) + +static int +pcfGetLSB32(FontFilePtr file) +{ + int c; + + c = FontFileGetc(file); + c |= FontFileGetc(file) << 8; + c |= FontFileGetc(file) << 16; + c |= FontFileGetc(file) << 24; + position += 4; + return c; +} + +static int +pcfGetINT32(FontFilePtr file, CARD32 format) +{ + int c; + + if (PCF_BYTE_ORDER(format) == MSBFirst) { + c = FontFileGetc(file) << 24; + c |= FontFileGetc(file) << 16; + c |= FontFileGetc(file) << 8; + c |= FontFileGetc(file); + } else { + c = FontFileGetc(file); + c |= FontFileGetc(file) << 8; + c |= FontFileGetc(file) << 16; + c |= FontFileGetc(file) << 24; + } + position += 4; + return c; +} + +static int +pcfGetINT16(FontFilePtr file, CARD32 format) +{ + int c; + + if (PCF_BYTE_ORDER(format) == MSBFirst) { + c = FontFileGetc(file) << 8; + c |= FontFileGetc(file); + } else { + c = FontFileGetc(file); + c |= FontFileGetc(file) << 8; + } + position += 2; + return c; +} + +#define pcfGetINT8(file, format) (position++, FontFileGetc(file)) + +static PCFTablePtr +pcfReadTOC(FontFilePtr file, int *countp) +{ + CARD32 version; + PCFTablePtr tables; + int count; + int i; + + position = 0; + version = pcfGetLSB32(file); + if (version != PCF_FILE_VERSION) + return (PCFTablePtr) NULL; + count = pcfGetLSB32(file); + if (IS_EOF(file)) return (PCFTablePtr) NULL; + if (count < 0 || count > INT32_MAX / sizeof(PCFTableRec)) { + pcfError("pcfReadTOC(): invalid file format\n"); + return NULL; + } + tables = malloc(count * sizeof(PCFTableRec)); + if (!tables) { + pcfError("pcfReadTOC(): Couldn't allocate tables (%d*%d)\n", count, sizeof(PCFTableRec)); + return (PCFTablePtr) NULL; + } + for (i = 0; i < count; i++) { + tables[i].type = pcfGetLSB32(file); + tables[i].format = pcfGetLSB32(file); + tables[i].size = pcfGetLSB32(file); + tables[i].offset = pcfGetLSB32(file); + if (IS_EOF(file)) goto Bail; + } + + *countp = count; + return tables; + + Bail: + free(tables); + return (PCFTablePtr) NULL; +} + +/* + * PCF supports two formats for metrics, both the regular + * jumbo size, and 'lite' metrics, which are useful + * for most fonts which have even vaguely reasonable + * metrics + */ + +static Bool +pcfGetMetric(FontFilePtr file, CARD32 format, xCharInfo *metric) +{ + metric->leftSideBearing = pcfGetINT16(file, format); + metric->rightSideBearing = pcfGetINT16(file, format); + metric->characterWidth = pcfGetINT16(file, format); + metric->ascent = pcfGetINT16(file, format); + metric->descent = pcfGetINT16(file, format); + metric->attributes = pcfGetINT16(file, format); + if (IS_EOF(file)) return FALSE; + + return TRUE; +} + +static Bool +pcfGetCompressedMetric(FontFilePtr file, CARD32 format, xCharInfo *metric) +{ + metric->leftSideBearing = pcfGetINT8(file, format) - 0x80; + metric->rightSideBearing = pcfGetINT8(file, format) - 0x80; + metric->characterWidth = pcfGetINT8(file, format) - 0x80; + metric->ascent = pcfGetINT8(file, format) - 0x80; + metric->descent = pcfGetINT8(file, format) - 0x80; + metric->attributes = 0; + if (IS_EOF(file)) return FALSE; + + return TRUE; +} + +/* + * Position the file to the begining of the specified table + * in the font file + */ +static Bool +pcfSeekToType(FontFilePtr file, PCFTablePtr tables, int ntables, + CARD32 type, CARD32 *formatp, CARD32 *sizep) +{ + int i; + + for (i = 0; i < ntables; i++) + if (tables[i].type == type) { + if (position > tables[i].offset) + return FALSE; + if (!FontFileSkip(file, tables[i].offset - position)) + return FALSE; + position = tables[i].offset; + *sizep = tables[i].size; + *formatp = tables[i].format; + return TRUE; + } + return FALSE; +} + +static Bool +pcfHasType (PCFTablePtr tables, int ntables, CARD32 type) +{ + int i; + + for (i = 0; i < ntables; i++) + if (tables[i].type == type) + return TRUE; + return FALSE; +} + +/* + * pcfGetProperties + * + * Reads the font properties from the font file, filling in the FontInfo rec + * supplied. Used by by both ReadFont and ReadFontInfo routines. + */ + +static Bool +pcfGetProperties(FontInfoPtr pFontInfo, FontFilePtr file, + PCFTablePtr tables, int ntables) +{ + FontPropPtr props = 0; + int nprops; + char *isStringProp = 0; + CARD32 format; + int i; + CARD32 size; + int string_size; + char *strings; + + /* font properties */ + + if (!pcfSeekToType(file, tables, ntables, PCF_PROPERTIES, &format, &size)) + goto Bail; + format = pcfGetLSB32(file); + if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) + goto Bail; + nprops = pcfGetINT32(file, format); + if (nprops <= 0 || nprops > INT32_MAX / sizeof(FontPropRec)) { + pcfError("pcfGetProperties(): invalid nprops value (%d)\n", nprops); + goto Bail; + } + if (IS_EOF(file)) goto Bail; + props = malloc(nprops * sizeof(FontPropRec)); + if (!props) { + pcfError("pcfGetProperties(): Couldn't allocate props (%d*%d)\n", nprops, sizeof(FontPropRec)); + goto Bail; + } + isStringProp = malloc(nprops * sizeof(char)); + if (!isStringProp) { + pcfError("pcfGetProperties(): Couldn't allocate isStringProp (%d*%d)\n", nprops, sizeof(char)); + goto Bail; + } + for (i = 0; i < nprops; i++) { + props[i].name = pcfGetINT32(file, format); + isStringProp[i] = pcfGetINT8(file, format); + props[i].value = pcfGetINT32(file, format); + if (props[i].name < 0 + || (isStringProp[i] != 0 && isStringProp[i] != 1) + || (isStringProp[i] && props[i].value < 0)) { + pcfError("pcfGetProperties(): invalid file format %d %d %d\n", + props[i].name, isStringProp[i], props[i].value); + goto Bail; + } + if (IS_EOF(file)) goto Bail; + } + /* pad the property array */ + /* + * clever here - nprops is the same as the number of odd-units read, as + * only isStringProp are odd length + */ + if (nprops & 3) + { + i = 4 - (nprops & 3); + (void)FontFileSkip(file, i); + position += i; + } + if (IS_EOF(file)) goto Bail; + string_size = pcfGetINT32(file, format); + if (string_size < 0) goto Bail; + if (IS_EOF(file)) goto Bail; + strings = malloc(string_size); + if (!strings) { + pcfError("pcfGetProperties(): Couldn't allocate strings (%d)\n", string_size); + goto Bail; + } + FontFileRead(file, strings, string_size); + if (IS_EOF(file)) goto Bail; + position += string_size; + for (i = 0; i < nprops; i++) { + props[i].name = MakeAtom(strings + props[i].name, + strlen(strings + props[i].name), TRUE); + if (isStringProp[i]) { + props[i].value = MakeAtom(strings + props[i].value, + strlen(strings + props[i].value), TRUE); + } + } + free(strings); + pFontInfo->isStringProp = isStringProp; + pFontInfo->props = props; + pFontInfo->nprops = nprops; + return TRUE; +Bail: + free(isStringProp); + free(props); + return FALSE; +} + + +/* + * pcfReadAccel + * + * Fill in the accelerator information from the font file; used + * to read both BDF_ACCELERATORS and old style ACCELERATORS + */ + +static Bool +pcfGetAccel(FontInfoPtr pFontInfo, FontFilePtr file, + PCFTablePtr tables, int ntables, CARD32 type) +{ + CARD32 format; + CARD32 size; + + if (!pcfSeekToType(file, tables, ntables, type, &format, &size) || + IS_EOF(file)) + goto Bail; + format = pcfGetLSB32(file); + if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && + !PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) + { + goto Bail; + } + pFontInfo->noOverlap = pcfGetINT8(file, format); + pFontInfo->constantMetrics = pcfGetINT8(file, format); + pFontInfo->terminalFont = pcfGetINT8(file, format); + pFontInfo->constantWidth = pcfGetINT8(file, format); + pFontInfo->inkInside = pcfGetINT8(file, format); + pFontInfo->inkMetrics = pcfGetINT8(file, format); + pFontInfo->drawDirection = pcfGetINT8(file, format); + pFontInfo->anamorphic = FALSE; + pFontInfo->cachable = TRUE; + /* natural alignment */ pcfGetINT8(file, format); + pFontInfo->fontAscent = pcfGetINT32(file, format); + pFontInfo->fontDescent = pcfGetINT32(file, format); + pFontInfo->maxOverlap = pcfGetINT32(file, format); + if (IS_EOF(file)) goto Bail; + if (!pcfGetMetric(file, format, &pFontInfo->minbounds)) + goto Bail; + if (!pcfGetMetric(file, format, &pFontInfo->maxbounds)) + goto Bail; + if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) { + if (!pcfGetMetric(file, format, &pFontInfo->ink_minbounds)) + goto Bail; + if (!pcfGetMetric(file, format, &pFontInfo->ink_maxbounds)) + goto Bail; + } else { + pFontInfo->ink_minbounds = pFontInfo->minbounds; + pFontInfo->ink_maxbounds = pFontInfo->maxbounds; + } + return TRUE; +Bail: + return FALSE; +} + +int +pcfReadFont(FontPtr pFont, FontFilePtr file, + int bit, int byte, int glyph, int scan) +{ + CARD32 format; + CARD32 size; + BitmapFontPtr bitmapFont = 0; + int i; + PCFTablePtr tables = 0; + int ntables; + int nmetrics; + int nbitmaps; + int sizebitmaps; + int nink_metrics; + CharInfoPtr metrics = 0; + xCharInfo *ink_metrics = 0; + char *bitmaps = 0; + CharInfoPtr **encoding = 0; + int nencoding = 0; + int encodingOffset; + CARD32 bitmapSizes[GLYPHPADOPTIONS]; + CARD32 *offsets = 0; + Bool hasBDFAccelerators; + + pFont->info.nprops = 0; + pFont->info.props = 0; + if (!(tables = pcfReadTOC(file, &ntables))) + goto Bail; + + /* properties */ + + if (!pcfGetProperties(&pFont->info, file, tables, ntables)) + goto Bail; + + /* Use the old accelerators if no BDF accelerators are in the file */ + + hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS); + if (!hasBDFAccelerators) + if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_ACCELERATORS)) + goto Bail; + + /* metrics */ + + if (!pcfSeekToType(file, tables, ntables, PCF_METRICS, &format, &size)) { + goto Bail; + } + format = pcfGetLSB32(file); + if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && + !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) { + goto Bail; + } + if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) + nmetrics = pcfGetINT32(file, format); + else + nmetrics = pcfGetINT16(file, format); + if (IS_EOF(file)) goto Bail; + if (nmetrics < 0 || nmetrics > INT32_MAX / sizeof(CharInfoRec)) { + pcfError("pcfReadFont(): invalid file format\n"); + goto Bail; + } + metrics = malloc(nmetrics * sizeof(CharInfoRec)); + if (!metrics) { + pcfError("pcfReadFont(): Couldn't allocate metrics (%d*%d)\n", nmetrics, sizeof(CharInfoRec)); + goto Bail; + } + for (i = 0; i < nmetrics; i++) + if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) { + if (!pcfGetMetric(file, format, &(metrics + i)->metrics)) + goto Bail; + } else { + if (!pcfGetCompressedMetric(file, format, &(metrics + i)->metrics)) + goto Bail; + } + + /* bitmaps */ + + if (!pcfSeekToType(file, tables, ntables, PCF_BITMAPS, &format, &size)) + goto Bail; + format = pcfGetLSB32(file); + if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) + goto Bail; + + nbitmaps = pcfGetINT32(file, format); + if (nbitmaps != nmetrics || IS_EOF(file)) + goto Bail; + /* nmetrics is already ok, so nbitmap also is */ + offsets = malloc(nbitmaps * sizeof(CARD32)); + if (!offsets) { + pcfError("pcfReadFont(): Couldn't allocate offsets (%d*%d)\n", nbitmaps, sizeof(CARD32)); + goto Bail; + } + for (i = 0; i < nbitmaps; i++) { + offsets[i] = pcfGetINT32(file, format); + if (IS_EOF(file)) goto Bail; + } + + for (i = 0; i < GLYPHPADOPTIONS; i++) { + bitmapSizes[i] = pcfGetINT32(file, format); + if (IS_EOF(file)) goto Bail; + if (bitmapSizes[i] < 0) goto Bail; + } + + sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX(format)]; + /* guard against completely empty font */ + bitmaps = malloc(sizebitmaps ? sizebitmaps : 1); + if (!bitmaps) { + pcfError("pcfReadFont(): Couldn't allocate bitmaps (%d)\n", sizebitmaps ? sizebitmaps : 1); + goto Bail; + } + FontFileRead(file, bitmaps, sizebitmaps); + if (IS_EOF(file)) goto Bail; + position += sizebitmaps; + + if (PCF_BIT_ORDER(format) != bit) + BitOrderInvert((unsigned char *)bitmaps, sizebitmaps); + if ((PCF_BYTE_ORDER(format) == PCF_BIT_ORDER(format)) != (bit == byte)) { + switch (bit == byte ? PCF_SCAN_UNIT(format) : scan) { + case 1: + break; + case 2: + TwoByteSwap((unsigned char *)bitmaps, sizebitmaps); + break; + case 4: + FourByteSwap((unsigned char *)bitmaps, sizebitmaps); + break; + } + } + if (PCF_GLYPH_PAD(format) != glyph) { + char *padbitmaps; + int sizepadbitmaps; + int old, + new; + xCharInfo *metric; + + sizepadbitmaps = bitmapSizes[PCF_SIZE_TO_INDEX(glyph)]; + padbitmaps = malloc(sizepadbitmaps); + if (!padbitmaps) { + pcfError("pcfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps); + goto Bail; + } + new = 0; + for (i = 0; i < nbitmaps; i++) { + old = offsets[i]; + metric = &metrics[i].metrics; + offsets[i] = new; + new += RepadBitmap(bitmaps + old, padbitmaps + new, + PCF_GLYPH_PAD(format), glyph, + metric->rightSideBearing - metric->leftSideBearing, + metric->ascent + metric->descent); + } + free(bitmaps); + bitmaps = padbitmaps; + } + for (i = 0; i < nbitmaps; i++) + metrics[i].bits = bitmaps + offsets[i]; + + free(offsets); + offsets = NULL; + + /* ink metrics ? */ + + ink_metrics = NULL; + if (pcfSeekToType(file, tables, ntables, PCF_INK_METRICS, &format, &size)) { + format = pcfGetLSB32(file); + if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && + !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) { + goto Bail; + } + if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) + nink_metrics = pcfGetINT32(file, format); + else + nink_metrics = pcfGetINT16(file, format); + if (IS_EOF(file)) goto Bail; + if (nink_metrics != nmetrics) + goto Bail; + /* nmetrics already checked */ + ink_metrics = malloc(nink_metrics * sizeof(xCharInfo)); + if (!ink_metrics) { + pcfError("pcfReadFont(): Couldn't allocate ink_metrics (%d*%d)\n", nink_metrics, sizeof(xCharInfo)); + goto Bail; + } + for (i = 0; i < nink_metrics; i++) + if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) { + if (!pcfGetMetric(file, format, ink_metrics + i)) + goto Bail; + } else { + if (!pcfGetCompressedMetric(file, format, ink_metrics + i)) + goto Bail; + } + } + + /* encoding */ + + if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size)) + goto Bail; + format = pcfGetLSB32(file); + if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) + goto Bail; + + pFont->info.firstCol = pcfGetINT16(file, format); + pFont->info.lastCol = pcfGetINT16(file, format); + pFont->info.firstRow = pcfGetINT16(file, format); + pFont->info.lastRow = pcfGetINT16(file, format); + pFont->info.defaultCh = pcfGetINT16(file, format); + if (IS_EOF(file)) goto Bail; + if (pFont->info.firstCol > pFont->info.lastCol || + pFont->info.firstRow > pFont->info.lastRow || + pFont->info.lastCol-pFont->info.firstCol > 255) goto Bail; + + nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * + (pFont->info.lastRow - pFont->info.firstRow + 1); + + encoding = calloc(NUM_SEGMENTS(nencoding), sizeof(CharInfoPtr*)); + if (!encoding) { + pcfError("pcfReadFont(): Couldn't allocate encoding (%d*%d)\n", nencoding, sizeof(CharInfoPtr)); + goto Bail; + } + + pFont->info.allExist = TRUE; + for (i = 0; i < nencoding; i++) { + encodingOffset = pcfGetINT16(file, format); + if (IS_EOF(file)) goto Bail; + if (encodingOffset == 0xFFFF) { + pFont->info.allExist = FALSE; + } else { + if(!encoding[SEGMENT_MAJOR(i)]) { + encoding[SEGMENT_MAJOR(i)]= + calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr)); + if(!encoding[SEGMENT_MAJOR(i)]) + goto Bail; + } + ACCESSENCODINGL(encoding, i) = metrics + encodingOffset; + } + } + + /* BDF style accelerators (i.e. bounds based on encoded glyphs) */ + + if (hasBDFAccelerators) + if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_BDF_ACCELERATORS)) + goto Bail; + + bitmapFont = malloc(sizeof *bitmapFont); + if (!bitmapFont) { + pcfError("pcfReadFont(): Couldn't allocate bitmapFont (%d)\n", sizeof *bitmapFont); + goto Bail; + } + + bitmapFont->version_num = PCF_FILE_VERSION; + bitmapFont->num_chars = nmetrics; + bitmapFont->num_tables = ntables; + bitmapFont->metrics = metrics; + bitmapFont->ink_metrics = ink_metrics; + bitmapFont->bitmaps = bitmaps; + bitmapFont->encoding = encoding; + bitmapFont->pDefault = (CharInfoPtr) 0; + if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) { + unsigned int r, + c, + cols; + + r = pFont->info.defaultCh >> 8; + c = pFont->info.defaultCh & 0xFF; + if (pFont->info.firstRow <= r && r <= pFont->info.lastRow && + pFont->info.firstCol <= c && c <= pFont->info.lastCol) { + cols = pFont->info.lastCol - pFont->info.firstCol + 1; + r = r - pFont->info.firstRow; + c = c - pFont->info.firstCol; + bitmapFont->pDefault = ACCESSENCODING(encoding, r * cols + c); + } + } + bitmapFont->bitmapExtra = (BitmapExtraPtr) 0; + pFont->fontPrivate = (pointer) bitmapFont; + pFont->get_glyphs = bitmapGetGlyphs; + pFont->get_metrics = bitmapGetMetrics; + pFont->unload_font = pcfUnloadFont; + pFont->unload_glyphs = NULL; + pFont->bit = bit; + pFont->byte = byte; + pFont->glyph = glyph; + pFont->scan = scan; + free(tables); + return Successful; +Bail: + free(ink_metrics); + if(encoding) { + for(i=0; iinfo.props); + pFont->info.nprops = 0; + pFont->info.props = 0; + free (pFont->info.isStringProp); + free(bitmapFont); + free(tables); + free(offsets); + return AllocError; +} + +int +pcfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file) +{ + PCFTablePtr tables; + int ntables; + CARD32 format; + CARD32 size; + int nencoding; + Bool hasBDFAccelerators; + + pFontInfo->isStringProp = NULL; + pFontInfo->props = NULL; + pFontInfo->nprops = 0; + + if (!(tables = pcfReadTOC(file, &ntables))) + goto Bail; + + /* properties */ + + if (!pcfGetProperties(pFontInfo, file, tables, ntables)) + goto Bail; + + /* Use the old accelerators if no BDF accelerators are in the file */ + + hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS); + if (!hasBDFAccelerators) + if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_ACCELERATORS)) + goto Bail; + + /* encoding */ + + if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size)) + goto Bail; + format = pcfGetLSB32(file); + if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) + goto Bail; + + pFontInfo->firstCol = pcfGetINT16(file, format); + pFontInfo->lastCol = pcfGetINT16(file, format); + pFontInfo->firstRow = pcfGetINT16(file, format); + pFontInfo->lastRow = pcfGetINT16(file, format); + pFontInfo->defaultCh = pcfGetINT16(file, format); + if (IS_EOF(file)) goto Bail; + if (pFontInfo->firstCol > pFontInfo->lastCol || + pFontInfo->firstRow > pFontInfo->lastRow || + pFontInfo->lastCol-pFontInfo->firstCol > 255) goto Bail; + + nencoding = (pFontInfo->lastCol - pFontInfo->firstCol + 1) * + (pFontInfo->lastRow - pFontInfo->firstRow + 1); + + pFontInfo->allExist = TRUE; + while (nencoding--) { + if (pcfGetINT16(file, format) == 0xFFFF) + pFontInfo->allExist = FALSE; + if (IS_EOF(file)) goto Bail; + } + if (IS_EOF(file)) goto Bail; + + /* BDF style accelerators (i.e. bounds based on encoded glyphs) */ + + if (hasBDFAccelerators) + if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_BDF_ACCELERATORS)) + goto Bail; + + free(tables); + return Successful; +Bail: + pFontInfo->nprops = 0; + free (pFontInfo->props); + free (pFontInfo->isStringProp); + free(tables); + return AllocError; +} + +static void +pcfUnloadFont(FontPtr pFont) +{ + BitmapFontPtr bitmapFont; + int i,nencoding; + + bitmapFont = (BitmapFontPtr) pFont->fontPrivate; + free(bitmapFont->ink_metrics); + if(bitmapFont->encoding) { + nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * + (pFont->info.lastRow - pFont->info.firstRow + 1); + for(i=0; iencoding[i]); + } + free(bitmapFont->encoding); + free(bitmapFont->bitmaps); + free(bitmapFont->metrics); + free(pFont->info.isStringProp); + free(pFont->info.props); + free(bitmapFont); + DestroyFontRec(pFont); +} diff --git a/src/bitmap/pcfwrite.c b/src/bitmap/pcfwrite.c new file mode 100755 index 0000000..3ac07b3 --- /dev/null +++ b/src/bitmap/pcfwrite.c @@ -0,0 +1,466 @@ +/* + +Copyright 1990, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +/* Write PCF font files */ + +static CARD32 current_position; + +static int +pcfWrite(FontFilePtr file, char *b, int c) +{ + current_position += c; + return FontFileWrite(file, b, c); +} + +static int +pcfPutLSB32(FontFilePtr file, int c) +{ + current_position += 4; + (void) FontFilePutc(c, file); + (void) FontFilePutc(c >> 8, file); + (void) FontFilePutc(c >> 16, file); + return FontFilePutc(c >> 24, file); +} + +static int +pcfPutINT32(FontFilePtr file, CARD32 format, int c) +{ + current_position += 4; + if (PCF_BYTE_ORDER(format) == MSBFirst) { + (void) FontFilePutc(c >> 24, file); + (void) FontFilePutc(c >> 16, file); + (void) FontFilePutc(c >> 8, file); + return FontFilePutc(c, file); + } else { + (void) FontFilePutc(c, file); + (void) FontFilePutc(c >> 8, file); + (void) FontFilePutc(c >> 16, file); + return FontFilePutc(c >> 24, file); + } +} + +static int +pcfPutINT16(FontFilePtr file, CARD32 format, int c) +{ + current_position += 2; + if (PCF_BYTE_ORDER(format) == MSBFirst) { + (void) FontFilePutc(c >> 8, file); + return FontFilePutc(c, file); + } else { + (void) FontFilePutc(c, file); + return FontFilePutc(c >> 8, file); + } +} + +/*ARGSUSED*/ +static int +pcfPutINT8(FontFilePtr file, CARD32 format, int c) +{ + current_position += 1; + return FontFilePutc(c, file); +} + +static void +pcfWriteTOC(FontFilePtr file, PCFTablePtr table, int count) +{ + CARD32 version; + int i; + + version = PCF_FILE_VERSION; + pcfPutLSB32(file, version); + pcfPutLSB32(file, count); + for (i = 0; i < count; i++) { + pcfPutLSB32(file, table->type); + pcfPutLSB32(file, table->format); + pcfPutLSB32(file, table->size); + pcfPutLSB32(file, table->offset); + table++; + } +} + +static void +pcfPutCompressedMetric(FontFilePtr file, CARD32 format, xCharInfo *metric) +{ + pcfPutINT8(file, format, metric->leftSideBearing + 0x80); + pcfPutINT8(file, format, metric->rightSideBearing + 0x80); + pcfPutINT8(file, format, metric->characterWidth + 0x80); + pcfPutINT8(file, format, metric->ascent + 0x80); + pcfPutINT8(file, format, metric->descent + 0x80); +} + +static void +pcfPutMetric(FontFilePtr file, CARD32 format, xCharInfo *metric) +{ + pcfPutINT16(file, format, metric->leftSideBearing); + pcfPutINT16(file, format, metric->rightSideBearing); + pcfPutINT16(file, format, metric->characterWidth); + pcfPutINT16(file, format, metric->ascent); + pcfPutINT16(file, format, metric->descent); + pcfPutINT16(file, format, metric->attributes); +} + +static void +pcfPutBitmap(FontFilePtr file, CARD32 format, CharInfoPtr pCI) +{ + int count; + unsigned char *bits; + + count = BYTES_FOR_GLYPH(pCI, PCF_GLYPH_PAD(format)); + bits = (unsigned char *) pCI->bits; + current_position += count; + while (count--) + FontFilePutc(*bits++, file); +} + +static void +pcfPutAccel(FontFilePtr file, CARD32 format, FontInfoPtr pFontInfo) +{ + pcfPutINT8(file, format, pFontInfo->noOverlap); + pcfPutINT8(file, format, pFontInfo->constantMetrics); + pcfPutINT8(file, format, pFontInfo->terminalFont); + pcfPutINT8(file, format, pFontInfo->constantWidth); + pcfPutINT8(file, format, pFontInfo->inkInside); + pcfPutINT8(file, format, pFontInfo->inkMetrics); + pcfPutINT8(file, format, pFontInfo->drawDirection); + pcfPutINT8(file, format, 0); + pcfPutINT32(file, format, pFontInfo->fontAscent); + pcfPutINT32(file, format, pFontInfo->fontDescent); + pcfPutINT32(file, format, pFontInfo->maxOverlap); + pcfPutMetric(file, format, &pFontInfo->minbounds); + pcfPutMetric(file, format, &pFontInfo->maxbounds); + if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) { + pcfPutMetric(file, format, &pFontInfo->ink_minbounds); + pcfPutMetric(file, format, &pFontInfo->ink_maxbounds); + } +} + +#define S32 4 +#define S16 2 +#define S8 1 + +#define Pad(s) (RoundUp(s) - (s)) +#define RoundUp(s) (((s) + 3) & ~3) + +#define Compressable(i) (-128 <= (i) && (i) <= 127) + +#define CanCompressMetric(m) (Compressable((m)->leftSideBearing) && \ + Compressable((m)->rightSideBearing) && \ + Compressable((m)->characterWidth) && \ + Compressable((m)->ascent) && \ + Compressable((m)->descent) && \ + (m)->attributes == 0) + +#define CanCompressMetrics(min,max) (CanCompressMetric(min) && CanCompressMetric(max)) + +static char * +pcfNameForAtom(Atom a) +{ + return NameForAtom(a); +} + +int +pcfWriteFont(FontPtr pFont, FontFilePtr file) +{ + PCFTableRec tables[32], + *table; + CARD32 mask, + bit; + int ntables; + int size; + CARD32 format; + int i; + int cur_table; + int prop_string_size; + int glyph_string_size; + xCharInfo *minbounds, + *maxbounds; + xCharInfo *ink_minbounds, + *ink_maxbounds; + BitmapFontPtr bitmapFont; + int nencodings = 0; + int header_size; + FontPropPtr offsetProps; + int prop_pad = 0; + char *atom_name; + int glyph; + CARD32 offset; + + bitmapFont = (BitmapFontPtr) pFont->fontPrivate; + if (bitmapFont->bitmapExtra) { + minbounds = &bitmapFont->bitmapExtra->info.minbounds; + maxbounds = &bitmapFont->bitmapExtra->info.maxbounds; + ink_minbounds = &bitmapFont->bitmapExtra->info.ink_minbounds; + ink_maxbounds = &bitmapFont->bitmapExtra->info.ink_maxbounds; + } else { + minbounds = &pFont->info.minbounds; + maxbounds = &pFont->info.maxbounds; + ink_minbounds = &pFont->info.ink_minbounds; + ink_maxbounds = &pFont->info.ink_maxbounds; + } + offsetProps = malloc(pFont->info.nprops * sizeof(FontPropRec)); + if (!offsetProps) { + pcfError("pcfWriteFont(): Couldn't allocate offsetProps (%d*%d)", pFont->info.nprops, sizeof(FontPropRec)); + return AllocError; + } + prop_string_size = 0; + for (i = 0; i < pFont->info.nprops; i++) { + offsetProps[i].name = prop_string_size; + prop_string_size += strlen(pcfNameForAtom(pFont->info.props[i].name)) + 1; + if (pFont->info.isStringProp[i]) { + offsetProps[i].value = prop_string_size; + prop_string_size += strlen(pcfNameForAtom(pFont->info.props[i].value)) + 1; + } else + offsetProps[i].value = pFont->info.props[i].value; + } + format = PCF_FORMAT(pFont->bit, pFont->byte, pFont->glyph, pFont->scan); + mask = 0xFFFFFFF; + ntables = 0; + table = tables; + while (mask) { + bit = lowbit(mask); + mask &= ~bit; + table->type = bit; + switch (bit) { + case PCF_PROPERTIES: + table->format = PCF_DEFAULT_FORMAT | format; + size = S32 + S32 + (S32 + S8 + S32) * pFont->info.nprops; + prop_pad = Pad(size); + table->size = RoundUp(size) + S32 + + RoundUp(prop_string_size); + table++; + break; + case PCF_ACCELERATORS: + if (bitmapFont->bitmapExtra->info.inkMetrics) + table->format = PCF_ACCEL_W_INKBOUNDS | format; + else + table->format = PCF_DEFAULT_FORMAT | format; + table->size = 100; + table++; + break; + case PCF_METRICS: + if (CanCompressMetrics(minbounds, maxbounds)) { + table->format = PCF_COMPRESSED_METRICS | format; + size = S32 + S16 + bitmapFont->num_chars * (5 * S8); + table->size = RoundUp(size); + } else { + table->format = PCF_DEFAULT_FORMAT | format; + table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16); + } + table++; + break; + case PCF_BITMAPS: + table->format = PCF_DEFAULT_FORMAT | format; + size = S32 + S32 + bitmapFont->num_chars * S32 + + GLYPHPADOPTIONS * S32 + + bitmapFont->bitmapExtra->bitmapsSizes[PCF_GLYPH_PAD_INDEX(format)]; + table->size = RoundUp(size); + table++; + break; + case PCF_INK_METRICS: + if (bitmapFont->ink_metrics) { + if (CanCompressMetrics(ink_minbounds, ink_maxbounds)) { + table->format = PCF_COMPRESSED_METRICS | format; + size = S32 + S16 + bitmapFont->num_chars * (5 * S8); + table->size = RoundUp(size); + } else { + table->format = PCF_DEFAULT_FORMAT | format; + table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16); + } + table++; + } + break; + case PCF_BDF_ENCODINGS: + table->format = PCF_DEFAULT_FORMAT | format; + nencodings = (pFont->info.lastRow - pFont->info.firstRow + 1) * + (pFont->info.lastCol - pFont->info.firstCol + 1); + size = S32 + 5 * S16 + nencodings * S16; + table->size = RoundUp(size); + table++; + break; + case PCF_SWIDTHS: + table->format = PCF_DEFAULT_FORMAT | format; + table->size = S32 + S32 + bitmapFont->num_chars * S32; + table++; + break; + case PCF_GLYPH_NAMES: + table->format = PCF_DEFAULT_FORMAT | format; + glyph_string_size = 0; + for (i = 0; i < bitmapFont->num_chars; i++) + glyph_string_size += strlen(pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i])) + 1; + table->size = S32 + S32 + bitmapFont->num_chars * S32 + + S32 + RoundUp(glyph_string_size); + table++; + break; + case PCF_BDF_ACCELERATORS: + if (pFont->info.inkMetrics) + table->format = PCF_ACCEL_W_INKBOUNDS | format; + else + table->format = PCF_DEFAULT_FORMAT | format; + table->size = 100; + table++; + break; + } + } + ntables = table - tables; + offset = 0; + header_size = S32 + S32 + ntables * (4 * S32); + offset = header_size; + for (cur_table = 0, table = tables; + cur_table < ntables; + cur_table++, table++) { + table->offset = offset; + offset += table->size; + } + current_position = 0; + pcfWriteTOC(file, tables, ntables); + for (cur_table = 0, table = tables; + cur_table < ntables; + cur_table++, table++) { + if (current_position > table->offset) { + printf("can't go backwards... %d > %d\n", + (int)current_position, (int)table->offset); + free(offsetProps); + return BadFontName; + } + while (current_position < table->offset) + pcfPutINT8(file, format, '\0'); + pcfPutLSB32(file, table->format); + switch (table->type) { + case PCF_PROPERTIES: + pcfPutINT32(file, format, pFont->info.nprops); + for (i = 0; i < pFont->info.nprops; i++) { + pcfPutINT32(file, format, offsetProps[i].name); + pcfPutINT8(file, format, pFont->info.isStringProp[i]); + pcfPutINT32(file, format, offsetProps[i].value); + } + for (i = 0; i < prop_pad; i++) + pcfPutINT8(file, format, 0); + pcfPutINT32(file, format, prop_string_size); + for (i = 0; i < pFont->info.nprops; i++) { + atom_name = pcfNameForAtom(pFont->info.props[i].name); + pcfWrite(file, atom_name, strlen(atom_name) + 1); + if (pFont->info.isStringProp[i]) { + atom_name = pcfNameForAtom(pFont->info.props[i].value); + pcfWrite(file, atom_name, strlen(atom_name) + 1); + } + } + break; + case PCF_ACCELERATORS: + pcfPutAccel(file, table->format, &bitmapFont->bitmapExtra->info); + break; + case PCF_METRICS: + if (PCF_FORMAT_MATCH(table->format, PCF_COMPRESSED_METRICS)) { + pcfPutINT16(file, format, bitmapFont->num_chars); + for (i = 0; i < bitmapFont->num_chars; i++) + pcfPutCompressedMetric(file, format, &bitmapFont->metrics[i].metrics); + } else { + pcfPutINT32(file, format, bitmapFont->num_chars); + for (i = 0; i < bitmapFont->num_chars; i++) + pcfPutMetric(file, format, &bitmapFont->metrics[i].metrics); + } + break; + case PCF_BITMAPS: + pcfPutINT32(file, format, bitmapFont->num_chars); + glyph = PCF_GLYPH_PAD(format); + offset = 0; + for (i = 0; i < bitmapFont->num_chars; i++) { + pcfPutINT32(file, format, offset); + offset += BYTES_FOR_GLYPH(&bitmapFont->metrics[i], glyph); + } + for (i = 0; i < GLYPHPADOPTIONS; i++) { + pcfPutINT32(file, format, + bitmapFont->bitmapExtra->bitmapsSizes[i]); + } + for (i = 0; i < bitmapFont->num_chars; i++) + pcfPutBitmap(file, format, &bitmapFont->metrics[i]); + break; + case PCF_INK_METRICS: + if (PCF_FORMAT_MATCH(table->format, PCF_COMPRESSED_METRICS)) { + pcfPutINT16(file, format, bitmapFont->num_chars); + for (i = 0; i < bitmapFont->num_chars; i++) + pcfPutCompressedMetric(file, format, &bitmapFont->ink_metrics[i]); + } else { + pcfPutINT32(file, format, bitmapFont->num_chars); + for (i = 0; i < bitmapFont->num_chars; i++) + pcfPutMetric(file, format, &bitmapFont->ink_metrics[i]); + } + break; + case PCF_BDF_ENCODINGS: + pcfPutINT16(file, format, pFont->info.firstCol); + pcfPutINT16(file, format, pFont->info.lastCol); + pcfPutINT16(file, format, pFont->info.firstRow); + pcfPutINT16(file, format, pFont->info.lastRow); + pcfPutINT16(file, format, pFont->info.defaultCh); + for (i = 0; i < nencodings; i++) { + if (ACCESSENCODING(bitmapFont->encoding,i)) + pcfPutINT16(file, format, + ACCESSENCODING(bitmapFont->encoding, i) - + bitmapFont->metrics); + else + pcfPutINT16(file, format, 0xFFFF); + } + break; + case PCF_SWIDTHS: + pcfPutINT32(file, format, bitmapFont->num_chars); + for (i = 0; i < bitmapFont->num_chars; i++) + pcfPutINT32(file, format, bitmapFont->bitmapExtra->sWidths[i]); + break; + case PCF_GLYPH_NAMES: + pcfPutINT32(file, format, bitmapFont->num_chars); + offset = 0; + for (i = 0; i < bitmapFont->num_chars; i++) { + pcfPutINT32(file, format, offset); + offset += strlen(pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i])) + 1; + } + pcfPutINT32(file, format, offset); + for (i = 0; i < bitmapFont->num_chars; i++) { + atom_name = pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i]); + pcfWrite(file, atom_name, strlen(atom_name) + 1); + } + break; + case PCF_BDF_ACCELERATORS: + pcfPutAccel(file, table->format, &pFont->info); + break; + } + } + + free(offsetProps); + return Successful; +} diff --git a/src/bitmap/snfread.c b/src/bitmap/snfread.c new file mode 100755 index 0000000..d003cc5 --- /dev/null +++ b/src/bitmap/snfread.c @@ -0,0 +1,508 @@ +/************************************************************************ +Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ + +/* + +Copyright 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include "snfstr.h" + +#include + +static void +snfError(const char* message, ...) +{ + va_list args; + + va_start(args, message); + + fprintf(stderr, "SNF Error: "); + vfprintf(stderr, message, args); + va_end(args); +} + +static void snfUnloadFont(FontPtr pFont); + +static int +snfReadCharInfo(FontFilePtr file, CharInfoPtr charInfo, char *base) +{ + snfCharInfoRec snfCharInfo; + +#define Width(m) ((m).rightSideBearing - (m).leftSideBearing) +#define Height(m) ((m).ascent + (m).descent) + + if (FontFileRead(file, (char *) &snfCharInfo, sizeof snfCharInfo) != + sizeof(snfCharInfo)) { + return BadFontName; + } + charInfo->metrics = snfCharInfo.metrics; + if (snfCharInfo.exists) + charInfo->bits = base + snfCharInfo.byteOffset; + else + charInfo->bits = 0; + return Successful; +} + +static int +snfReadxCharInfo(FontFilePtr file, xCharInfo *charInfo) +{ + snfCharInfoRec snfCharInfo; + + if (FontFileRead(file, (char *) &snfCharInfo, sizeof snfCharInfo) != + sizeof(snfCharInfo)) { + return BadFontName; + } + *charInfo = snfCharInfo.metrics; + return Successful; +} + +static void +snfCopyInfo(snfFontInfoPtr snfInfo, FontInfoPtr pFontInfo) +{ + pFontInfo->firstCol = snfInfo->firstCol; + pFontInfo->lastCol = snfInfo->lastCol; + pFontInfo->firstRow = snfInfo->firstRow; + pFontInfo->lastRow = snfInfo->lastRow; + pFontInfo->defaultCh = snfInfo->chDefault; + pFontInfo->noOverlap = snfInfo->noOverlap; + pFontInfo->terminalFont = snfInfo->terminalFont; + pFontInfo->constantMetrics = snfInfo->constantMetrics; + pFontInfo->constantWidth = snfInfo->constantWidth; + pFontInfo->inkInside = snfInfo->inkInside; + pFontInfo->inkMetrics = snfInfo->inkMetrics; + pFontInfo->allExist = snfInfo->allExist; + pFontInfo->drawDirection = snfInfo->drawDirection; + pFontInfo->anamorphic = FALSE; + pFontInfo->cachable = TRUE; + pFontInfo->maxOverlap = 0; + pFontInfo->minbounds = snfInfo->minbounds.metrics; + pFontInfo->maxbounds = snfInfo->maxbounds.metrics; + pFontInfo->fontAscent = snfInfo->fontAscent; + pFontInfo->fontDescent = snfInfo->fontDescent; + pFontInfo->nprops = snfInfo->nProps; +} + +static int +snfReadProps(snfFontInfoPtr snfInfo, FontInfoPtr pFontInfo, FontFilePtr file) +{ + char *strings; + FontPropPtr pfp; + snfFontPropPtr psnfp; + char *propspace; + int bytestoalloc; + int i; + + bytestoalloc = snfInfo->nProps * sizeof(snfFontPropRec) + + BYTESOFSTRINGINFO(snfInfo); + propspace = malloc(bytestoalloc); + if (!propspace) { + snfError("snfReadProps(): Couldn't allocate propspace (%d)\n", bytestoalloc); + return AllocError; + } + + if (FontFileRead(file, propspace, bytestoalloc) != bytestoalloc) { + free(propspace); + return BadFontName; + } + psnfp = (snfFontPropPtr) propspace; + + strings = propspace + BYTESOFPROPINFO(snfInfo); + + for (i = 0, pfp = pFontInfo->props; i < snfInfo->nProps; i++, pfp++, psnfp++) { + pfp->name = MakeAtom(&strings[psnfp->name], + (unsigned) strlen(&strings[psnfp->name]), 1); + pFontInfo->isStringProp[i] = psnfp->indirect; + if (psnfp->indirect) + pfp->value = (INT32) MakeAtom(&strings[psnfp->value], + (unsigned) strlen(&strings[psnfp->value]), 1); + else + pfp->value = psnfp->value; + } + + free(propspace); + return Successful; +} + +static int +snfReadHeader(snfFontInfoPtr snfInfo, FontFilePtr file) +{ + if (FontFileRead(file, (char *) snfInfo, sizeof *snfInfo) != sizeof *snfInfo) + return BadFontName; + + if (snfInfo->version1 != FONT_FILE_VERSION || + snfInfo->version2 != FONT_FILE_VERSION) + return BadFontName; + return Successful; +} + +static int snf_set; +static int snf_bit, snf_byte, snf_glyph, snf_scan; + +void +SnfSetFormat (int bit, int byte, int glyph, int scan) +{ + snf_bit = bit; + snf_byte = byte; + snf_glyph = glyph; + snf_scan = scan; + snf_set = 1; +} + +static void +SnfGetFormat (int *bit, int *byte, int *glyph, int *scan) +{ + if (!snf_set) + FontDefaultFormat (&snf_bit, &snf_byte, &snf_glyph, &snf_scan); + *bit = snf_bit; + *byte = snf_byte; + *glyph = snf_glyph; + *scan = snf_scan; +} + +int +snfReadFont(FontPtr pFont, FontFilePtr file, + int bit, int byte, int glyph, int scan) +{ + snfFontInfoRec fi; + unsigned bytestoalloc; + int i, j; + char *fontspace; + BitmapFontPtr bitmapFont; + int num_chars; + int bitmapsSize; + int ret; + int metrics_off; + int encoding_off; + int props_off; + int isStringProp_off; + int ink_off; + char *bitmaps; + int def_bit, def_byte, def_glyph, def_scan; + + ret = snfReadHeader(&fi, file); + if (ret != Successful) + return ret; + + SnfGetFormat (&def_bit, &def_byte, &def_glyph, &def_scan); + + /* + * we'll allocate one chunk of memory and split it among the various parts + * of the font: + * + * BitmapFontRec CharInfoRec's Glyphs Encoding DIX Properties Ink CharInfoRec's + * + * If the glyphpad is not the same as the font file, then the glyphs + * are allocated separately, to be later realloc'ed when we know + * how big to make them. + */ + + bitmapsSize = BYTESOFGLYPHINFO(&fi); + num_chars = n2dChars(&fi); + bytestoalloc = sizeof(BitmapFontRec); /* bitmapFont */ + metrics_off = bytestoalloc; + bytestoalloc += num_chars * sizeof(CharInfoRec); /* metrics */ + encoding_off = bytestoalloc; + bytestoalloc += NUM_SEGMENTS(num_chars) * sizeof(CharInfoPtr**); + /* encoding */ + props_off = bytestoalloc; + bytestoalloc += fi.nProps * sizeof(FontPropRec); /* props */ + isStringProp_off = bytestoalloc; + bytestoalloc += fi.nProps * sizeof(char); /* isStringProp */ + bytestoalloc = (bytestoalloc + 3) & ~3; + ink_off = bytestoalloc; + if (fi.inkMetrics) + bytestoalloc += num_chars * sizeof(xCharInfo); /* ink_metrics */ + + fontspace = malloc(bytestoalloc); + if (!fontspace) { + snfError("snfReadFont(): Couldn't allocate fontspace (%d)\n", bytestoalloc); + return AllocError; + } + bitmaps = malloc (bitmapsSize); + if (!bitmaps) + { + snfError("snfReadFont(): Couldn't allocate bitmaps (%d)\n", bitmapsSize); + free (fontspace); + return AllocError; + } + /* + * now fix up pointers + */ + + bitmapFont = (BitmapFontPtr) fontspace; + bitmapFont->num_chars = num_chars; + bitmapFont->metrics = (CharInfoPtr) (fontspace + metrics_off); + bitmapFont->encoding = (CharInfoPtr **) (fontspace + encoding_off); + bitmapFont->bitmaps = bitmaps; + bitmapFont->pDefault = NULL; + bitmapFont->bitmapExtra = NULL; + pFont->info.props = (FontPropPtr) (fontspace + props_off); + pFont->info.isStringProp = (char *) (fontspace + isStringProp_off); + if (fi.inkMetrics) + bitmapFont->ink_metrics = (xCharInfo *) (fontspace + ink_off); + else + bitmapFont->ink_metrics = 0; + + /* + * read the CharInfo + */ + + ret = Successful; + memset(bitmapFont->encoding, 0, + NUM_SEGMENTS(num_chars)*sizeof(CharInfoPtr*)); + for (i = 0; ret == Successful && i < num_chars; i++) { + ret = snfReadCharInfo(file, &bitmapFont->metrics[i], bitmaps); + if (bitmapFont->metrics[i].bits) { + if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) { + bitmapFont->encoding[SEGMENT_MAJOR(i)]= + calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr)); + if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) { + ret = AllocError; + break; + } + } + ACCESSENCODINGL(bitmapFont->encoding,i) = &bitmapFont->metrics[i]; + } + } + + if (ret != Successful) { + free(bitmaps); + if(bitmapFont->encoding) { + for(j=0; jencoding[i]); + } + free(fontspace); + return ret; + } + /* + * read the glyphs + */ + + if (FontFileRead(file, bitmaps, bitmapsSize) != bitmapsSize) { + free(bitmaps); + free(fontspace); + return BadFontName; + } + + if (def_bit != bit) + BitOrderInvert((unsigned char *)bitmaps, bitmapsSize); + if ((def_byte == def_bit) != (bit == byte)) { + switch (bit == byte ? def_scan : scan) { + case 1: + break; + case 2: + TwoByteSwap((unsigned char *)bitmaps, bitmapsSize); + break; + case 4: + FourByteSwap((unsigned char *)bitmaps, bitmapsSize); + break; + } + } + if (def_glyph != glyph) { + char *padbitmaps; + int sizepadbitmaps; + int sizechar; + CharInfoPtr metric; + + sizepadbitmaps = 0; + metric = bitmapFont->metrics; + for (i = 0; i < num_chars; i++) + { + if (metric->bits) + sizepadbitmaps += BYTES_FOR_GLYPH(metric,glyph); + metric++; + } + padbitmaps = malloc(sizepadbitmaps); + if (!padbitmaps) { + snfError("snfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps); + free (bitmaps); + free (fontspace); + return AllocError; + } + metric = bitmapFont->metrics; + bitmapFont->bitmaps = padbitmaps; + for (i = 0; i < num_chars; i++) { + sizechar = RepadBitmap(metric->bits, padbitmaps, + def_glyph, glyph, + metric->metrics.rightSideBearing - + metric->metrics.leftSideBearing, + metric->metrics.ascent + metric->metrics.descent); + metric->bits = padbitmaps; + padbitmaps += sizechar; + metric++; + } + free(bitmaps); + } + + /* now read and atom'ize properties */ + + ret = snfReadProps(&fi, &pFont->info, file); + if (ret != Successful) { + free(fontspace); + return ret; + } + snfCopyInfo(&fi, &pFont->info); + + /* finally, read the ink metrics if the exist */ + + if (fi.inkMetrics) { + ret = Successful; + ret = snfReadxCharInfo(file, &pFont->info.ink_minbounds); + ret = snfReadxCharInfo(file, &pFont->info.ink_maxbounds); + for (i = 0; ret == Successful && i < num_chars; i++) + ret = snfReadxCharInfo(file, &bitmapFont->ink_metrics[i]); + if (ret != Successful) { + free(fontspace); + return ret; + } + } else { + pFont->info.ink_minbounds = pFont->info.minbounds; + pFont->info.ink_maxbounds = pFont->info.maxbounds; + } + + if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) { + unsigned int r, + c, + cols; + + r = pFont->info.defaultCh >> 8; + c = pFont->info.defaultCh & 0xFF; + if (pFont->info.firstRow <= r && r <= pFont->info.lastRow && + pFont->info.firstCol <= c && c <= pFont->info.lastCol) { + cols = pFont->info.lastCol - pFont->info.firstCol + 1; + r = r - pFont->info.firstRow; + c = c - pFont->info.firstCol; + bitmapFont->pDefault = &bitmapFont->metrics[r * cols + c]; + } + } + bitmapFont->bitmapExtra = (BitmapExtraPtr) 0; + pFont->fontPrivate = (pointer) bitmapFont; + pFont->get_glyphs = bitmapGetGlyphs; + pFont->get_metrics = bitmapGetMetrics; + pFont->unload_font = snfUnloadFont; + pFont->unload_glyphs = NULL; + pFont->bit = bit; + pFont->byte = byte; + pFont->glyph = glyph; + pFont->scan = scan; + return Successful; +} + +int +snfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file) +{ + int ret; + snfFontInfoRec fi; + int bytestoskip; + int num_chars; + + ret = snfReadHeader(&fi, file); + if (ret != Successful) + return ret; + snfCopyInfo(&fi, pFontInfo); + + pFontInfo->props = malloc(fi.nProps * sizeof(FontPropRec)); + if (!pFontInfo->props) { + snfError("snfReadFontInfo(): Couldn't allocate props (%d*%d)\n", fi.nProps, sizeof(FontPropRec)); + return AllocError; + } + pFontInfo->isStringProp = malloc(fi.nProps * sizeof(char)); + if (!pFontInfo->isStringProp) { + snfError("snfReadFontInfo(): Couldn't allocate isStringProp (%d*%d)\n", fi.nProps, sizeof(char)); + free(pFontInfo->props); + return AllocError; + } + num_chars = n2dChars(&fi); + bytestoskip = num_chars * sizeof(snfCharInfoRec); /* charinfos */ + bytestoskip += BYTESOFGLYPHINFO(&fi); + (void)FontFileSkip(file, bytestoskip); + + ret = snfReadProps(&fi, pFontInfo, file); + if (ret != Successful) { + free(pFontInfo->props); + free(pFontInfo->isStringProp); + return ret; + } + if (fi.inkMetrics) { + ret = snfReadxCharInfo(file, &pFontInfo->ink_minbounds); + if (ret != Successful) { + free(pFontInfo->props); + free(pFontInfo->isStringProp); + return ret; + } + ret = snfReadxCharInfo(file, &pFontInfo->ink_maxbounds); + if (ret != Successful) { + free(pFontInfo->props); + free(pFontInfo->isStringProp); + return ret; + } + } else { + pFontInfo->ink_minbounds = pFontInfo->minbounds; + pFontInfo->ink_maxbounds = pFontInfo->maxbounds; + } + return Successful; + +} + +static void +snfUnloadFont(FontPtr pFont) +{ + BitmapFontPtr bitmapFont; + + bitmapFont = (BitmapFontPtr) pFont->fontPrivate; + free (bitmapFont->bitmaps); + free (bitmapFont); + DestroyFontRec (pFont); +} + diff --git a/src/bitmap/snfstr.h b/src/bitmap/snfstr.h new file mode 100755 index 0000000..148bb1f --- /dev/null +++ b/src/bitmap/snfstr.h @@ -0,0 +1,182 @@ +/*********************************************************** +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + +Copyright 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifndef SNFSTR_H +#define SNFSTR_H 1 + +#include + +/*- + * This file describes the Server Natural Font format. + * SNF fonts are both CPU-dependent and frame buffer bit order dependent. + * This file is used by: + * 1) the server, to hold font information read out of font files. + * 2) font converters + * + * Each font file contains the following + * data structures, with no padding in-between. + * + * 1) The XFONTINFO structure + * hand-padded to a two-short boundary. + * maxbounds.byteoffset is the total number of bytes in the + * glpyh array + * maxbounds.bitOffset is thetotal width of the unpadded font + * + * 2) The XCHARINFO array + * indexed directly with character codes, both on disk + * and in memory. + * + * 3) Character glyphs + * padded in the server-natural way, and + * ordered in the device-natural way. + * End of glyphs padded to 32-bit boundary. + * + * 4) nProps font properties + * + * 5) a sequence of null-terminated strings, for font properties + */ + +#define FONT_FILE_VERSION 4 + +typedef struct _snfFontProp { + CARD32 name; /* offset of string */ + INT32 value; /* number or offset of string */ + Bool indirect; /* value is a string offset */ +} snfFontPropRec; + +/* + * the following macro definitions describe a font file image in memory + */ +#define ADDRCharInfoRec( pfi) \ + ((snfCharInfoRec *) &(pfi)[1]) + +#define ADDRCHARGLYPHS( pfi) \ + (((char *) &(pfi)[1]) + BYTESOFCHARINFO(pfi)) + +/* + * pad out glyphs to a CARD32 boundary + */ +#define ADDRXFONTPROPS( pfi) \ + ((snfFontPropRec *) ((char *)ADDRCHARGLYPHS( pfi) + BYTESOFGLYPHINFO(pfi))) + +#define ADDRSTRINGTAB( pfi) \ + ((char *)ADDRXFONTPROPS( pfi) + BYTESOFPROPINFO(pfi)) + +#define n2dChars(pfi) (((pfi)->lastRow - (pfi)->firstRow + 1) * \ + ((pfi)->lastCol - (pfi)->firstCol + 1)) +#define BYTESOFFONTINFO(pfi) (sizeof(snfFontInfoRec)) +#define BYTESOFCHARINFO(pfi) (sizeof(snfCharInfoRec) * n2dChars(pfi)) +#define BYTESOFPROPINFO(pfi) (sizeof(snfFontPropRec) * (pfi)->nProps) +#define BYTESOFSTRINGINFO(pfi) ((pfi)->lenStrings) +#define BYTESOFGLYPHINFO(pfi) (((pfi)->maxbounds.byteOffset+3) & ~0x3) +#define BYTESOFINKINFO(pfi) (sizeof(snfCharInfoRec) * n2dChars(pfi)) + +typedef struct _snfFontProp *snfFontPropPtr; +typedef struct _snfCharInfo *snfCharInfoPtr; +typedef struct _snfFontInfo *snfFontInfoPtr; + +typedef struct _snfCharInfo { + xCharInfo metrics; /* info preformatted for Queries */ + unsigned byteOffset:24; /* byte offset of the raster from pGlyphs */ + unsigned exists:1; /* true iff glyph exists for this char */ + unsigned pad:7; /* must be zero for now */ +} snfCharInfoRec; + +typedef struct _snfFontInfo { + unsigned int version1; /* version stamp */ + unsigned int allExist; + unsigned int drawDirection; + unsigned int noOverlap; /* true if: + * max(rightSideBearing-characterWidth) <= + * minbounds->metrics.leftSideBearing */ + unsigned int constantMetrics; + unsigned int terminalFont; /* Should be deprecated! true if: constant + * metrics && leftSideBearing == 0 && + * rightSideBearing == characterWidth && + * ascent == fontAscent && descent == + * fontDescent */ + unsigned int linear:1; /* true if firstRow == lastRow */ + unsigned int constantWidth:1; /* true if + * minbounds->metrics.characterWidth + * == + * maxbounds->metrics.characterWidth */ + unsigned int inkInside:1; /* true if for all defined glyphs: + * leftSideBearing >= 0 && rightSideBearing <= + * characterWidth && -fontDescent <= ascent <= + * fontAscent && -fontAscent <= descent <= + * fontDescent */ + unsigned int inkMetrics:1; /* ink metrics != bitmap metrics */ + /* used with terminalFont */ + /* see font's pInk{CI,Min,Max} */ + unsigned int padding:28; + unsigned int firstCol; + unsigned int lastCol; + unsigned int firstRow; + unsigned int lastRow; + unsigned int nProps; + unsigned int lenStrings; /* length in bytes of string table */ + unsigned int chDefault; /* default character */ + int fontDescent; /* minimum for quality typography */ + int fontAscent; /* minimum for quality typography */ + snfCharInfoRec minbounds; /* MIN of glyph metrics over all chars */ + snfCharInfoRec maxbounds; /* MAX of glyph metrics over all chars */ + unsigned int pixDepth; /* intensity bits per pixel */ + unsigned int glyphSets; /* number of sets of glyphs, for sub-pixel + * positioning */ + unsigned int version2; /* version stamp double-check */ +} snfFontInfoRec; + +extern void SnfSetFormat ( int bit, int byte, int glyph, int scan ); +extern int snfReadFont ( FontPtr pFont, FontFilePtr file, + int bit, int byte, int glyph, int scan ); +extern int snfReadFontInfo ( FontInfoPtr pFontInfo, FontFilePtr file ); + +#endif /* SNFSTR_H */ diff --git a/src/builtins/Makefile.am b/src/builtins/Makefile.am new file mode 100644 index 0000000..b203fda --- /dev/null +++ b/src/builtins/Makefile.am @@ -0,0 +1,17 @@ +INCLUDES = \ + -I${top_srcdir}/include \ + -I${top_srcdir}/src/bitmap + +AM_CFLAGS = $(XFONT_CFLAGS) $(OS_CFLAGS) $(CWARNFLAGS) + +noinst_LTLIBRARIES = libbuiltins.la + +libbuiltins_la_SOURCES = \ + builtin.h \ + dir.c \ + file.c \ + fonts.c \ + fpe.c \ + render.c + +EXTRA_DIST = buildfont diff --git a/src/builtins/buildfont b/src/builtins/buildfont new file mode 100644 index 0000000..aa4602f --- /dev/null +++ b/src/builtins/buildfont @@ -0,0 +1,14 @@ +#!/bin/sh +# +# Convert a bdf file into C-code suitable for inclusion in +# builtin fonts +# +FONT=$1 +NAME=$2 +echo 'static const char file_'$NAME'[] = {' +bdftopcf -p1 -u1 $1 | + compress -b 12 | + od -b -v -w8 | + sed 's/^[0-9]*\( *\)/\1\1\1\1/' | + sed 's/\([0-9][0-9]*\)/'"'"'\\\1'"'"',/g' +echo '};' diff --git a/src/builtins/builtin.h b/src/builtins/builtin.h new file mode 100755 index 0000000..418bfe9 --- /dev/null +++ b/src/builtins/builtin.h @@ -0,0 +1,62 @@ +/* + * + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#include +#include +#include +#include +#include +#include + +typedef struct _BuiltinFile { + const char *name; + int len; + const char *bits; +} BuiltinFileRec, *BuiltinFilePtr; + +typedef struct _BuiltinDir { + char *file_name; + char *font_name; +} BuiltinDirRec, *BuiltinDirPtr; + +typedef struct _BuiltinAlias { + char *alias_name; + char *font_name; +} BuiltinAliasRec, *BuiltinAliasPtr; + +extern const BuiltinFileRec builtin_files[]; +extern const int builtin_files_count; + +extern const BuiltinDirRec builtin_dir[]; +extern const int builtin_dir_count; + +extern const BuiltinAliasRec builtin_alias[]; +extern const int builtin_alias_count; + +extern FontFilePtr BuiltinFileOpen (char *); +extern int BuiltinFileClose (BufFilePtr, int); +extern int BuiltinReadDirectory (char *, FontDirectoryPtr *); +extern void BuiltinRegisterFontFileFunctions (void); + +extern void BuiltinRegisterFpeFunctions (void); diff --git a/src/builtins/dir.c b/src/builtins/dir.c new file mode 100644 index 0000000..bf351b1 --- /dev/null +++ b/src/builtins/dir.c @@ -0,0 +1,208 @@ +/* + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "builtin.h" + +static BuiltinDirPtr +BuiltinDirsDup (const BuiltinDirPtr a_dirs, + int a_dirs_len) +{ + BuiltinDirPtr dirs=NULL ; + int i=0 ; + + if (!a_dirs) + return NULL ; + + dirs = calloc (a_dirs_len, sizeof (BuiltinDirRec)) ; + if (!dirs) + return NULL ; + + for (i=0; i < a_dirs_len; i++) { + dirs[i].file_name = strdup(a_dirs[i].file_name); + dirs[i].font_name = strdup(a_dirs[i].font_name); + } + return dirs ; +} + +/** + * Copy a_save back into a_cur + * @param a_cur the instance of BuiltinDir to restore + * @param a_saved the saved instance of BuiltinDir to copy into a_cur + * @return 0 if went okay, 1 otherwise. + */ +static int +BuiltinDirRestore (BuiltinDirPtr a_cur, + const BuiltinDirPtr a_saved) +{ + if (!a_cur) + return 1 ; + if (!a_saved) + return 0 ; + + if (a_saved->font_name) + memmove (a_cur->font_name, a_saved->font_name, strlen (a_saved->font_name)) ; + return 0 ; +} + + +static int +BuiltinDirsRestore (BuiltinDirPtr a_cur_tab, + const BuiltinDirPtr a_saved_tab, + int a_tab_len) +{ + int i=0 ; + + if (!a_cur_tab) + return 1 ; + if (!a_saved_tab) + return 0 ; + + for (i=0 ; i < a_tab_len; i++) { + if (BuiltinDirRestore (&a_cur_tab[i], &a_saved_tab[i])) + return 1 ; + } + return 0 ; +} + +static BuiltinAliasPtr +BuiltinAliasesDup (const BuiltinAliasPtr a_aliases, + int a_aliases_len) +{ + BuiltinAliasPtr aliases=NULL ; + int i=0 ; + + if (!a_aliases) + return NULL ; + + aliases = calloc (a_aliases_len, sizeof (BuiltinAliasRec)) ; + if (!aliases) + return NULL ; + + for (i=0; i < a_aliases_len; i++) { + aliases[i].font_name = strdup(a_aliases[i].font_name); + } + return aliases ; +} + +/** + * Copy a_save back into a_cur + * @param a_cur the instance of BuiltinAlias to restore + * @param a_saved the saved instance of BuiltinAlias to copy into a_cur + * @return 0 if went okay, 1 otherwise. + */ +static int +BuiltinAliasRestore (BuiltinAliasPtr a_cur, + const BuiltinAliasPtr a_save) +{ + if (!a_cur) + return 1 ; + if (!a_save) + return 0 ; + if (a_save->alias_name) + memmove (a_cur->alias_name, a_save->alias_name, strlen (a_save->alias_name)) ; + if (a_save->font_name) + memmove (a_cur->font_name, a_save->font_name, strlen (a_save->font_name)) ; + return 0 ; +} + +static int +BuiltinAliasesRestore (BuiltinAliasPtr a_cur_tab, + const BuiltinAliasPtr a_saved_tab, + int a_tab_len) +{ + int i=0 ; + + if (!a_cur_tab) + return 1 ; + if (!a_saved_tab) + return 0 ; + + for (i=0 ; i < a_tab_len; i++) { + if (BuiltinAliasRestore (&a_cur_tab[i], &a_saved_tab[i])) + return 1 ; + } + return 0 ; +} + +int +BuiltinReadDirectory (char *directory, FontDirectoryPtr *pdir) +{ + FontDirectoryPtr dir; + int i; + + static BuiltinDirPtr saved_builtin_dir; + static BuiltinAliasPtr saved_builtin_alias; + + dir = FontFileMakeDir ("", builtin_dir_count); + + if (saved_builtin_dir) + { + BuiltinDirsRestore ((BuiltinDirPtr) builtin_dir, + saved_builtin_dir, + builtin_dir_count) ; + } + else + { + saved_builtin_dir = BuiltinDirsDup ((const BuiltinDirPtr) builtin_dir, + builtin_dir_count) ; + } + + if (saved_builtin_alias) + { + BuiltinAliasesRestore ((BuiltinAliasPtr) builtin_alias, + saved_builtin_alias, + builtin_alias_count) ; + } + else + { + saved_builtin_alias = BuiltinAliasesDup ((const BuiltinAliasPtr) builtin_alias, + builtin_alias_count) ; + } + + for (i = 0; i < builtin_dir_count; i++) + { + if (!FontFileAddFontFile (dir, + (char *) builtin_dir[i].font_name, + (char *) builtin_dir[i].file_name)) + { + FontFileFreeDir (dir); + return BadFontPath; + } + } + for (i = 0; i < builtin_alias_count; i++) + { + if (!FontFileAddFontAlias (dir, + (char *) builtin_alias[i].alias_name, + (char *) builtin_alias[i].font_name)) + { + FontFileFreeDir (dir); + return BadFontPath; + } + } + FontFileSortDir (dir); + *pdir = dir; + return Successful; +} diff --git a/src/builtins/file.c b/src/builtins/file.c new file mode 100755 index 0000000..5492539 --- /dev/null +++ b/src/builtins/file.c @@ -0,0 +1,130 @@ +/* + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include "builtin.h" + +typedef struct _BuiltinIO { + int offset; + BuiltinFilePtr file; +} BuiltinIORec, *BuiltinIOPtr; + +static int +BuiltinFill (BufFilePtr f) +{ + int left, len; + BuiltinIOPtr io = ((BuiltinIOPtr) f->private); + + left = io->file->len - io->offset; + if (left <= 0) + { + f->left = 0; + return BUFFILEEOF; + } + len = BUFFILESIZE; + if (len > left) + len = left; + memcpy (f->buffer, io->file->bits + io->offset, len); + io->offset += len; + f->left = len - 1; + f->bufp = f->buffer + 1; + return f->buffer[0]; +} + +static int +BuiltinSkip (BufFilePtr f, int count) +{ + BuiltinIOPtr io = ((BuiltinIOPtr) f->private); + int curoff; + int fileoff; + int todo; + + curoff = f->bufp - f->buffer; + fileoff = curoff + f->left; + if (curoff + count <= fileoff) { + f->bufp += count; + f->left -= count; + } else { + todo = count - (fileoff - curoff); + io->offset += todo; + if (io->offset > io->file->len) + io->offset = io->file->len; + if (io->offset < 0) + io->offset = 0; + f->left = 0; + } + return count; +} + +static int +BuiltinClose (BufFilePtr f, int unused) +{ + BuiltinIOPtr io = ((BuiltinIOPtr) f->private); + + free (io); + return 1; +} + + +FontFilePtr +BuiltinFileOpen (char *name) +{ + int i; + BuiltinIOPtr io; + BufFilePtr raw, cooked; + + if (*name == '/') name++; + for (i = 0; i < builtin_files_count; i++) + if (!strcmp (name, builtin_files[i].name)) + break; + if (i == builtin_files_count) + return NULL; + io = malloc (sizeof (BuiltinIORec)); + if (!io) + return NULL; + io->offset = 0; + io->file = (void *) &builtin_files[i]; + raw = BufFileCreate ((char *) io, BuiltinFill, 0, BuiltinSkip, BuiltinClose); + if (!raw) + { + free (io); + return NULL; + } + if ((cooked = BufFilePushZIP (raw))) + raw = cooked; + else + { + raw->left += raw->bufp - raw->buffer; + raw->bufp = raw->buffer; + } + return (FontFilePtr) raw; +} + +int +BuiltinFileClose (FontFilePtr f, int unused) +{ + return BufFileClose ((BufFilePtr) f, TRUE); +} diff --git a/src/builtins/fonts.c b/src/builtins/fonts.c new file mode 100755 index 0000000..9a9d7d2 --- /dev/null +++ b/src/builtins/fonts.c @@ -0,0 +1,1252 @@ +/* + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "builtin.h" + +static const char file_cursor[] = { + '\037', '\213', '\010', '\010', '\143', '\117', '\054', '\100', + '\000', '\003', '\143', '\165', '\162', '\163', '\157', '\162', + '\056', '\160', '\143', '\146', '\000', '\355', '\233', '\177', + '\160', '\124', '\327', '\165', '\307', '\317', '\112', '\102', + '\022', '\130', '\040', '\021', '\300', '\226', '\023', '\031', + '\311', '\100', '\034', '\114', '\354', '\104', '\004', '\033', + '\013', '\233', '\040', '\141', '\040', '\006', '\327', '\001', + '\154', '\213', '\000', '\216', '\143', '\151', '\221', '\026', + '\244', '\146', '\365', '\203', '\325', '\352', '\027', '\010', + '\264', '\253', '\137', '\273', '\010', '\320', '\217', '\332', + '\155', '\035', '\217', '\123', '\323', '\044', '\323', '\361', + '\340', '\114', '\207', '\231', '\144', '\062', '\324', '\303', + '\324', '\212', '\235', '\232', '\046', '\045', '\305', '\323', + '\072', '\143', '\322', '\060', '\365', '\062', '\166', '\143', + '\246', '\166', '\221', '\360', '\057', '\224', '\262', '\150', + '\373', '\075', '\357', '\234', '\273', '\357', '\355', '\112', + '\313', '\217', '\244', '\371', '\057', '\232', '\371', '\274', + '\167', '\357', '\271', '\347', '\336', '\167', '\177', '\236', + '\173', '\356', '\173', '\053', '\327', '\316', '\252', '\306', + '\154', '\042', '\162', '\201', '\064', '\360', '\056', '\010', + '\153', '\230', '\251', '\006', '\136', '\044', '\146', '\160', + '\034', '\367', '\354', '\164', '\242', '\067', '\370', '\256', + '\351', '\147', '\027', '\021', '\235', '\101', '\142', '\221', + '\306', '\327', '\042', '\355', '\307', '\167', '\022', '\225', + '\151', '\274', '\021', '\227', '\361', '\045', '\104', '\001', + '\215', '\237', '\237', '\116', '\124', '\163', '\267', '\074', + '\320', '\224', '\277', '\371', '\076', '\011', '\043', '\311', + '\372', '\163', '\315', '\300', '\145', '\011', '\207', '\226', + '\103', '\353', '\136', '\226', '\334', '\217', '\313', '\152', + '\226', '\160', '\322', '\172', '\016', '\174', '\033', '\074', + '\316', '\201', '\215', '\240', '\322', '\004', '\352', '\070', + '\020', '\303', '\137', '\013', '\007', '\146', '\112', '\171', + '\101', '\260', '\146', '\323', '\346', '\355', '\217', '\155', + '\170', '\150', '\175', '\071', '\225', '\327', '\170', '\232', + '\074', '\105', '\013', '\166', '\171', '\333', '\033', '\153', + '\232', '\026', '\024', '\271', '\175', '\236', '\242', '\346', + '\172', '\117', '\175', '\125', '\163', '\335', '\016', '\217', + '\317', '\123', '\115', '\233', '\067', '\155', '\330', '\130', + '\136', '\361', '\370', '\206', '\047', '\326', '\321', '\327', + '\066', '\155', '\054', '\247', '\252', '\146', '\137', '\123', + '\203', '\217', '\266', '\256', '\263', '\162', '\077', '\266', + '\356', '\361', '\115', '\217', '\154', '\051', '\337', '\260', + '\151', '\243', '\043', '\130', '\261', '\315', '\031', '\331', + '\116', '\333', '\052', '\326', '\213', '\366', '\243', '\133', + '\126', '\257', '\255', '\330', '\272', '\141', '\155', '\271', + '\125', '\345', '\064', '\262', '\377', '\362', '\300', '\154', + '\255', '\353', '\305', '\030', '\267', '\053', '\026', '\263', + '\332', '\216', '\224', '\331', '\224', '\153', '\245', '\377', + '\076', '\177', '\074', '\106', '\317', '\321', '\236', '\360', + '\160', '\137', '\270', '\375', '\300', '\160', '\350', '\100', + '\123', '\160', '\070', '\060', '\340', '\353', '\032', '\016', + '\016', '\356', '\353', '\035', '\076', '\020', '\354', '\350', + '\033', '\356', '\357', '\262', '\103', '\110', '\350', '\356', + '\305', '\245', '\247', '\167', '\117', '\210', '\163', '\204', + '\221', '\043', '\060', '\060', '\174', '\070', '\330', '\071', + '\070', '\074', '\320', '\205', '\274', '\207', '\203', '\110', + '\035', '\350', '\102', '\352', '\341', '\040', '\122', '\007', + '\272', '\332', '\103', '\310', '\333', '\026', '\106', '\336', + '\266', '\320', '\160', '\070', '\214', '\120', '\070', '\214', + '\242', '\002', '\003', '\173', '\103', '\170', '\006', '\122', + '\103', '\041', '\113', '\206', '\032', '\164', '\037', '\336', + '\163', '\000', '\027', '\144', '\073', '\020', '\102', '\135', + '\254', '\113', '\110', '\152', '\025', '\017', '\205', '\035', + '\262', '\260', '\011', '\355', '\355', '\035', '\356', '\355', + '\335', '\323', '\067', '\334', '\327', '\207', '\113', '\157', + '\250', '\235', '\253', '\006', '\131', '\050', '\204', '\150', + '\070', '\354', '\103', '\213', '\006', '\371', '\062', '\024', + '\017', '\015', '\332', '\172', '\166', '\313', '\355', '\272', + '\240', '\011', '\135', '\207', '\271', '\251', '\207', '\367', + '\017', '\040', '\233', '\165', '\361', '\007', '\315', '\045', + '\060', '\210', '\332', '\007', '\206', '\120', '\173', '\124', + '\067', '\334', '\147', '\135', '\254', '\154', '\326', '\305', + '\052', '\264', '\315', '\352', '\227', '\060', '\364', '\072', + '\017', '\100', '\017', '\075', '\324', '\027', '\102', '\017', + '\205', '\302', '\201', '\176', '\074', '\243', '\363', '\240', + '\121', '\266', '\272', '\004', '\262', '\003', '\101', '\310', + '\372', '\273', '\132', '\203', '\010', '\265', '\164', '\111', + '\077', '\367', '\036', '\264', '\056', '\266', '\136', '\307', + '\301', '\341', '\340', '\341', '\216', '\103', '\050', '\257', + '\045', '\070', '\074', '\030', '\154', '\356', '\302', '\005', + '\175', '\160', '\250', '\007', '\265', '\077', '\324', '\203', + '\076', '\355', '\355', '\105', '\237', '\366', '\365', '\165', + '\240', '\345', '\341', '\275', '\334', '\362', '\166', '\036', + '\313', '\066', '\036', '\113', '\214', '\114', '\137', '\010', + '\345', '\205', '\302', '\170', '\106', '\050', '\204', '\147', + '\070', '\153', '\140', '\367', '\001', '\372', '\245', '\163', + '\000', '\011', '\201', '\241', '\175', '\075', '\303', '\203', + '\001', '\024', '\145', '\075', '\243', '\273', '\007', '\227', + '\236', '\336', '\340', '\020', '\102', '\150', '\171', '\117', + '\357', '\356', '\000', '\102', '\273', '\203', '\010', '\101', + '\257', '\163', '\010', '\172', '\126', '\216', '\120', '\330', + '\172', '\170', '\013', '\107', '\233', '\371', '\342', '\030', + '\337', '\176', '\056', '\236', '\057', '\255', '\350', '\335', + '\201', '\026', '\276', '\130', '\323', '\307', '\214', '\145', + '\237', '\065', '\334', '\241', '\075', '\241', '\041', '\204', + '\302', '\103', '\350', '\253', '\001', '\356', '\277', '\101', + '\351', '\077', '\015', '\331', '\263', '\023', '\063', '\054', + '\300', '\005', '\130', '\163', '\050', '\320', '\217', '\147', + '\004', '\017', '\242', '\006', '\001', '\251', '\013', '\372', + '\064', '\320', '\217', '\076', '\015', '\036', '\104', '\152', + '\327', '\041', '\244', '\166', '\015', '\240', '\345', '\201', + '\176', '\074', '\067', '\170', '\020', '\025', '\077', '\020', + '\262', '\056', '\373', '\172', '\372', '\103', '\241', '\216', + '\336', '\376', '\160', '\230', '\327', '\332', '\163', '\272', + '\046', '\112', '\100', '\033', '\070', '\006', '\306', '\100', + '\076', '\326', '\310', '\172', '\320', '\010', '\216', '\200', + '\021', '\360', '\056', '\050', '\100', '\246', '\047', '\301', + '\063', '\340', '\115', '\220', '\003', '\133', '\367', '\010', + '\350', '\001', '\077', '\003', '\037', '\200', '\002', '\330', + '\272', '\047', '\301', '\363', '\340', '\115', '\060', '\167', + '\032', '\164', '\300', '\041', '\160', '\012', '\344', '\144', + '\042', '\016', '\016', '\201', '\177', '\006', '\331', '\131', + '\260', '\211', '\040', '\000', '\116', '\200', '\050', '\050', + '\201', '\361', '\154', '\003', '\107', '\300', '\033', '\331', + '\142', '\370', '\112', '\100', '\043', '\070', '\006', '\076', + '\000', '\167', '\301', '\320', '\325', '\200', '\037', '\200', + '\067', '\101', '\316', '\115', '\050', '\007', '\364', '\200', + '\023', '\040', '\012', '\112', '\162', '\120', '\016', '\070', + '\016', '\306', '\101', '\011', '\354', '\135', '\033', '\070', + '\006', '\306', '\300', '\342', '\131', '\260', '\214', '\340', + '\010', '\210', '\200', '\374', '\134', '\242', '\155', '\140', + '\010', '\274', '\001', '\062', '\140', '\144', '\312', '\100', + '\033', '\070', '\016', '\306', '\101', '\011', '\214', '\122', + '\045', '\030', '\002', '\307', '\301', '\171', '\260', '\370', + '\063', '\250', '\013', '\170', '\021', '\234', '\007', '\105', + '\163', '\240', '\003', '\216', '\200', '\010', '\050', '\232', + '\213', '\070', '\010', '\203', '\343', '\340', '\143', '\160', + '\317', '\074', '\354', '\033', '\340', '\207', '\040', '\002', + '\012', '\156', '\046', '\052', '\007', '\317', '\200', '\067', + '\301', '\334', '\133', '\320', '\117', '\340', '\020', '\030', + '\271', '\205', '\007', '\205', '\150', '\045', '\350', '\000', + '\317', '\202', '\023', '\340', '\014', '\210', '\202', '\374', + '\133', '\221', '\006', '\332', '\300', '\161', '\360', '\061', + '\050', '\376', '\054', '\372', '\013', '\034', '\003', '\347', + '\301', '\342', '\317', '\241', '\216', '\340', '\105', '\160', + '\036', '\054', '\056', '\100', '\034', '\274', '\010', '\316', + '\202', '\271', '\267', '\141', '\314', '\101', '\017', '\070', + '\001', '\242', '\340', '\236', '\371', '\104', '\176', '\360', + '\103', '\360', '\001', '\130', '\124', '\210', '\375', '\010', + '\034', '\002', '\047', '\100', '\024', '\254', '\304', '\306', + '\126', '\015', '\236', '\001', '\247', '\100', '\316', '\355', + '\310', '\007', '\252', '\301', '\017', '\300', '\273', '\240', + '\140', '\001', '\321', '\217', '\320', '\167', '\137', '\102', + '\137', '\075', '\211', '\360', '\361', '\265', '\104', '\131', + '\230', '\164', '\271', '\053', '\211', '\012', '\127', '\021', + '\255', '\342', '\262', '\320', '\337', '\343', '\030', '\373', + '\261', '\164', '\201', '\303', '\054', '\343', '\064', '\326', + '\141', '\135', '\053', '\017', '\046', '\150', '\341', '\070', + '\121', '\151', '\224', '\250', '\163', '\202', '\150', '\242', + '\023', '\172', '\245', '\320', '\207', '\336', '\130', '\256', + '\300', '\141', '\226', '\161', '\032', '\353', '\260', '\056', + '\347', '\341', '\274', '\124', '\014', '\120', '\026', '\101', + '\147', '\104', '\363', '\360', '\163', '\106', '\360', '\274', + '\010', '\150', '\304', '\263', '\113', '\170', '\036', '\143', + '\276', '\317', '\002', '\131', '\146', '\137', '\212', '\000', + '\224', '\101', '\050', '\057', '\200', '\162', '\043', '\140', + '\274', '\124', '\236', '\303', '\375', '\020', '\321', '\262', + '\306', '\101', '\007', '\062', '\255', '\002', '\205', '\310', + '\210', '\151', '\145', '\371', '\006', '\061', '\135', '\153', + '\061', '\031', '\312', '\004', '\236', '\320', '\052', '\161', + '\070', '\226', '\076', '\231', '\066', '\135', '\237', '\023', + '\056', '\233', '\250', '\312', '\362', '\065', '\357', '\023', + '\123', '\224', '\353', '\174', '\146', '\361', '\024', '\145', + '\230', '\162', '\247', '\172', '\146', '\200', '\233', '\214', + '\373', '\354', '\114', '\222', '\235', '\067', '\137', '\033', + '\222', '\046', '\351', '\334', '\035', '\074', '\116', '\277', + '\313', '\222', '\364', '\070', '\350', '\207', '\130', '\226', + '\350', '\074', '\204', '\171', '\265', '\066', '\303', '\206', + '\323', '\326', '\315', '\115', '\204', '\145', '\116', '\035', + '\316', '\363', '\366', '\076', '\233', '\263', '\230', '\207', + '\261', '\116', '\033', '\043', '\167', '\312', '\130', '\307', + '\231', '\007', '\217', '\266', '\130', '\010', '\333', '\261', + '\020', '\145', '\056', '\104', '\235', '\027', '\242', '\275', + '\337', '\207', '\254', '\012', '\274', '\223', '\153', '\353', + '\060', '\261', '\122', '\001', '\142', '\213', '\121', '\164', + '\326', '\050', '\346', '\332', '\050', '\352', '\062', '\212', + '\001', '\034', '\105', '\173', '\106', '\241', '\070', '\132', + '\152', '\303', '\172', '\011', '\355', '\066', '\235', '\014', + '\062', '\226', '\302', '\256', '\201', '\074', '\120', '\004', + '\312', '\100', '\000', '\104', '\227', '\332', '\072', '\214', + '\171', '\256', '\145', '\164', '\101', '\316', '\045', '\314', + '\073', '\120', '\002', '\032', '\101', '\004', '\214', '\200', + '\250', '\003', '\326', '\113', '\176', '\156', '\031', '\115', + '\015', '\367', '\347', '\172', '\264', '\175', '\263', '\113', + '\306', '\253', '\314', '\314', '\207', '\102', '\141', '\304', + '\065', '\065', '\247', '\156', '\225', '\076', '\345', '\271', + '\074', '\226', '\045', '\363', '\200', '\345', '\316', '\076', + '\147', '\106', '\350', '\352', '\230', '\366', '\215', '\244', + '\137', '\235', '\344', '\366', '\160', '\331', '\354', '\157', + '\137', '\301', '\175', '\032', '\052', '\375', '\111', '\005', + '\321', '\274', '\315', '\104', '\277', '\332', '\112', '\264', + '\245', '\034', '\154', '\101', '\030', '\314', '\103', '\370', + '\023', '\310', '\246', '\041', '\355', '\012', '\164', '\134', + '\145', '\132', '\267', '\344', '\362', '\156', '\020', '\063', + '\104', '\146', '\175', '\104', '\025', '\263', '\156', '\226', + '\241', '\316', '\113', '\323', '\022', '\206', '\322', '\102', + '\207', '\221', '\306', '\135', '\102', '\064', '\135', '\230', + '\310', '\022', '\142', '\271', '\066', '\227', '\146', '\331', + '\372', '\206', '\210', '\313', '\266', '\173', '\363', '\141', + '\157', '\147', '\025', '\210', '\315', '\163', '\302', '\062', + '\116', '\063', '\366', '\222', '\363', '\260', '\335', '\162', + '\332', '\074', '\306', '\330', '\074', '\047', '\054', '\063', + '\351', '\306', '\146', '\106', '\364', '\171', '\277', '\305', + '\230', '\317', '\131', '\106', '\364', '\163', '\234', '\127', + '\332', '\301', '\154', '\330', '\351', '\167', '\060', '\137', + '\047', '\240', '\363', '\213', '\271', '\066', '\377', '\215', + '\275', '\352', '\137', '\356', '\021', '\173', '\154', '\306', + '\227', '\165', '\056', '\255', '\040', '\372', '\115', '\053', + '\321', '\377', '\340', '\204', '\161', '\245', '\001', '\166', + '\141', '\047', '\321', '\107', '\115', '\222', '\376', '\376', + '\275', '\066', '\227', '\161', '\226', '\171', '\277', '\231', + '\350', '\164', '\207', '\075', '\217', '\306', '\165', '\257', + '\315', '\254', '\204', '\237', '\277', '\215', '\350', '\303', + '\207', '\260', '\056', '\313', '\204', '\064', '\345', '\071', + '\310', '\277', '\201', '\061', '\177', '\013', '\174', '\163', + '\273', '\055', '\267', '\332', '\221', '\053', '\066', '\170', + '\042', '\046', '\044', '\217', '\347', '\325', '\344', '\234', + '\277', '\314', '\065', '\065', '\235', '\152', '\100', '\371', + '\236', '\112', '\207', '\327', '\106', '\062', '\123', '\315', + '\251', '\251', '\364', '\230', '\007', '\261', '\077', '\256', + '\173', '\224', '\350', '\141', '\234', '\011', '\313', '\321', + '\267', '\065', '\360', '\133', '\066', '\303', '\117', '\172', + '\145', '\102', '\312', '\347', '\073', '\307', '\131', '\316', + '\351', '\254', '\307', '\372', '\234', '\157', '\047', '\306', + '\253', '\356', '\067', '\104', '\173', '\321', '\337', '\055', + '\350', '\127', '\057', '\366', '\365', '\212', '\053', '\030', + '\347', '\011', '\261', '\337', '\174', '\347', '\070', '\313', + '\071', '\235', '\365', '\130', '\237', '\363', '\161', '\172', + '\052', '\270', '\275', '\127', '\113', '\117', '\145', '\067', + '\234', '\355', '\115', '\245', '\063', '\242', '\375', '\126', + '\231', '\056', '\355', '\132', '\017', '\137', '\156', '\355', + '\154', '\151', '\117', '\147', '\247', '\366', '\167', '\247', + '\304', '\131', '\316', '\351', '\254', '\307', '\372', '\246', + '\277', '\331', '\046', '\361', '\230', '\263', '\215', '\372', + '\127', '\314', '\273', '\223', '\273', '\345', '\231', '\235', + '\372', '\154', '\216', '\263', '\174', '\052', '\033', '\346', + '\334', '\003', '\223', '\367', '\074', '\347', '\276', '\310', + '\353', '\167', '\252', '\165', '\353', '\304', '\244', '\263', + '\056', '\307', '\135', '\331', '\211', '\270', '\225', '\144', + '\271', '\225', '\277', '\324', '\306', '\254', '\355', '\367', + '\126', '\044', '\142', '\344', '\116', '\135', '\143', '\227', + '\330', '\036', '\375', '\104', '\155', '\121', '\262', '\035', + '\142', '\331', '\117', '\034', '\076', '\202', '\261', '\115', + '\306', '\046', '\045', '\267', '\311', '\330', '\237', '\344', + '\266', '\261', '\056', '\347', '\341', '\064', '\153', '\363', + '\110', '\341', '\073', '\261', '\357', '\136', '\006', '\212', + '\240', '\237', '\007', '\262', '\371', '\175', '\210', '\276', + '\277', '\140', '\073', '\156', '\275', '\176', '\340', '\212', + '\354', '\207', '\156', '\251', '\370', '\112', '\154', '\173', + '\046', '\162', '\005', '\266', '\101', '\074', '\106', '\307', + '\221', '\367', '\171', '\060', '\200', '\114', '\041', '\227', + '\354', '\315', '\256', '\024', '\317', '\266', '\034', '\053', + '\370', '\360', '\001', '\354', '\161', '\145', '\372', '\176', + '\205', '\337', '\011', '\360', '\161', '\101', '\335', '\224', + '\304', '\147', '\257', '\262', '\237', '\315', '\004', '\330', + '\347', '\343', '\147', '\147', '\312', '\073', '\030', '\076', + '\003', '\025', '\150', '\261', '\354', '\363', '\245', '\153', + '\177', '\014', '\243', '\300', '\357', '\140', '\016', '\316', + '\304', '\372', '\313', '\232', '\145', '\217', '\051', '\207', + '\131', '\306', '\151', '\303', '\111', '\143', '\372', '\321', + '\062', '\261', '\163', '\245', '\010', '\277', '\215', '\347', + '\216', '\176', '\125', '\340', '\060', '\313', '\070', '\215', + '\165', '\214', '\376', '\105', '\074', '\354', '\062', '\373', + '\213', '\070', '\243', '\114', '\107', '\131', '\267', '\362', + '\332', '\045', '\307', '\037', '\107', '\356', '\100', '\273', + '\140', '\227', '\163', '\120', '\306', '\070', '\362', '\217', + '\055', '\204', '\175', '\106', '\236', '\113', '\271', '\272', + '\237', '\103', '\247', '\224', '\347', '\112', '\261', '\370', + '\173', '\226', '\351', '\322', '\100', '\016', '\354', '\100', + '\001', '\046', '\103', '\024', '\341', '\161', '\060', '\066', + '\212', '\166', '\237', '\224', '\075', '\232', '\367', '\017', + '\366', '\343', '\070', '\374', '\063', '\074', '\373', '\365', + '\174', '\273', '\136', '\034', '\146', '\031', '\247', '\261', + '\016', '\353', '\162', '\330', '\332', '\267', '\325', '\137', + '\346', '\071', '\160', '\036', '\347', '\223', '\263', '\017', + '\114', '\266', '\171', '\054', '\343', '\264', '\061', '\035', + '\143', '\263', '\337', '\323', '\174', '\351', '\150', '\327', + '\051', '\354', '\023', '\063', '\245', '\357', '\072', '\321', + '\366', '\122', '\220', '\311', '\203', '\240', '\173', '\133', + '\036', '\045', '\322', '\146', '\372', '\002', '\244', '\073', + '\237', '\125', '\072', '\031', '\336', '\223', '\170', '\355', + '\363', '\270', '\226', '\220', '\275', '\207', '\063', '\074', + '\077', '\347', '\140', '\314', '\267', '\302', '\256', '\314', + '\301', '\144', '\371', '\167', '\334', '\013', '\127', '\112', + '\037', '\345', '\275', '\053', '\014', '\175', '\014', '\370', + '\216', '\364', '\060', '\372', '\240', '\007', '\025', '\350', + '\050', '\224', '\374', '\227', '\221', '\377', '\022', '\333', + '\014', '\356', '\177', '\246', '\324', '\366', '\073', '\330', + '\107', '\033', '\143', '\142', '\172', '\177', '\317', '\336', + '\237', '\070', '\277', '\345', '\107', '\317', '\227', '\065', + '\063', '\222', '\156', '\367', '\077', '\267', '\367', '\177', + '\265', '\314', '\053', '\346', '\034', '\204', '\064', '\230', + '\173', '\302', '\120', '\023', '\216', '\204', '\224', '\103', + '\072', '\111', '\013', '\165', '\356', '\146', '\331', '\171', + '\047', '\222', '\355', '\223', '\372', '\340', '\061', '\336', + '\307', '\264', '\333', '\346', '\253', '\355', '\163', '\241', + '\355', '\373', '\321', '\256', '\154', '\264', '\213', '\137', + '\156', '\132', '\167', '\354', '\355', '\331', '\330', '\363', + '\213', '\127', '\243', '\154', '\054', '\246', '\062', '\234', + '\143', '\003', '\274', '\230', '\246', '\311', '\142', '\212', + '\333', '\113', '\265', '\035', '\023', '\272', '\206', '\271', + '\135', '\326', '\071', '\250', '\123', '\347', '\026', '\356', + '\221', '\122', '\131', '\243', '\274', '\306', '\314', '\001', + '\212', '\333', '\376', '\072', '\374', '\211', '\356', '\112', + '\361', '\323', '\234', '\244', '\103', '\226', '\211', '\171', + '\233', '\303', '\147', '\131', '\064', '\262', '\070', '\123', + '\354', '\075', '\333', '\153', '\316', '\067', '\121', '\052', + '\066', '\235', '\363', '\246', '\053', '\153', '\334', '\260', + '\021', '\215', '\230', '\106', '\030', '\334', '\002', '\364', + '\111', '\311', '\254', '\044', '\137', '\025', '\165', '\171', + '\351', '\050', '\174', '\305', '\137', '\311', '\175', '\332', + '\033', '\104', '\067', '\035', '\111', '\175', '\067', '\172', + '\174', '\377', '\103', '\375', '\107', '\313', '\267', '\050', + '\024', '\333', '\370', '\273', '\057', '\310', '\132', '\147', + '\173', '\176', '\332', '\341', '\063', '\161', '\230', '\145', + '\234', '\306', '\072', '\121', '\355', '\123', '\247', '\017', + '\167', '\335', '\317', '\352', '\264', '\175', '\072', '\227', + '\332', '\256', '\054', '\131', '\106', '\074', '\125', '\254', + '\261', '\357', '\124', '\163', '\300', '\161', '\270', '\003', + '\144', '\216', '\042', '\225', '\312', '\325', '\362', '\304', + '\034', '\173', '\045', '\313', '\370', '\030', '\362', '\221', + '\332', '\016', '\143', '\023', '\314', '\131', '\252', '\033', + '\254', '\321', '\071', '\073', '\207', '\327', '\112', '\251', + '\334', '\027', '\252', '\274', '\333', '\241', '\153', '\316', + '\133', '\271', '\210', '\014', '\202', '\323', '\050', '\153', + '\224', '\022', '\333', '\306', '\161', '\226', '\163', '\072', + '\353', '\231', '\074', '\351', '\051', '\060', '\365', '\114', + '\225', '\236', '\233', '\202', '\344', '\275', '\075', '\225', + '\236', '\013', '\215', '\235', '\170', '\105', '\130', '\360', + '\075', '\242', '\357', '\035', '\115', '\204', '\145', '\046', + '\075', '\031', '\053', '\257', '\261', '\025', '\277', '\007', + '\234', '\067', '\125', '\273', '\222', '\333', '\237', '\252', + '\376', '\251', '\332', '\173', '\255', '\202', '\115', '\271', + '\327', '\052', '\070', '\271', '\134', '\313', '\347', '\312', + '\025', '\337', '\215', '\277', '\063', '\274', '\172', '\216', + '\150', '\321', '\277', '\141', '\257', '\347', '\367', '\156', + '\260', '\013', '\105', '\151', '\222', '\306', '\167', '\266', + '\265', '\354', '\357', '\055', '\236', '\001', '\133', '\305', + '\357', '\206', '\242', '\366', '\171', '\210', '\355', '\314', + '\153', '\260', '\115', '\357', '\275', '\243', '\176', '\373', + '\333', '\142', '\127', '\043', '\131', '\211', '\076', '\041', + '\353', '\355', '\057', '\025', '\337', '\227', '\111', '\036', + '\257', '\045', '\107', '\023', '\371', '\143', '\217', '\127', + '\304', '\261', '\316', '\170', '\235', '\360', '\032', '\167', + '\025', '\021', '\375', '\322', '\153', '\343', '\252', '\024', + '\062', '\141', '\313', '\362', '\063', '\165', '\117', '\120', + '\077', '\324', '\072', '\027', '\152', '\076', '\313', '\166', + '\244', '\260', '\001', '\321', '\121', '\373', '\375', '\031', + '\347', '\147', '\077', '\146', '\266', '\256', '\363', '\307', + '\300', '\123', '\240', '\207', '\344', '\333', '\025', '\357', + '\177', '\171', '\240', '\330', '\364', '\177', '\206', '\354', + '\107', '\226', '\001', '\300', '\363', '\331', '\201', '\162', + '\256', '\177', '\164', '\043', '\105', '\135', '\302', '\170', + '\272', '\356', '\115', '\272', '\377', '\107', '\162', '\325', + '\326', '\027', '\252', '\341', '\340', '\115', '\246', '\040', + '\161', '\137', '\073', '\225', '\043', '\070', '\353', '\167', + '\016', '\376', '\375', '\071', '\330', '\360', '\127', '\261', + '\257', '\026', '\314', '\322', '\263', '\057', '\316', '\175', + '\271', '\035', '\322', '\077', '\316', '\167', '\200', '\334', + '\166', '\143', '\117', '\131', '\166', '\021', '\106', '\344', + '\042', '\346', '\301', '\107', '\060', '\102', '\243', '\053', + '\344', '\074', '\314', '\371', '\047', '\116', '\112', '\137', + '\160', '\031', '\311', '\076', '\261', '\231', '\277', '\251', + '\316', '\354', '\123', '\371', '\300', '\116', '\337', '\330', + '\320', '\241', '\375', '\161', '\022', '\317', '\353', '\126', + '\077', '\365', '\165', '\175', '\277', '\302', '\343', '\305', + '\276', '\306', '\142', '\345', '\002', '\360', '\252', '\214', + '\375', '\227', '\161', '\355', '\307', '\011', '\335', '\107', + '\007', '\301', '\013', '\340', '\077', '\035', '\276', '\366', + '\170', '\222', '\136', '\124', '\145', '\330', '\352', '\344', + '\354', '\245', '\363', '\141', '\314', '\350', '\151', '\175', + '\142', '\032', '\077', '\003', '\016', '\221', '\370', '\012', + '\231', '\012', '\257', '\337', '\200', '\372', '\136', '\021', + '\035', '\077', '\036', '\107', '\353', '\054', '\340', '\130', + '\333', '\054', '\073', '\001', '\126', '\246', '\313', '\060', + '\316', '\327', '\162', '\114', '\147', '\225', '\201', '\100', + '\261', '\116', '\252', '\257', '\040', '\317', '\175', '\162', + '\347', '\170', '\100', '\323', '\223', '\073', '\166', '\204', + '\271', '\210', '\164', '\336', '\060', '\056', '\045', '\316', + '\131', '\216', '\263', '\234', '\323', '\107', '\234', '\235', + '\174', '\055', '\033', '\164', '\203', '\306', '\175', '\222', + '\255', '\113', '\101', '\262', '\255', '\070', '\232', '\304', + '\037', '\333', '\126', '\360', '\372', '\166', '\055', '\260', + '\211', '\055', '\224', '\367', '\060', '\116', '\056', '\102', + '\147', '\166', '\221', '\115', '\262', '\115', '\310', '\302', + '\244', '\213', '\215', '\332', '\264', '\136', '\020', '\056', + '\305', '\154', '\132', '\043', '\211', '\171', '\002', '\072', + '\267', '\370', '\133', '\017', '\163', '\214', '\111', '\227', + '\363', '\030', '\163', '\102', '\277', '\315', '\374', '\043', + '\203', '\176', '\052', '\064', '\007', '\044', '\375', '\156', + '\063', '\142', '\316', '\122', '\271', '\372', '\036', '\134', + '\141', '\277', '\060', '\376', '\216', '\074', '\246', '\357', + '\140', '\012', '\345', '\154', '\011', '\167', '\363', '\272', + '\141', '\073', '\264', '\112', '\314', '\212', '\165', '\276', + '\353', '\270', '\116', '\054', '\277', '\305', '\045', '\353', + '\243', '\303', '\261', '\016', '\331', '\337', '\145', '\137', + '\223', '\373', '\074', '\267', '\115', '\356', '\034', '\147', + '\071', '\373', '\237', '\354', '\117', '\046', '\217', '\045', + '\307', '\131', '\316', '\351', '\331', '\272', '\056', '\330', + '\347', '\312', '\325', '\173', '\216', '\326', '\255', '\130', + '\237', '\023', '\157', '\257', '\336', '\071', '\136', '\242', + '\351', '\226', '\242', '\236', '\263', '\330', '\150', '\130', + '\367', '\174', '\262', '\013', '\056', '\320', '\161', '\355', + '\244', '\370', '\373', '\120', '\113', '\247', '\100', '\322', + '\263', '\065', '\270', '\112', '\373', '\346', '\106', '\372', + '\062', '\117', '\353', '\147', '\354', '\230', '\351', '\243', + '\353', '\355', '\323', '\033', '\171', '\166', '\362', '\270', + '\135', '\357', '\163', '\247', '\032', '\067', '\353', '\120', + '\317', '\233', '\032', '\357', '\065', '\173', '\061', '\117', + '\301', '\020', '\010', '\047', '\161', '\010', '\014', '\200', + '\127', '\100', '\076', '\157', '\200', '\306', '\210', '\071', + '\053', '\215', '\076', '\255', '\004', '\215', '\240', '\055', + '\211', '\016', '\260', '\077', '\046', '\357', '\222', '\366', + '\103', '\267', '\170', '\077', '\131', '\357', '\035', '\330', + '\134', '\271', '\034', '\360', '\231', '\175', '\166', '\232', + '\275', '\056', '\363', '\026', '\310', '\231', '\234', '\160', + '\106', '\267', '\214', '\077', '\006', '\172', '\244', '\224', + '\022', '\336', '\057', '\361', '\262', '\341', '\363', '\272', + '\205', '\163', '\155', '\216', '\312', '\231', '\174', '\114', + '\215', '\370', '\110', '\314', '\046', '\203', '\317', '\147', + '\031', '\102', '\136', '\232', '\160', '\356', '\234', '\274', + '\257', '\345', '\275', '\220', '\341', '\060', '\313', '\114', + '\272', '\321', '\347', '\274', '\231', '\230', '\127', '\071', + '\071', '\022', '\147', '\337', '\202', '\367', '\116', '\336', + '\067', '\077', '\175', '\100', '\375', '\052', '\344', '\377', + '\264', '\120', '\144', '\234', '\226', '\237', '\046', '\172', + '\234', '\207', '\363', '\362', '\006', '\302', '\266', '\341', + '\056', '\334', '\377', '\006', '\367', '\233', '\063', '\305', + '\067', '\300', '\366', '\115', '\070', '\266', '\320', '\347', + '\223', '\356', '\137', '\320', '\064', '\206', '\365', '\270', + '\357', '\363', '\161', '\306', '\357', '\120', '\366', '\317', + '\244', '\370', '\373', '\211', '\353', '\201', '\237', '\355', + '\174', '\337', '\132', '\224', '\146', '\363', '\174', '\201', + '\234', '\005', '\171', '\135', '\032', '\337', '\161', '\021', + '\316', '\255', '\163', '\347', '\312', '\172', '\346', '\167', + '\312', '\234', '\337', '\274', '\167', '\344', '\063', '\045', + '\303', '\347', '\313', '\022', '\314', '\213', '\027', '\060', + '\271', '\322', '\043', '\230', '\122', '\035', '\122', '\026', + '\177', '\367', '\340', '\167', '\243', '\313', '\227', '\213', + '\377', '\311', '\147', '\113', '\316', '\307', '\276', '\016', + '\237', '\057', '\271', '\114', '\076', '\247', '\166', '\127', + '\312', '\371', '\223', '\357', '\346', '\334', '\152', '\316', + '\237', '\043', '\111', '\357', '\050', '\127', '\316', '\227', + '\162', '\370', '\254', '\372', '\032', '\306', '\250', '\352', + '\035', '\271', '\233', '\263', '\053', '\247', '\133', '\176', + '\154', '\172', '\352', '\357', '\070', '\154', '\063', '\123', + '\245', '\245', '\174', '\027', '\353', '\260', '\135', '\251', + '\164', '\314', '\226', '\271', '\112', '\327', '\244', '\365', + '\275', '\042', '\327', '\366', '\101', '\212', '\215', '\217', + '\310', '\357', '\327', '\170', '\001', '\263', '\361', '\050', + '\222', '\171', '\134', '\250', '\113', '\151', '\102', '\337', + '\223', '\106', '\325', '\316', '\133', '\066', '\137', '\333', + '\077', '\306', '\176', '\035', '\373', '\202', '\150', '\147', + '\204', '\035', '\230', '\010', '\131', '\016', '\214', '\071', + '\003', '\073', '\267', '\156', '\376', '\046', '\127', '\105', + '\362', '\215', '\216', '\277', '\325', '\131', '\337', '\354', + '\062', '\344', '\033', '\136', '\374', '\154', '\023', '\113', + '\204', '\353', '\356', '\374', '\046', '\147', '\175', '\243', + '\313', '\322', '\157', '\166', '\005', '\372', '\015', '\257', + '\330', '\161', '\346', '\321', '\347', '\072', '\035', '\300', + '\250', '\176', '\233', '\053', '\323', '\157', '\165', '\171', + '\372', '\355', '\056', '\303', '\361', '\255', '\156', '\322', + '\167', '\276', '\261', '\304', '\157', '\162', '\043', '\372', + '\255', '\256', '\121', '\277', '\335', '\361', '\067', '\274', + '\034', '\375', '\126', '\147', '\175', '\257', '\053', '\024', + '\110', '\307', '\214', '\273', '\201', '\277', '\311', '\361', + '\267', '\071', '\376', '\106', '\227', '\162', '\334', '\073', + '\047', '\217', '\143', '\362', '\373', '\157', '\236', '\263', + '\051', '\347', '\200', '\266', '\167', '\204', '\256', '\361', + '\235', '\056', '\251', '\175', '\327', '\372', '\136', '\227', + '\055', '\115', '\111', '\060', '\251', '\255', '\064', '\331', + '\336', '\177', '\213', '\344', '\147', '\150', '\033', '\110', + '\176', '\234', '\146', '\060', '\357', '\344', '\222', '\367', + '\002', '\247', '\315', '\177', '\071', '\111', '\376', '\226', + '\162', '\322', '\361', '\056', '\342', '\232', '\147', '\341', + '\353', '\074', '\323', '\033', '\302', '\074', '\317', '\161', + '\366', '\374', '\071', '\174', '\332', '\017', '\247', '\313', + '\357', '\124', '\326', '\344', '\247', '\030', '\037', '\265', + '\107', '\001', '\204', '\317', '\267', '\020', '\135', '\176', + '\233', '\350', '\112', '\251', '\356', '\371', '\352', '\223', + '\235', '\156', '\237', '\142', '\134', '\262', '\022', '\011', + '\134', '\217', '\137', '\153', '\374', '\337', '\353', '\364', + '\143', '\015', '\146', '\177', '\060', '\347', '\250', '\076', + '\264', '\245', '\033', '\363', '\071', '\210', '\011', '\370', + '\323', '\163', '\302', '\355', '\010', '\317', '\051', '\026', + '\133', '\037', '\235', '\042', '\217', '\341', '\132', '\347', + '\117', '\363', '\316', '\325', '\231', '\247', '\325', '\061', + '\027', '\256', '\207', '\002', '\235', '\107', '\243', '\216', + '\161', '\067', '\373', '\377', '\325', '\160', '\372', '\014', + '\234', '\127', '\176', '\107', '\370', '\035', '\062', '\177', + '\056', '\110', '\322', '\341', '\100', '\114', '\303', '\146', + '\226', '\205', '\047', '\115', '\247', '\031', '\164', '\023', + '\066', '\246', '\231', '\160', '\050', '\162', '\255', '\337', + '\023', '\176', '\206', '\346', '\300', '\143', '\231', '\107', + '\067', '\323', '\055', '\160', '\304', '\156', '\245', '\317', + '\322', '\347', '\120', '\233', '\333', '\340', '\074', '\024', + '\302', '\340', '\335', '\116', '\013', '\150', '\041', '\066', + '\366', '\317', '\323', '\035', '\330', '\337', '\026', '\323', + '\235', '\264', '\204', '\276', '\110', '\167', '\321', '\335', + '\364', '\045', '\372', '\062', '\014', '\304', '\122', '\034', + '\202', '\226', '\321', '\075', '\164', '\057', '\055', '\247', + '\373', '\120', '\243', '\025', '\164', '\077', '\075', '\000', + '\247', '\341', '\253', '\130', '\015', '\245', '\230', '\055', + '\253', '\351', '\101', '\132', '\103', '\153', '\151', '\035', + '\175', '\215', '\036', '\242', '\365', '\130', '\017', '\017', + '\323', '\237', '\321', '\043', '\364', '\165', '\332', '\110', + '\233', '\150', '\063', '\075', '\212', '\023', '\372', '\343', + '\124', '\116', '\133', '\350', '\033', '\264', '\225', '\266', + '\321', '\166', '\172', '\202', '\276', '\111', '\117', '\142', + '\375', '\074', '\105', '\025', '\124', '\111', '\156', '\332', + '\001', '\333', '\130', '\115', '\036', '\332', '\111', '\273', + '\250', '\206', '\152', '\351', '\317', '\261', '\256', '\274', + '\124', '\107', '\365', '\324', '\200', '\223', '\341', '\156', + '\362', '\121', '\023', '\371', '\251', '\231', '\132', '\320', + '\177', '\155', '\324', '\116', '\173', '\150', '\057', '\172', + '\145', '\037', '\355', '\307', '\232', '\014', '\120', '\220', + '\272', '\250', '\033', '\247', '\377', '\136', '\352', '\243', + '\020', '\205', '\351', '\000', '\365', '\323', '\101', '\234', + '\022', '\017', '\323', '\000', '\015', '\322', '\020', '\015', + '\323', '\137', '\320', '\323', '\364', '\014', '\375', '\045', + '\375', '\025', '\375', '\065', '\075', '\153', '\365', '\234', + '\371', '\175', '\330', '\242', '\264', '\077', '\361', '\047', + '\260', '\037', '\052', '\377', '\337', '\345', '\076', '\350', + '\022', '\322', '\310', '\376', '\075', '\042', '\377', '\316', + '\231', '\177', '\362', '\206', '\355', '\315', '\162', '\245', + '\127', '\200', '\115', '\044', '\357', '\260', '\174', '\152', + '\043', '\370', '\135', '\142', '\077', '\170', '\026', '\274', + '\004', '\136', '\003', '\157', '\221', '\154', '\271', '\374', + '\116', '\144', '\246', '\113', '\176', '\307', '\270', '\030', + '\054', '\003', '\153', '\300', '\106', '\360', '\024', '\360', + '\200', '\335', '\240', '\025', '\164', '\201', '\303', '\340', + '\273', '\340', '\373', '\340', '\357', '\301', '\011', '\227', + '\274', '\163', '\376', '\065', '\070', '\017', '\076', '\005', + '\323', '\121', '\301', '\231', '\340', '\146', '\160', '\033', + '\270', '\023', '\054', '\117', '\223', '\075', '\274', '\034', + '\170', '\300', '\156', '\320', '\005', '\016', '\203', '\357', + '\202', '\277', '\003', '\077', '\006', '\057', '\203', '\177', + '\002', '\277', '\004', '\377', '\001', '\042', '\340', '\175', + '\160', '\021', '\104', '\101', '\032', '\154', '\373', '\114', + '\060', '\207', '\337', '\273', '\200', '\205', '\340', '\356', + '\164', '\371', '\035', '\332', '\172', '\360', '\050', '\250', + '\000', '\265', '\240', '\015', '\004', '\323', '\345', '\175', + '\370', '\163', '\340', '\050', '\370', '\021', '\370', '\051', + '\370', '\005', '\070', '\003', '\316', '\202', '\377', '\002', + '\037', '\202', '\014', '\354', '\151', '\063', '\300', '\274', + '\014', '\371', '\155', '\346', '\142', '\360', '\145', '\360', + '\200', '\176', '\067', '\175', '\030', '\154', '\007', '\165', + '\240', '\025', '\364', '\201', '\141', '\360', '\267', '\340', + '\045', '\360', '\062', '\170', '\035', '\274', '\005', '\042', + '\340', '\002', '\270', '\004', '\246', '\361', '\267', '\063', + '\160', '\007', '\050', '\001', '\233', '\300', '\267', '\100', + '\043', '\350', '\004', '\117', '\203', '\027', '\300', '\061', + '\360', '\052', '\370', '\065', '\070', '\007', '\056', '\200', + '\117', '\200', '\213', '\177', '\373', '\011', '\346', '\202', + '\333', '\300', '\027', '\063', '\305', '\057', '\277', '\037', + '\254', '\006', '\137', '\007', '\345', '\374', '\035', '\010', + '\064', '\200', '\156', '\360', '\064', '\170', '\021', '\374', + '\003', '\070', '\015', '\316', '\200', '\337', '\202', '\013', + '\340', '\062', '\277', '\350', '\302', '\236', '\065', '\003', + '\314', '\001', '\267', '\203', '\045', '\354', '\267', '\203', + '\325', '\140', '\023', '\330', '\002', '\052', '\301', '\116', + '\260', '\033', '\154', '\253', '\320', '\337', '\256', '\233', + '\100', '\105', '\235', '\273', '\351', '\333', '\344', '\366', + '\371', '\032', '\132', '\345', '\052', '\202', '\035', '\356', + '\046', '\117', '\165', '\205', '\010', '\252', '\033', '\132', + '\353', '\047', '\011', '\046', '\253', '\065', '\067', '\046', + '\105', '\125', '\245', '\301', '\355', '\267', '\056', '\046', + '\272', '\253', '\241', '\251', '\326', '\337', '\036', '\017', + '\030', '\261', '\337', '\337', '\120', '\127', '\341', '\365', + '\354', '\364', '\127', '\124', '\065', '\370', '\352', '\075', + '\276', '\051', '\104', '\011', '\252', '\276', '\332', '\135', + '\065', '\311', '\272', '\116', '\131', '\202', '\162', '\123', + '\155', '\265', '\307', '\031', '\116', '\110', '\364', '\173', + '\074', '\216', '\240', '\111', '\152', '\253', '\150', '\152', + '\254', '\365', '\271', '\275', '\216', '\240', '\044', '\125', + '\171', '\352', '\375', '\050', '\276', '\321', '\357', '\163', + '\004', '\065', '\251', '\326', '\127', '\345', '\365', '\350', + '\115', '\105', '\336', '\206', '\052', '\275', '\252', '\240', + '\141', '\347', '\116', '\176', '\112', '\363', '\056', '\107', + '\120', '\223', '\174', '\015', '\115', '\115', '\162', '\165', + '\010', '\052', '\174', '\236', '\026', '\217', '\257', '\311', + '\223', '\030', '\163', '\050', '\324', '\270', '\153', '\175', + '\166', '\110', '\022', '\252', '\153', '\335', '\165', '\015', + '\365', '\325', '\025', '\122', '\144', '\102', '\114', '\025', + '\032', '\374', '\114', '\074', '\202', '\126', '\352', '\315', + '\210', '\232', '\167', '\240', '\015', '\062', '\061', '\234', + '\021', '\115', '\366', '\271', '\061', '\054', '\136', '\267', + '\157', '\227', '\307', '\031', '\166', '\046', '\066', '\325', + '\271', '\275', '\136', '\147', '\070', '\236', '\330', '\210', + '\111', '\142', '\075', '\057', '\036', '\224', '\044', '\117', + '\133', '\125', '\215', '\273', '\036', '\045', '\232', '\200', + '\210', '\167', '\172', '\075', '\315', '\076', '\271', '\212', + '\140', '\127', '\303', '\016', '\124', '\307', '\147', '\356', + '\052', '\154', '\256', '\333', '\321', '\056', '\127', '\021', + '\240', '\204', '\352', '\245', '\162', '\265', '\005', '\137', + '\221', '\253', '\012', '\074', '\156', '\237', '\137', '\256', + '\042', '\250', '\255', '\152', '\250', '\267', '\056', '\032', + '\365', '\041', '\044', '\075', '\150', '\007', '\045', '\311', + '\232', '\225', '\074', '\005', '\114', '\300', '\041', '\266', + '\046', '\133', '\074', '\344', '\110', '\340', '\211', '\146', + '\002', '\266', '\170', '\107', '\063', '\246', '\136', '\275', + '\043', '\250', '\111', '\336', '\012', '\164', '\001', '\146', + '\223', '\011', '\250', '\330', '\147', '\304', '\076', '\247', + '\270', '\316', '\135', '\317', '\150', '\244', '\266', '\272', + '\332', '\353', '\321', '\162', '\235', '\021', '\115', '\156', + '\150', '\306', '\154', '\262', '\256', '\042', '\150', '\364', + '\324', '\127', '\325', '\172', '\365', '\246', '\042', '\314', + '\167', '\277', '\107', '\157', '\052', '\362', '\066', '\067', + '\131', '\027', '\211', '\356', '\156', '\366', '\064', '\371', + '\153', '\121', '\246', '\114', '\221', '\304', '\250', '\250', + '\310', '\162', '\344', '\136', '\212', '\207', '\234', '\011', + '\126', '\077', '\331', '\101', '\147', '\022', '\367', '\124', + '\074', '\344', '\110', '\320', '\066', '\071', '\302', '\232', + '\350', '\367', '\126', '\170', '\141', '\120', '\342', '\001', + '\021', '\067', '\271', '\153', '\275', '\226', '\375', '\061', + '\001', '\025', '\357', '\020', '\023', '\046', '\065', '\117', + '\210', '\305', '\025', '\152', '\052', '\022', '\126', '\300', + '\044', '\111', '\134', '\321', '\032', '\320', '\270', '\222', + '\035', '\213', '\053', '\110', '\073', '\342', '\032', '\216', + '\150', '\134', '\005', '\266', '\062', '\236', '\156', '\302', + '\361', '\304', '\226', '\111', '\065', '\151', '\231', '\252', + '\046', '\065', '\350', '\016', '\114', '\013', '\275', '\253', + '\260', '\166', '\117', '\155', '\375', '\056', '\275', '\251', + '\250', '\021', '\135', '\355', '\323', '\233', '\021', '\371', + '\334', '\355', '\125', '\230', '\100', '\046', '\240', '\142', + '\277', '\333', '\147', '\135', '\044', '\352', '\347', '\365', + '\355', '\327', '\233', '\212', '\144', '\155', '\370', '\035', + '\353', '\302', '\337', '\320', '\350', '\354', '\221', '\304', + '\150', '\222', '\212', '\332', '\356', '\244', '\270', '\255', + '\224', '\140', '\341', '\223', '\005', '\266', '\232', '\065', + '\215', '\114', '\300', '\026', '\363', '\024', '\322', '\273', + '\012', '\175', '\036', '\271', '\110', '\264', '\331', '\254', + '\257', '\346', '\204', '\365', '\005', '\373', '\341', '\363', + '\170', '\275', '\356', '\170', '\100', '\305', '\146', '\331', + '\065', '\047', '\054', '\273', '\126', '\267', '\277', '\252', + '\106', '\256', '\042', '\150', '\303', '\176', '\120', '\047', + '\127', '\021', '\320', '\215', '\377', '\217', '\327', '\377', + '\001', '\226', '\047', '\030', '\162', '\200', '\067', '\000', + '\000', + +}; + +static const char file_6x13[] = { + '\037', '\213', '\010', '\010', '\126', '\121', '\054', '\100', + '\000', '\003', '\066', '\170', '\061', '\063', '\055', '\111', + '\123', '\117', '\070', '\070', '\065', '\071', '\055', '\061', + '\056', '\160', '\143', '\146', '\000', '\355', '\234', '\177', + '\170', '\024', '\307', '\171', '\307', '\277', '\002', '\001', + '\002', '\013', '\020', '\106', '\004', '\141', '\203', '\045', + '\333', '\330', '\306', '\066', '\262', '\045', '\014', '\030', + '\073', '\330', '\346', '\054', '\035', '\240', '\104', '\110', + '\030', '\111', '\061', '\070', '\151', '\345', '\343', '\156', + '\045', '\155', '\270', '\037', '\362', '\375', '\300', '\222', + '\215', '\101', '\010', '\044', '\204', '\114', '\012', '\051', + '\216', '\103', '\034', '\222', '\100', '\203', '\123', '\334', + '\342', '\032', '\327', '\264', '\265', '\023', '\307', '\165', + '\152', '\047', '\301', '\055', '\165', '\150', '\202', '\133', + '\352', '\322', '\230', '\076', '\365', '\037', '\364', '\251', + '\363', '\074', '\116', '\037', '\047', '\161', '\373', '\270', + '\245', '\337', '\331', '\335', '\071', '\215', '\206', '\335', + '\273', '\225', '\340', '\111', '\237', '\247', '\017', '\003', + '\237', '\331', '\331', '\335', '\171', '\147', '\346', '\175', + '\347', '\335', '\231', '\331', '\071', '\335', '\025', '\264', + '\205', '\073', '\047', '\002', '\050', '\040', '\143', '\110', + '\007', '\243', '\175', '\116', '\172', '\014', '\057', '\106', + '\170', '\304', '\130', '\240', '\120', '\236', '\063', '\021', + '\341', '\171', '\221', '\223', '\347', '\154', '\025', '\160', + '\174', '\002', '\120', '\242', '\334', '\077', '\274', '\004', + '\250', '\160', '\356', '\227', '\060', '\052', '\276', '\007', + '\130', '\346', '\234', '\157', '\247', '\354', '\354', '\373', + '\200', '\036', '\347', '\174', '\037', '\053', '\077', '\160', + '\277', '\335', '\000', '\131', '\337', '\222', '\172', '\373', + '\336', '\247', '\140', '\207', '\202', '\053', '\031', '\115', + '\027', '\211', '\253', '\141', '\227', '\134', '\060', '\237', + '\321', '\002', '\221', '\270', '\227', '\121', '\120', '\044', + '\076', '\313', '\150', '\225', '\110', '\174', '\236', '\221', + '\051', '\022', '\135', '\214', '\272', '\205', '\374', '\144', + '\121', '\257', '\110', '\210', '\053', '\273', '\105', '\102', + '\144', '\336', '\057', '\023', '\317', '\211', '\314', '\057', + '\062', '\172', '\111', '\134', '\131', '\112', '\176', '\040', + '\256', '\374', '\224', '\321', '\273', '\042', '\361', '\357', + '\214', '\176', '\041', '\022', '\277', '\141', '\064', '\107', + '\030', '\112', '\030', '\154', '\236', '\110', '\214', '\047', + '\325', '\114', '\024', '\054', '\146', '\264', '\121', '\134', + '\231', '\104', '\236', '\020', '\211', '\166', '\062', '\040', + '\363', '\000', '\173', '\231', '\134', '\336', '\330', '\320', + '\334', '\020', '\130', '\025', '\154', '\135', '\023', '\134', + '\121', '\327', '\324', '\274', '\146', '\235', '\270', '\324', + '\322', '\120', '\313', '\304', '\052', '\063', '\025', '\306', + '\362', '\300', '\252', '\272', '\372', '\165', '\255', '\042', + '\013', '\226', '\233', '\135', '\106', '\004', '\017', '\006', + '\353', '\126', '\254', '\154', '\266', '\257', '\254', '\062', + '\042', '\146', '\046', '\206', '\246', '\372', '\100', '\103', + '\063', '\326', '\240', '\051', '\330', '\374', '\140', '\135', + '\155', '\363', '\112', '\373', '\146', '\223', '\021', '\063', + '\153', '\022', '\361', '\210', '\021', '\117', '\121', '\054', + '\120', '\133', '\333', '\332', '\324', '\274', '\256', '\076', + '\150', '\337', '\304', '\352', '\272', '\265', '\301', '\372', + '\326', '\246', '\272', '\207', '\202', '\130', '\335', '\130', + '\327', '\320', '\154', '\047', '\327', '\004', '\233', '\032', + '\353', '\133', '\232', '\353', '\032', '\033', '\132', '\327', + '\252', '\047', '\353', '\320', '\264', '\072', '\120', '\123', + '\327', '\260', '\002', '\065', '\010', '\174', '\056', '\270', + '\046', '\260', '\042', '\330', '\152', '\125', '\205', '\232', + '\225', '\201', '\065', '\254', '\167', '\250', '\375', '\165', + '\115', '\215', '\113', '\226', '\054', '\272', '\053', '\173', + '\043', '\330', '\120', '\323', '\130', '\053', '\044', '\253', + '\121', '\323', '\270', '\172', '\335', '\032', '\321', '\172', + '\254', '\316', '\254', '\217', '\232', '\341', '\212', '\110', + '\042', '\026', '\062', '\343', '\025', '\155', '\211', '\170', + '\372', '\266', '\212', '\212', '\246', '\216', '\120', '\322', + '\250', '\010', '\305', '\043', '\025', '\106', '\374', '\213', + '\211', '\356', '\333', '\120', '\023', '\130', '\335', '\272', + '\322', '\122', '\027', '\153', '\145', '\102', '\030', '\014', + '\225', '\302', '\066', '\225', '\226', '\075', '\052', '\155', + '\033', '\124', '\256', '\251', '\034', '\246', '\157', '\145', + '\145', '\365', '\035', '\225', '\325', '\013', '\252', '\052', + '\357', '\134', '\044', '\376', '\327', '\124', '\056', '\256', + '\252', '\164', '\132', '\126', '\131', '\355', '\330', '\120', + '\121', '\020', '\017', '\264', '\004', '\152', '\035', '\215', + '\054', '\237', '\053', '\260', '\002', '\160', '\205', '\343', + '\223', '\166', '\030', '\317', '\177', '\127', '\070', '\347', + '\152', '\132', '\234', '\235', '\077', '\377', '\353', '\363', + '\042', '\357', '\360', '\353', '\136', '\101', '\324', '\361', + '\036', '\172', '\372', '\373', '\237', '\354', '\275', '\034', + '\135', '\216', '\056', '\107', '\227', '\243', '\113', '\033', + '\071', '\343', '\326', '\173', '\316', '\170', '\263', '\120', + '\314', '\343', '\316', '\014', '\167', '\222', '\024', '\162', + '\374', '\131', '\102', '\242', '\344', '\000', '\071', '\105', + '\212', '\050', '\260', '\224', '\164', '\222', '\103', '\344', + '\264', '\230', '\247', '\071', '\067', '\057', '\043', '\151', + '\162', '\230', '\234', '\041', '\045', '\234', '\317', '\153', + '\111', '\027', '\071', '\102', '\316', '\222', '\322', '\161', + '\300', '\112', '\262', '\211', '\034', '\045', '\357', '\223', + '\062', '\116', '\163', '\365', '\244', '\207', '\034', '\043', + '\347', '\310', '\154', '\256', '\013', '\126', '\223', '\355', + '\344', '\145', '\362', '\001', '\251', '\340', '\302', '\241', + '\231', '\014', '\220', '\127', '\311', '\207', '\144', '\056', + '\347', '\323', '\265', '\144', '\027', '\171', '\235', '\174', + '\104', '\346', '\161', '\042', '\375', '\002', '\331', '\103', + '\336', '\044', '\037', '\223', '\371', '\034', '\240', '\037', + '\046', '\117', '\221', '\343', '\344', '\023', '\122', '\125', + '\314', '\065', '\003', '\331', '\107', '\116', '\024', '\333', + '\223', '\375', '\102', '\322', '\101', '\366', '\223', '\223', + '\244', '\160', '\012', '\365', '\047', '\121', '\162', '\200', + '\234', '\042', '\105', '\123', '\251', '\077', '\351', '\044', + '\207', '\310', '\151', '\122', '\314', '\105', '\314', '\062', + '\222', '\046', '\207', '\311', '\031', '\122', '\062', '\215', + '\372', '\223', '\056', '\162', '\204', '\234', '\045', '\245', + '\134', '\217', '\254', '\044', '\233', '\310', '\121', '\362', + '\076', '\051', '\343', '\372', '\244', '\236', '\364', '\220', + '\143', '\344', '\034', '\231', '\135', '\112', '\375', '\311', + '\166', '\362', '\062', '\371', '\200', '\124', '\314', '\240', + '\376', '\144', '\200', '\274', '\112', '\076', '\044', '\163', + '\271', '\320', '\131', '\113', '\166', '\221', '\327', '\311', + '\107', '\144', '\336', '\114', '\352', '\117', '\366', '\220', + '\067', '\311', '\307', '\144', '\176', '\031', '\365', '\047', + '\117', '\221', '\343', '\344', '\023', '\122', '\065', '\213', + '\372', '\223', '\175', '\344', '\004', '\301', '\125', '\324', + '\237', '\164', '\220', '\375', '\344', '\044', '\051', '\344', + '\262', '\151', '\011', '\211', '\222', '\003', '\344', '\024', + '\051', '\232', '\115', '\375', '\111', '\047', '\071', '\104', + '\116', '\223', '\342', '\071', '\324', '\237', '\244', '\311', + '\141', '\162', '\206', '\224', '\134', '\103', '\375', '\111', + '\027', '\071', '\102', '\316', '\222', '\322', '\162', '\352', + '\117', '\066', '\221', '\243', '\344', '\175', '\122', '\306', + '\145', '\131', '\075', '\351', '\041', '\307', '\310', '\071', + '\062', '\373', '\132', '\352', '\117', '\266', '\223', '\227', + '\311', '\007', '\244', '\342', '\072', '\352', '\117', '\006', + '\310', '\253', '\344', '\103', '\062', '\367', '\172', '\352', + '\117', '\166', '\221', '\327', '\311', '\107', '\144', '\336', + '\134', '\352', '\117', '\366', '\220', '\067', '\311', '\307', + '\144', '\376', '\015', '\324', '\237', '\074', '\105', '\216', + '\223', '\117', '\110', '\325', '\215', '\324', '\237', '\354', + '\043', '\047', '\010', '\156', '\242', '\376', '\244', '\203', + '\354', '\047', '\047', '\111', '\341', '\074', '\352', '\117', + '\242', '\344', '\000', '\071', '\105', '\212', '\156', '\246', + '\376', '\244', '\223', '\034', '\042', '\247', '\111', '\361', + '\055', '\324', '\237', '\244', '\311', '\141', '\162', '\206', + '\224', '\334', '\112', '\375', '\111', '\027', '\071', '\102', + '\316', '\222', '\122', '\256', '\076', '\127', '\222', '\115', + '\344', '\050', '\171', '\237', '\224', '\125', '\002', '\115', + '\364', '\307', '\357', '\260', '\357', '\352', '\231', '\336', + '\367', '\320', '\320', '\374', '\077', '\303', '\071', '\116', + '\363', '\070', '\316', '\200', '\167', '\020', '\353', '\156', + '\272', '\053', '\312', '\235', '\143', '\241', '\113', '\036', + '\041', '\177', '\313', '\010', '\217', '\062', '\214', '\163', + '\230', '\240', '\244', '\351', '\012', '\326', '\372', '\136', + '\242', '\007', '\221', '\127', '\254', '\154', '\307', '\072', + '\307', '\071', '\116', '\273', '\212', '\235', '\243', '\133', + '\033', '\307', '\073', '\171', '\345', '\212', '\130', '\344', + '\055', '\125', '\216', '\245', '\056', '\062', '\005', '\012', + '\023', '\234', '\166', '\345', '\253', '\107', '\334', '\273', + '\322', '\241', '\330', '\345', '\276', '\127', '\220', '\345', + '\225', '\153', '\145', '\227', '\173', '\344', '\027', '\257', + '\000', '\142', '\275', '\070', '\331', '\111', '\027', '\152', + '\314', '\166', '\221', '\031', '\247', '\060', '\306', '\301', + '\313', '\326', '\172', '\171', '\222', '\011', '\043', '\320', + '\111', '\206', '\011', '\071', '\312', '\363', '\012', '\113', + '\163', '\310', '\170', '\261', '\064', '\107', '\171', '\136', + '\062', '\367', '\345', '\271', '\167', '\061', '\341', '\377', + '\203', '\174', '\056', '\133', '\217', '\264', '\177', '\162', + '\371', '\301', '\245', '\354', '\203', '\134', '\355', '\036', + '\015', '\152', '\340', '\224', '\227', '\035', '\113', '\306', + '\073', '\347', '\042', '\170', '\075', '\247', '\042', '\210', + '\161', '\112', '\214', '\005', '\045', '\316', '\161', '\254', + '\017', '\031', '\031', '\104', '\236', '\111', '\056', '\344', + '\012', '\045', '\030', '\032', '\107', '\312', '\235', '\266', + '\272', '\005', '\071', '\126', '\311', '\261', '\140', '\202', + '\222', '\026', '\327', '\047', '\373', '\150', '\337', '\110', + '\306', '\270', '\221', '\204', '\174', '\375', '\341', '\066', + '\166', '\370', '\265', '\217', '\227', '\134', '\271', '\166', + '\364', '\052', '\107', '\324', '\315', '\145', '\110', '\166', + '\054', '\025', '\363', '\242', '\234', '\103', '\246', '\172', + '\264', '\115', '\330', '\163', '\206', '\123', '\146', '\221', + '\223', '\147', '\214', '\163', '\056', '\256', '\117', '\364', + '\250', '\153', '\014', '\206', '\217', '\331', '\342', '\070', + '\313', '\311', '\377', '\051', '\227', '\374', '\176', '\306', + '\126', '\065', '\310', '\266', '\310', '\366', '\350', '\310', + '\173', '\352', '\334', '\240', '\137', '\327', '\121', '\313', + '\323', '\333', '\046', '\164', '\235', '\342', '\034', '\375', + '\266', '\121', '\325', '\113', '\237', '\037', '\107', '\032', + '\344', '\334', '\235', '\157', '\317', '\304', '\317', '\263', + '\231', '\053', '\210', '\072', '\334', '\326', '\113', '\045', + '\016', '\252', '\255', '\244', '\255', '\345', '\132', '\303', + '\255', '\054', '\341', '\047', '\323', '\134', '\230', '\344', + '\122', '\207', '\224', '\021', '\343', '\323', '\070', '\270', + '\077', '\103', '\156', '\372', '\115', '\121', '\312', '\225', + '\155', '\224', '\355', '\053', '\360', '\220', '\051', '\327', + '\362', '\116', '\121', '\164', '\234', '\346', '\234', '\353', + '\101', '\352', '\136', '\214', '\241', '\347', '\154', '\242', + '\123', '\226', '\327', '\232', '\117', '\216', '\143', '\002', + '\061', '\056', '\115', '\367', '\121', '\217', '\324', '\107', + '\312', '\115', '\305', '\160', '\333', '\271', '\311', '\250', + '\372', '\170', '\075', '\033', '\136', '\365', '\250', '\345', + '\346', '\253', '\107', '\317', '\163', '\215', '\017', '\175', + '\144', '\160', '\363', '\055', '\057', '\177', '\313', '\165', + '\337', '\353', '\131', '\160', '\353', '\173', '\371', '\314', + '\027', '\071', '\367', '\163', '\205', '\162', '\217', '\264', + '\036', '\334', '\312', '\325', '\353', '\325', '\203', '\227', + '\217', '\346', '\232', '\027', '\124', '\031', '\061', '\166', + '\316', '\160', '\230', '\354', '\324', '\161', '\215', '\213', + '\214', '\333', '\063', '\127', '\256', '\235', '\353', '\101', + '\370', '\327', '\225', '\012', '\123', '\264', '\363', '\251', + '\071', '\332', '\126', '\340', '\202', '\227', '\037', '\350', + '\365', '\350', '\270', '\325', '\243', '\076', '\077', '\362', + '\131', '\120', '\317', '\275', '\236', '\355', '\134', '\062', + '\271', '\372', '\107', '\315', '\063', '\013', '\271', '\237', + '\005', '\175', '\114', '\323', '\355', '\354', '\146', '\153', + '\351', '\313', '\136', '\270', '\325', '\243', '\277', '\353', + '\250', '\210', '\361', '\147', '\174', '\216', '\266', '\211', + '\373', '\142', '\054', '\035', '\353', '\034', '\047', '\346', + '\150', '\233', '\133', '\137', '\346', '\263', '\265', '\054', + '\113', '\174', '\302', '\044', '\375', '\063', '\237', '\015', + '\304', '\265', '\351', '\016', '\122', '\146', '\026', '\206', + '\333', '\133', '\017', '\372', '\270', '\243', '\343', '\345', + '\157', '\152', '\236', '\221', '\370', '\201', '\033', '\162', + '\015', '\240', '\217', '\043', '\156', '\365', '\344', '\263', + '\265', '\356', '\157', '\176', '\346', '\037', '\165', '\015', + '\341', '\147', '\315', '\217', '\034', '\272', '\214', '\304', + '\257', '\325', '\365', '\251', '\337', '\172', '\146', '\150', + '\270', '\255', '\111', '\365', '\362', '\013', '\225', '\164', + '\056', '\337', '\321', '\145', '\362', '\331', '\300', '\155', + '\156', '\124', '\327', '\056', '\272', '\137', '\117', '\201', + '\373', '\232', '\122', '\107', '\267', '\235', '\354', '\113', + '\165', '\015', '\052', '\353', '\224', '\175', '\253', '\327', + '\343', '\365', '\134', '\253', '\350', '\365', '\250', '\143', + '\374', '\245', '\014', '\252', '\035', '\364', '\265', '\363', + '\150', '\202', '\364', '\151', '\061', '\117', '\311', '\071', + '\314', '\155', '\355', '\257', '\217', '\325', '\272', '\057', + '\271', '\315', '\013', '\172', '\075', '\352', '\263', '\344', + '\345', '\327', '\045', '\012', '\262', '\115', '\372', '\132', + '\306', '\117', '\075', '\162', '\176', '\361', '\252', '\107', + '\177', '\077', '\235', '\212', '\013', '\175', '\307', '\117', + '\075', '\372', '\032', '\113', '\257', '\117', '\265', '\233', + '\134', '\133', '\346', '\033', '\173', '\105', '\220', '\317', + '\310', '\170', '\370', '\233', '\177', '\104', '\220', '\276', + '\120', '\014', '\367', '\071', '\110', '\237', '\207', '\324', + '\266', '\171', '\315', '\101', '\172', '\160', '\153', '\217', + '\237', '\266', '\311', '\040', '\366', '\025', '\365', '\161', + '\047', '\337', '\063', '\062', '\022', '\273', '\311', '\340', + '\066', '\107', '\344', '\153', '\133', '\276', '\271', '\310', + '\055', '\350', '\076', '\252', '\256', '\265', '\275', '\326', + '\262', '\122', '\237', '\174', '\363', '\234', '\233', '\076', + '\302', '\376', '\105', '\171', '\364', '\361', '\362', '\151', + '\077', '\373', '\306', '\272', '\315', '\274', '\306', '\003', + '\057', '\031', '\165', '\314', '\367', '\043', '\223', '\157', + '\376', '\321', '\145', '\324', '\371', '\304', '\317', '\370', + '\352', '\246', '\113', '\276', '\367', '\040', '\371', '\256', + '\230', '\353', '\375', '\264', '\014', '\027', '\372', '\376', + '\130', '\227', '\153', '\145', '\232', '\334', '\110', '\367', + '\004', '\275', '\312', '\164', '\253', '\133', '\015', '\162', + '\117', '\310', '\153', '\357', '\347', '\122', '\005', '\365', + '\335', '\310', '\357', '\172', '\107', '\216', '\023', '\242', + '\175', '\162', '\377', '\111', '\256', '\333', '\274', '\374', + '\346', '\142', '\366', '\023', '\145', '\137', '\113', '\337', + '\224', '\317', '\222', '\127', '\136', '\325', '\217', '\325', + '\275', '\316', '\134', '\372', '\350', '\372', '\346', '\262', + '\201', '\252', '\213', '\376', '\231', '\116', '\011', '\334', + '\237', '\323', '\321', '\354', '\075', '\112', '\075', '\205', + '\155', '\305', '\332', '\177', '\072', '\206', '\336', '\001', + '\162', '\371', '\277', '\276', '\046', '\220', '\163', '\256', + '\237', '\175', '\253', '\122', '\247', '\235', '\262', '\137', + '\047', '\301', '\375', '\363', '\057', '\267', '\040', '\327', + '\200', '\371', '\366', '\000', '\364', '\266', '\346', '\273', + '\057', '\164', '\230', '\011', '\133', '\367', '\253', '\225', + '\164', '\276', '\061', '\140', '\244', '\341', '\267', '\361', + '\371', '\234', '\334', '\247', '\225', '\143', '\223', '\237', + '\317', '\314', '\244', '\214', '\134', '\357', '\352', '\143', + '\205', '\133', '\220', '\343', '\337', '\305', '\004', '\267', + '\271', '\104', '\330', '\136', '\237', '\357', '\256', '\161', + '\256', '\253', '\210', '\161', '\272', '\024', '\336', '\237', + '\237', '\352', '\341', '\122', '\175', '\126', '\240', '\352', + '\055', '\354', '\065', '\026', '\303', '\307', '\034', '\077', + '\301', '\153', '\217', '\316', '\217', '\117', '\251', '\317', + '\214', '\372', '\054', '\351', '\301', '\255', '\155', '\342', + '\271', '\051', '\163', '\344', '\146', '\343', '\302', '\347', + '\310', '\115', '\246', '\310', '\311', '\057', '\337', '\275', + '\364', '\317', '\166', '\165', '\337', '\021', '\351', '\053', + '\363', '\324', '\003', '\134', '\070', '\016', '\312', '\171', + '\324', '\153', '\055', '\066', '\106', '\223', '\121', '\337', + '\057', '\325', '\075', '\033', '\065', '\024', '\215', '\102', + '\106', '\076', '\243', '\043', '\221', '\221', '\375', '\060', + '\022', '\231', '\111', '\243', '\220', '\221', '\371', '\364', + '\365', '\115', '\056', '\031', '\021', '\256', '\302', '\360', + '\317', '\337', '\305', '\134', '\250', '\376', '\315', '\303', + '\034', '\027', '\031', '\077', '\173', '\203', '\352', '\376', + '\255', '\332', '\077', '\352', '\336', '\235', '\272', '\106', + '\326', '\375', '\273', '\150', '\024', '\062', '\152', '\377', + '\370', '\225', '\121', '\155', '\355', '\127', '\106', '\325', + '\307', '\153', '\277', '\117', '\367', '\321', '\242', '\121', + '\310', '\250', '\372', '\370', '\225', '\121', '\365', '\361', + '\053', '\003', '\134', '\270', '\167', '\073', '\023', '\271', + '\367', '\156', '\125', '\277', '\226', '\276', '\045', '\367', + '\373', '\274', '\366', '\371', '\164', '\273', '\371', '\331', + '\257', '\322', '\355', '\346', '\107', '\106', '\267', '\233', + '\037', '\031', '\125', '\037', '\277', '\062', '\272', '\255', + '\375', '\310', '\350', '\101', '\175', '\057', '\361', '\172', + '\047', '\051', '\161', '\312', '\221', '\173', '\250', '\352', + '\173', '\217', '\334', '\147', '\025', '\367', '\325', '\171', + '\121', '\265', '\265', '\133', '\273', '\362', '\331', '\332', + '\257', '\214', '\152', '\153', '\277', '\062', '\252', '\335', + '\056', '\246', '\155', '\156', '\373', '\203', '\172', '\160', + '\333', '\163', '\312', '\367', '\156', '\056', '\336', '\223', + '\345', '\236', '\207', '\034', '\007', '\325', '\275', '\136', + '\267', '\367', '\005', '\335', '\267', '\375', '\354', '\213', + '\351', '\276', '\355', '\107', '\106', '\367', '\155', '\077', + '\062', '\272', '\157', '\373', '\221', '\321', '\175', '\073', + '\237', '\214', '\154', '\127', '\361', '\010', '\144', '\364', + '\040', '\377', '\136', '\101', '\034', '\345', '\173', '\135', + '\276', '\367', '\026', '\257', '\275', '\101', '\165', '\376', + '\001', '\334', '\307', '\236', '\174', '\373', '\174', '\156', + '\143', '\217', '\337', '\275', '\301', '\221', '\310', '\270', + '\215', '\043', '\371', '\144', '\124', '\175', '\374', '\356', + '\363', '\025', '\215', '\102', '\106', '\325', '\307', '\257', + '\214', '\252', '\217', '\037', '\031', '\371', '\034', '\313', + '\375', '\051', '\277', '\373', '\157', '\252', '\137', '\373', + '\335', '\347', '\313', '\067', '\007', '\371', '\365', '\203', + '\174', '\062', '\371', '\346', '\240', '\174', '\372', '\370', + '\225', '\311', '\067', '\007', '\171', '\315', '\077', '\156', + '\357', '\212', '\136', '\143', '\250', '\032', '\324', '\271', + '\110', '\235', '\203', '\364', '\371', '\107', '\204', '\134', + '\163', '\220', '\237', '\061', '\321', '\257', '\114', '\256', + '\071', '\310', '\317', '\370', '\166', '\261', '\155', '\313', + '\267', '\067', '\350', '\265', '\207', '\077', '\035', '\103', + '\237', '\365', '\253', '\266', '\363', '\152', '\233', '\133', + '\075', '\316', '\167', '\250', '\372', '\372', '\167', '\366', + '\060', '\332', '\261', '\331', '\376', '\362', '\203', '\163', + '\252', '\106', '\133', '\031', '\075', '\316', '\324', '\300', + '\026', '\345', '\306', '\266', '\376', '\047', '\067', '\061', + '\352', '\353', '\355', '\355', '\267', '\043', '\236', '\312', + '\157', '\117', '\154', '\144', '\064', '\320', '\315', '\250', + '\117', '\134', '\353', '\335', '\302', '\150', '\213', '\225', + '\245', '\127', '\210', '\131', '\131', '\304', '\015', '\212', + '\155', '\263', '\253', '\264', '\112', '\266', '\242', '\176', + '\121', '\174', '\277', '\135', '\121', '\357', '\166', '\121', + '\100', '\017', '\057', '\061', '\037', '\233', '\261', '\275', + '\177', '\347', '\143', '\172', '\063', '\170', '\152', '\335', + '\175', '\214', '\167', '\007', '\267', '\132', '\221', '\270', + '\261', '\311', '\322', '\210', '\247', '\275', '\342', '\264', + '\157', '\223', '\114', '\135', '\240', '\233', '\217', '\210', + '\262', '\073', '\266', '\132', '\221', '\274', '\326', '\277', + '\171', '\364', '\105', '\371', '\316', '\074', '\262', '\346', + '\146', '\065', '\037', '\112', '\011', '\133', '\365', '\154', + '\245', '\021', '\007', '\273', '\244', '\141', '\355', '\326', + '\273', '\245', '\172', '\245', '\354', '\100', '\117', '\017', + '\243', '\336', '\141', '\315', '\355', '\327', '\242', '\336', + '\154', '\224', '\275', '\066', '\340', '\226', '\257', '\147', + '\130', '\276', '\301', '\255', '\126', '\067', '\132', '\051', + '\273', '\175', '\331', '\256', '\025', '\247', '\331', '\136', + '\335', '\341', '\364', '\376', '\066', '\333', '\365', '\006', + '\055', '\215', '\204', '\012', '\203', '\326', '\215', '\315', + '\062', '\113', '\237', '\350', '\337', '\276', '\115', '\331', + '\033', '\135', '\212', '\237', '\156', '\353', '\037', '\174', + '\334', '\212', '\262', '\352', '\367', '\016', '\271', '\024', + '\243', '\236', '\136', '\073', '\213', '\132', '\336', '\140', + '\317', '\260', '\150', '\147', '\317', '\205', '\327', '\334', + '\262', '\354', '\354', '\165', '\273', '\053', '\332', '\354', + '\104', '\331', '\123', '\177', '\205', '\132', '\316', '\157', + '\131', '\050', '\117', '\275', '\071', '\243', '\301', '\341', + '\035', '\340', '\356', '\211', '\166', '\244', '\366', '\264', + '\217', '\342', '\255', '\307', '\157', '\207', '\247', '\167', + '\132', '\217', '\263', '\125', '\245', '\374', '\016', '\025', + '\160', '\136', '\031', '\317', '\306', '\140', '\054', '\107', + '\302', '\161', '\234', '\261', '\047', '\160', '\124', '\234', + '\310', '\321', '\352', '\012', '\216', '\302', '\223', '\071', + '\042', '\115', '\345', '\350', '\064', '\215', '\243', '\361', + '\164', '\316', '\146', '\063', '\070', '\132', '\315', '\104', + '\031', '\307', '\255', '\253', '\160', '\065', '\146', '\143', + '\016', '\127', '\203', '\345', '\250', '\300', '\265', '\270', + '\016', '\327', '\143', '\056', '\156', '\300', '\215', '\270', + '\011', '\363', '\160', '\063', '\156', '\301', '\255', '\230', + '\217', '\112', '\334', '\206', '\333', '\121', '\205', '\152', + '\054', '\300', '\035', '\130', '\210', '\105', '\130', '\214', + '\073', '\261', '\004', '\167', '\341', '\156', '\174', '\032', + '\113', '\161', '\017', '\356', '\305', '\175', '\130', '\206', + '\000', '\356', '\107', '\015', '\152', '\021', '\304', '\162', + '\254', '\300', '\112', '\324', '\341', '\063', '\370', '\054', + '\352', '\261', '\012', '\015', '\150', '\304', '\152', '\074', + '\040', '\276', '\006', '\214', '\146', '\264', '\340', '\163', + '\170', '\020', '\153', '\261', '\016', '\017', '\341', '\363', + '\370', '\002', '\176', '\007', '\277', '\213', '\126', '\074', + '\214', '\020', '\326', '\043', '\214', '\010', '\014', '\264', + '\241', '\035', '\035', '\060', '\361', '\105', '\154', '\100', + '\024', '\061', '\304', '\221', '\100', '\047', '\036', '\101', + '\022', '\051', '\244', '\221', '\301', '\106', '\074', '\212', + '\056', '\164', '\343', '\061', '\074', '\216', '\115', '\170', + '\002', '\233', '\161', '\376', '\242', '\303', '\026', '\364', + '\140', '\053', '\172', '\261', '\015', '\333', '\321', '\207', + '\176', '\354', '\300', '\000', '\166', '\142', '\020', '\117', + '\142', '\027', '\276', '\204', '\337', '\303', '\156', '\354', + '\301', '\227', '\361', '\373', '\330', '\213', '\247', '\360', + '\025', '\074', '\215', '\257', '\142', '\037', '\276', '\206', + '\147', '\360', '\165', '\354', '\307', '\067', '\360', '\115', + '\174', '\013', '\007', '\160', '\020', '\177', '\200', '\157', + '\343', '\020', '\236', '\305', '\167', '\360', '\207', '\070', + '\214', '\347', '\360', '\107', '\370', '\143', '\034', '\301', + '\363', '\370', '\023', '\274', '\200', '\243', '\170', '\021', + '\177', '\212', '\227', '\160', '\014', '\177', '\206', '\077', + '\307', '\137', '\340', '\145', '\274', '\202', '\357', '\342', + '\173', '\170', '\025', '\337', '\307', '\153', '\370', '\113', + '\274', '\216', '\037', '\340', '\257', '\360', '\006', '\336', + '\304', '\017', '\361', '\043', '\374', '\030', '\307', '\361', + '\026', '\376', '\032', '\177', '\203', '\023', '\370', '\133', + '\274', '\215', '\237', '\340', '\044', '\376', '\016', '\077', + '\305', '\317', '\160', '\012', '\357', '\340', '\357', '\361', + '\017', '\070', '\215', '\177', '\304', '\273', '\370', '\047', + '\234', '\301', '\077', '\343', '\347', '\030', '\372', '\116', + '\335', '\331', '\202', '\313', '\134', '\346', '\062', '\377', + '\027', '\250', '\337', '\153', '\225', '\337', '\025', '\023', + '\173', '\271', '\327', '\301', '\376', '\056', '\233', '\370', + '\021', '\210', '\273', '\111', '\000', '\366', '\217', '\071', + '\064', '\021', '\361', '\013', '\020', '\021', '\022', '\043', + '\033', '\311', '\026', '\062', '\100', '\366', '\300', '\376', + '\155', '\213', '\203', '\260', '\177', '\364', '\341', '\105', + '\362', '\135', '\362', '\006', '\071', '\101', '\336', '\041', + '\342', '\271', '\077', '\107', '\176', '\105', '\076', '\026', + '\163', '\000', '\333', '\060', '\211', '\314', '\042', '\345', + '\344', '\106', '\162', '\073', '\271', '\233', '\004', '\110', + '\035', '\151', '\042', '\255', '\304', '\044', '\351', '\002', + '\373', '\367', '\037', '\172', '\013', '\354', '\237', '\177', + '\330', '\115', '\236', '\046', '\373', '\311', '\101', '\362', + '\054', '\171', '\216', '\274', '\100', '\216', '\221', '\127', + '\310', '\367', '\311', '\033', '\344', '\055', '\362', '\166', + '\201', '\375', '\375', '\334', '\237', '\223', '\177', '\045', + '\377', '\106', '\176', '\111', '\376', '\213', '\374', '\067', + '\071', '\117', '\012', '\150', '\224', '\261', '\144', '\034', + '\231', '\100', '\046', '\222', '\053', '\310', '\144', '\062', + '\225', '\114', '\043', '\323', '\311', '\014', '\062', '\223', + '\314', '\042', '\127', '\223', '\071', '\244', '\234', '\134', + '\113', '\256', '\047', '\067', '\220', '\233', '\310', '\315', + '\344', '\126', '\122', '\111', '\156', '\047', '\325', '\344', + '\036', '\262', '\202', '\064', '\223', '\207', '\311', '\006', + '\362', '\010', '\111', '\221', '\014', '\171', '\224', '\164', + '\223', '\307', '\311', '\023', '\144', '\013', '\331', '\112', + '\266', '\221', '\076', '\262', '\203', '\354', '\044', '\117', + '\222', '\057', '\221', '\335', '\344', '\313', '\144', '\057', + '\371', '\012', '\371', '\052', '\371', '\032', '\371', '\072', + '\371', '\006', '\371', '\026', '\071', '\110', '\276', '\115', + '\236', '\045', '\057', '\220', '\227', '\310', '\153', '\344', + '\055', '\362', '\023', '\362', '\056', '\171', '\217', '\234', + '\043', '\277', '\044', '\277', '\042', '\347', '\205', '\015', + '\304', '\367', '\224', '\311', '\125', '\344', '\106', '\262', + '\220', '\334', '\107', '\226', '\223', '\007', '\310', '\132', + '\322', '\112', '\114', '\222', '\041', '\333', '\310', '\116', + '\262', '\213', '\074', '\115', '\236', '\045', '\317', '\223', + '\127', '\310', '\217', '\310', '\073', '\344', '\054', '\071', + '\107', '\176', '\115', '\306', '\362', '\145', '\150', '\022', + '\231', '\106', '\346', '\220', '\271', '\344', '\066', '\262', + '\220', '\334', '\111', '\226', '\221', '\025', '\244', '\201', + '\074', '\124', '\150', '\377', '\006', '\312', '\006', '\222', + '\044', '\233', '\311', '\000', '\331', '\105', '\366', '\222', + '\147', '\310', '\101', '\362', '\074', '\071', '\106', '\136', + '\043', '\077', '\046', '\157', '\223', '\167', '\310', '\031', + '\162', '\216', '\374', '\007', '\371', '\117', '\162', '\136', + '\324', '\075', '\216', '\165', '\213', '\357', '\130', '\223', + '\271', '\344', '\126', '\262', '\210', '\174', '\232', '\334', + '\113', '\126', '\220', '\006', '\322', '\102', '\102', '\144', + '\003', '\111', '\222', '\156', '\322', '\107', '\166', '\223', + '\275', '\344', '\031', '\162', '\220', '\034', '\046', '\307', + '\310', '\367', '\310', '\017', '\311', '\011', '\362', '\063', + '\362', '\056', '\371', '\027', '\362', '\013', '\362', '\033', + '\362', '\077', '\244', '\160', '\074', '\337', '\277', '\110', + '\304', '\150', '\013', '\145', '\242', '\351', '\160', '\107', + '\050', '\211', '\114', '\334', '\134', '\260', '\250', '\146', + '\061', '\122', '\035', '\241', '\210', '\141', '\235', '\055', + '\254', '\272', '\313', '\071', '\326', '\070', '\307', '\132', + '\347', '\030', '\240', '\144', '\173', '\322', '\060', '\320', + '\031', '\315', '\244', '\142', '\146', '\074', '\223', '\262', + '\157', '\054', '\130', '\350', '\144', '\270', '\037', '\115', + '\313', '\253', '\026', '\126', '\061', '\210', '\304', '\035', + '\062', '\121', '\055', '\023', '\013', '\144', '\142', '\221', + '\225', '\020', '\102', '\167', '\334', '\037', '\160', '\216', + '\102', '\330', '\312', '\051', '\157', '\324', '\070', '\307', + '\132', '\041', '\261', '\104', '\212', '\336', '\045', '\023', + '\167', '\312', '\304', '\142', '\047', '\121', '\155', '\327', + '\023', '\065', '\122', '\051', '\343', '\221', '\114', '\050', + '\012', '\266', '\065', '\224', '\066', '\222', '\366', '\111', + '\247', '\211', '\170', '\042', '\155', '\247', '\123', '\274', + '\032', '\065', '\343', '\355', '\350', '\064', '\222', '\146', + '\042', '\022', '\066', '\342', '\042', '\133', '\004', '\251', + '\316', '\120', '\330', '\200', '\321', '\025', '\216', '\206', + '\142', '\170', '\044', '\303', '\354', '\221', '\365', '\121', + '\304', '\063', '\261', '\365', '\106', '\062', '\145', '\266', + '\307', '\021', '\111', '\104', '\243', '\064', '\032', '\305', + '\204', '\014', '\102', '\061', '\246', '\122', '\241', '\170', + '\304', '\316', '\234', '\142', '\221', '\121', '\132', '\047', + '\224', '\064', '\342', '\121', '\243', '\055', '\155', '\247', + '\222', '\146', '\173', '\007', '\263', '\212', '\072', '\315', + '\324', '\006', '\313', '\166', '\010', '\047', '\142', '\261', + '\020', '\072', '\272', '\073', '\073', '\214', '\270', '\323', + '\010', '\244', '\242', '\241', '\124', '\007', '\036', '\063', + '\222', '\011', '\044', '\342', '\006', '\322', '\217', '\046', + '\220', '\356', '\020', '\326', '\156', '\113', '\144', '\222', + '\150', '\063', '\067', '\032', '\110', '\231', '\135', '\110', + '\031', '\033', '\051', '\143', '\130', '\205', '\306', '\115', + '\146', '\014', '\047', '\242', '\211', '\070', '\057', '\307', + '\114', '\073', '\045', '\364', '\307', '\060', '\003', '\260', + '\165', '\106', '\052', '\155', '\362', '\136', '\050', '\075', + '\252', '\205', '\350', '\372', '\144', '\050', '\274', '\301', + '\110', '\133', '\072', '\255', '\147', '\322', '\156', '\252', + '\163', '\125', '\352', '\027', '\066', '\315', '\260', '\231', + '\014', '\147', '\142', '\354', '\266', '\010', '\315', '\022', + '\116', '\044', '\015', '\266', '\040', '\304', '\166', '\217', + '\146', '\361', '\052', '\112', '\067', '\234', '\032', '\223', + '\366', '\231', '\122', '\123', '\332', '\214', '\322', '\135', + '\325', '\376', '\212', '\044', '\036', '\215', '\303', '\352', + '\225', '\154', '\357', '\206', '\063', '\111', '\332', '\077', + '\334', '\215', '\156', '\132', '\154', '\175', '\062', '\261', + '\301', '\210', '\213', '\262', '\122', '\106', '\330', '\062', + '\106', '\304', '\144', '\247', '\247', '\114', '\321', '\033', + '\235', '\335', '\166', '\331', '\211', '\144', '\244', '\215', + '\206', '\264', '\354', '\332', '\236', '\061', '\243', '\121', + '\043', '\226', '\260', '\325', '\216', '\046', '\332', '\315', + '\160', '\050', '\112', '\027', '\222', '\335', '\226', '\064', + '\332', '\315', '\224', '\355', '\067', '\261', '\120', '\070', + '\051', '\012', '\324', '\237', '\016', '\366', '\141', '\052', + '\143', '\165', '\157', '\322', '\356', '\313', '\354', '\131', + '\050', '\234', '\111', '\033', '\210', '\145', '\204', '\213', + '\204', '\150', '\244', '\316', '\016', '\335', '\027', '\303', + '\106', '\204', '\365', '\207', '\204', '\057', '\144', '\245', + '\330', '\274', '\030', '\325', '\317', '\104', '\207', '\265', + '\317', '\151', '\172', '\134', '\364', '\171', '\122', '\164', + '\067', '\223', '\035', '\241', '\150', '\233', '\135', '\245', + '\163', '\061', '\225', '\165', '\002', '\313', '\120', '\001', + '\273', '\143', '\002', '\166', '\073', '\002', '\166', '\307', + '\265', '\105', '\215', '\056', '\004', '\154', '\323', '\006', + '\262', '\326', '\011', '\044', '\205', '\055', '\003', '\101', + '\324', '\310', '\046', '\005', '\155', '\341', '\240', '\055', + '\034', '\124', '\204', '\203', '\131', '\251', '\072', '\073', + '\117', '\235', '\235', '\247', '\116', '\311', '\123', '\227', + '\315', '\023', '\114', '\167', '\240', '\301', '\256', '\256', + '\321', '\316', '\336', '\150', '\147', '\157', '\124', '\262', + '\067', '\072', '\031', '\262', '\122', '\061', '\016', '\135', + '\146', '\147', '\264', '\033', '\215', '\266', '\033', '\266', + '\330', '\242', '\055', '\266', '\150', '\213', '\042', '\332', + '\222', '\225', '\131', '\147', '\337', '\154', '\356', '\110', + '\044', '\343', '\150', '\067', '\222', '\061', '\076', '\263', + '\353', '\243', '\051', '\204', '\034', '\377', '\264', '\157', + '\207', '\024', '\331', '\220', '\135', '\155', '\050', '\133', + '\104', '\310', '\062', '\103', '\210', '\317', '\233', '\064', + '\203', '\141', '\013', '\033', '\266', '\260', '\241', '\010', + '\033', '\131', '\051', '\323', '\316', '\143', '\332', '\171', + '\114', '\045', '\217', '\231', '\315', '\143', '\320', '\014', + '\161', '\273', '\272', '\204', '\235', '\075', '\141', '\147', + '\117', '\050', '\331', '\023', '\116', '\206', '\254', '\124', + '\304', '\334', '\150', '\212', '\013', '\266', '\021', '\062', + '\266', '\140', '\306', '\026', '\314', '\050', '\202', '\231', + '\254', '\104', '\267', '\175', '\063', '\155', '\031', '\241', + '\073', '\173', '\371', '\322', '\375', '\156', '\322', '\377', + '\002', '\174', '\155', '\142', '\140', '\200', '\114', '\000', + '\000', + +}; + +static char name_6x13[] = "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1"; +static char name_cursor[] = "cursor"; + +const BuiltinFileRec builtin_files[] = { + { "6x13.builtin", sizeof file_6x13, file_6x13, }, + { "cursor.builtin", sizeof file_cursor, file_cursor, } +}; + +const int builtin_files_count = sizeof (builtin_files) / sizeof (builtin_files[0]); + +const BuiltinDirRec builtin_dir[] = { + { "6x13.builtin", name_6x13, }, + { "cursor.builtin", name_cursor, } +}; + +const int builtin_dir_count = sizeof (builtin_dir) / sizeof (builtin_dir[0]); + +static char alias_fixed[] = "fixed"; +static char alias_6x13[] = "6x13"; +static char alias_6x13_100[] = "-misc-fixed-medium-r-semicondensed--13-100-100-100-c-60-iso8859-1"; + +const BuiltinAliasRec builtin_alias[] = { + { alias_fixed, name_6x13, }, + { alias_6x13, name_6x13, }, + { alias_6x13_100, name_6x13, } +}; + +const int builtin_alias_count = sizeof (builtin_alias) / sizeof (builtin_alias[0]); diff --git a/src/builtins/fpe.c b/src/builtins/fpe.c new file mode 100755 index 0000000..403dbb7 --- /dev/null +++ b/src/builtins/fpe.c @@ -0,0 +1,91 @@ +/* + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include "builtin.h" + +static int font_file_type; + +static const char builtin_fonts[] = "built-ins"; + +static int +BuiltinNameCheck (char *name) +{ + return (strcmp (name, builtin_fonts) == 0); +} + +static int +BuiltinInitFPE (FontPathElementPtr fpe) +{ + int status; + FontDirectoryPtr dir; + + status = BuiltinReadDirectory (fpe->name, &dir); + + if (status == Successful) + fpe->private = (pointer) dir; + return status; +} + +/* ARGSUSED */ +static int +BuiltinResetFPE (FontPathElementPtr fpe) +{ + FontDirectoryPtr dir; + + dir = (FontDirectoryPtr) fpe->private; + /* builtins can't change! */ + return Successful; +} + +static int +BuiltinFreeFPE (FontPathElementPtr fpe) +{ + FontFileFreeDir ((FontDirectoryPtr) fpe->private); + return Successful; +} + +void +BuiltinRegisterFpeFunctions(void) +{ + BuiltinRegisterFontFileFunctions (); + + font_file_type = RegisterFPEFunctions(BuiltinNameCheck, + BuiltinInitFPE, + BuiltinFreeFPE, + BuiltinResetFPE, + FontFileOpenFont, + FontFileCloseFont, + FontFileListFonts, + FontFileStartListFontsWithInfo, + FontFileListNextFontWithInfo, + (WakeupFpeFunc) 0, + (ClientDiedFunc) 0, + (LoadGlyphsFunc) 0, + (StartLaFunc) 0, + (NextLaFunc) 0, + (SetPathFunc) 0); +} diff --git a/src/builtins/render.c b/src/builtins/render.c new file mode 100755 index 0000000..4d10483 --- /dev/null +++ b/src/builtins/render.c @@ -0,0 +1,132 @@ +/* + * Copyright 1999 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include "builtin.h" + +static int +BuiltinOpenBitmap (FontPathElementPtr fpe, FontPtr *ppFont, int flags, + FontEntryPtr entry, char *fileName, fsBitmapFormat format, + fsBitmapFormatMask fmask, FontPtr unused) +{ + FontFilePtr file; + FontPtr pFont; + int ret; + int bit, + byte, + glyph, + scan, + image; + + file = BuiltinFileOpen (fileName); + if (!file) + return BadFontName; + pFont = malloc(sizeof(FontRec)); + if (!pFont) { + BuiltinFileClose (file, 0); + return AllocError; + } + /* set up default values */ + FontDefaultFormat(&bit, &byte, &glyph, &scan); + /* get any changes made from above */ + ret = CheckFSFormat(format, fmask, &bit, &byte, &scan, &glyph, &image); + + /* Fill in font record. Data format filled in by reader. */ + pFont->refcnt = 0; + pFont->maxPrivate = -1; + pFont->devPrivates = (pointer *) 0; + + ret = pcfReadFont (pFont, file, bit, byte, glyph, scan); + + BuiltinFileClose (file, 0); + if (ret != Successful) + free(pFont); + else + *ppFont = pFont; + return ret; +} + +static int +BuiltinGetInfoBitmap (FontPathElementPtr fpe, FontInfoPtr pFontInfo, + FontEntryPtr entry, char *fileName) +{ + FontFilePtr file; + int ret; + + file = BuiltinFileOpen (fileName); + if (!file) + return BadFontName; + ret = pcfReadFontInfo (pFontInfo, file); + BuiltinFileClose (file, 0); + return ret; +} + +static int +BuiltinOpenScalable (FontPathElementPtr fpe, + FontPtr *pFont, + int flags, + FontEntryPtr entry, + char *fileName, + FontScalablePtr vals, + fsBitmapFormat format, + fsBitmapFormatMask fmask, + FontPtr non_cachable_font) /* We don't do licensing */ +{ + return BadFontName; +} + +static int +BuiltinGetInfoScalable (FontPathElementPtr fpe, + FontInfoPtr pFontInfo, + FontEntryPtr entry, + FontNamePtr fontName, + char *fileName, + FontScalablePtr vals) +{ + return BadFontName; +} + +static FontRendererRec renderers[] = { + { ".builtin", 8, + BuiltinOpenBitmap, + BuiltinOpenScalable, + BuiltinGetInfoBitmap, + BuiltinGetInfoScalable, + 0 } +}; + +#define numRenderers (sizeof renderers / sizeof renderers[0]) + +void +BuiltinRegisterFontFileFunctions(void) +{ + int i; + for (i = 0; i < numRenderers; i++) + FontFileRegisterRenderer ((FontRendererRec *) &renderers[i]); +} + diff --git a/src/dummy.c b/src/dummy.c new file mode 100644 index 0000000..e69de29 diff --git a/src/fc/Makefile.am b/src/fc/Makefile.am new file mode 100644 index 0000000..3bfd231 --- /dev/null +++ b/src/fc/Makefile.am @@ -0,0 +1,16 @@ +INCLUDES = \ + -I${top_srcdir}/include + +AM_CFLAGS = $(XFONT_CFLAGS) $(OS_CFLAGS) $(CWARNFLAGS) + +noinst_LTLIBRARIES = libfc.la + +libfc_la_SOURCES = \ + fsconvert.c \ + fserve.c \ + fserve.h \ + fservestr.h \ + fsio.c \ + fsio.h \ + fslibos.h \ + fstrans.c diff --git a/src/fc/fsconvert.c b/src/fc/fsconvert.c new file mode 100755 index 0000000..15c5e42 --- /dev/null +++ b/src/fc/fsconvert.c @@ -0,0 +1,719 @@ +/* + * Copyright 1990 Network Computing Devices + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Network Computing Devices not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Network Computing Devices + * makes no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Dave Lemke, Network Computing Devices, Inc + */ +/* + * FS data conversion + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include "fservestr.h" +#include +#include "fslibos.h" + +extern char _fs_glyph_undefined; +extern char _fs_glyph_requested; + +/* + * converts data from font server form to X server form + */ + +void +_fs_convert_char_info(fsXCharInfo *src, xCharInfo *dst) +{ + dst->ascent = src->ascent; + dst->descent = src->descent; + dst->leftSideBearing = src->left; + dst->rightSideBearing = src->right; + dst->characterWidth = src->width; + dst->attributes = src->attributes; +} + +void +_fs_init_fontinfo(FSFpePtr conn, FontInfoPtr pfi) +{ + if (conn->fsMajorVersion == 1) { + unsigned short n; + n = pfi->firstCol; + pfi->firstCol = pfi->firstRow; + pfi->firstRow = n; + n = pfi->lastCol; + pfi->lastCol = pfi->lastRow; + pfi->lastRow = n; + pfi->defaultCh = ((pfi->defaultCh >> 8) & 0xff) + + ((pfi->defaultCh & 0xff) << 8); + } + + if (FontCouldBeTerminal (pfi)) + { + pfi->terminalFont = TRUE; + pfi->minbounds.ascent = pfi->fontAscent; + pfi->minbounds.descent = pfi->fontDescent; + pfi->minbounds.leftSideBearing = 0; + pfi->minbounds.rightSideBearing = pfi->minbounds.characterWidth; + pfi->maxbounds = pfi->minbounds; + } + + FontComputeInfoAccelerators (pfi); +} + +int +_fs_convert_props(fsPropInfo *pi, fsPropOffset *po, pointer pd, + FontInfoPtr pfi) +{ + FontPropPtr dprop; + int i, + nprops; + char *is_str; + fsPropOffset local_off; + char *off_adr; + char *pdc = pd; + +/* stolen from server/include/resource.h */ +#define BAD_RESOURCE 0xe0000000 + + nprops = pfi->nprops = pi->num_offsets; + + if (nprops < 0 + || nprops > SIZE_MAX/(sizeof(FontPropRec) + sizeof(char))) + return -1; + + dprop = malloc(sizeof(FontPropRec) * nprops + sizeof (char) * nprops); + if (!dprop) + return -1; + + is_str = (char *) (dprop + nprops); + pfi->props = dprop; + pfi->isStringProp = is_str; + + off_adr = (char *)po; + for (i = 0; i < nprops; i++, dprop++, is_str++) + { + memcpy(&local_off, off_adr, SIZEOF(fsPropOffset)); + dprop->name = MakeAtom(&pdc[local_off.name.position], + local_off.name.length, 1); + if (local_off.type != PropTypeString) { + *is_str = FALSE; + dprop->value = local_off.value.position; + } else { + *is_str = TRUE; + dprop->value = (INT32) MakeAtom(&pdc[local_off.value.position], + local_off.value.length, 1); + if (dprop->value == BAD_RESOURCE) + { + free (pfi->props); + pfi->nprops = 0; + pfi->props = 0; + pfi->isStringProp = 0; + return -1; + } + } + off_adr += SIZEOF(fsPropOffset); + } + + return nprops; +} + +void +_fs_free_props (FontInfoPtr pfi) +{ + if (pfi->props) + { + free (pfi->props); + pfi->nprops = 0; + pfi->props = 0; + } +} + +int +_fs_convert_lfwi_reply(FSFpePtr conn, FontInfoPtr pfi, + fsListFontsWithXInfoReply *fsrep, + fsPropInfo *pi, fsPropOffset *po, pointer pd) +{ + fsUnpack_XFontInfoHeader(fsrep, pfi); + _fs_init_fontinfo(conn, pfi); + + if (_fs_convert_props(pi, po, pd, pfi) == -1) + return AllocError; + + return Successful; +} + + +#define ENCODING_UNDEFINED(enc) \ + ((enc)->bits == &_fs_glyph_undefined ? \ + TRUE : \ + (access_done = access_done && (enc)->bits != &_fs_glyph_requested, \ + FALSE)) + +#define GLYPH_UNDEFINED(loc) ENCODING_UNDEFINED(encoding + (loc)) + +/* + * figures out what glyphs to request + * + * Includes logic to attempt to reduce number of round trips to the font + * server: when a glyph is requested, fs_build_range() requests a + * 16-glyph range of glyphs that contains the requested glyph. This is + * predicated on the belief that using a glyph increases the chances + * that nearby glyphs will be used: a good assumption for phonetic + * alphabets, but a questionable one for ideographic/pictographic ones. + */ +/* ARGSUSED */ +int +fs_build_range(FontPtr pfont, Bool range_flag, unsigned int count, + int item_size, unsigned char *data, int *nranges, + fsRange **ranges) +{ + FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate); + FSFontPtr fsfont = (FSFontPtr) (pfont->fontPrivate); + register CharInfoPtr encoding = fsfont->encoding; + FontInfoPtr pfi = &(pfont->info); + fsRange range; + int access_done = TRUE; + int err; + register unsigned long firstrow, lastrow, firstcol, lastcol; + register unsigned long row; + register unsigned long col; + register unsigned long loc; + + if (!fsd->glyphs_to_get) + return AccessDone; + + firstrow = pfi->firstRow; + lastrow = pfi->lastRow; + firstcol = pfi->firstCol; + lastcol = pfi->lastCol; + + /* Make sure we have default char */ + if (fsfont->pDefault && ENCODING_UNDEFINED(fsfont->pDefault)) + { + loc = fsfont->pDefault - encoding; + row = loc / (lastcol - firstcol + 1) + firstrow; + col = loc % (lastcol - firstcol + 1) + firstcol; + + range.min_char_low = range.max_char_low = col; + range.min_char_high = range.max_char_high = row; + + if ((err = add_range(&range, nranges, ranges, FALSE)) != + Successful) return err; + encoding[loc].bits = &_fs_glyph_requested; + access_done = FALSE; + } + + if (!range_flag && item_size == 1) + { + if (firstrow != 0) return AccessDone; + while (count--) + { + col = *data++; + if (col >= firstcol && col <= lastcol && + GLYPH_UNDEFINED(col - firstcol)) + { + int col1, col2; + col1 = col & 0xf0; + col2 = col1 + 15; + if (col1 < firstcol) col1 = firstcol; + if (col2 > lastcol) col2 = lastcol; + /* Collect a 16-glyph neighborhood containing the requested + glyph... should in most cases reduce the number of round + trips to the font server. */ + for (col = col1; col <= col2; col++) + { + if (!GLYPH_UNDEFINED(col - firstcol)) continue; + range.min_char_low = range.max_char_low = col; + range.min_char_high = range.max_char_high = 0; + if ((err = add_range(&range, nranges, ranges, FALSE)) != + Successful) return err; + encoding[col - firstcol].bits = &_fs_glyph_requested; + access_done = FALSE; + } + } + } + } + else + { + fsRange fullrange[1]; + + if (range_flag && count == 0) + { + count = 2; + data = (unsigned char *)fullrange; + fullrange[0].min_char_high = firstrow; + fullrange[0].min_char_low = firstcol; + fullrange[0].max_char_high = lastrow; + fullrange[0].max_char_low = lastcol; + } + + while (count--) + { + int row1, col1, row2, col2; + row1 = row2 = *data++; + col1 = col2 = *data++; + if (range_flag) + { + if (count) + { + row2 = *data++; + col2 = *data++; + count--; + } + else + { + row2 = lastrow; + col2 = lastcol; + } + if (row1 < firstrow) row1 = firstrow; + if (row2 > lastrow) row2 = lastrow; + if (col1 < firstcol) col1 = firstcol; + if (col2 > lastcol) col2 = lastcol; + } + else + { + if (row1 < firstrow || row1 > lastrow || + col1 < firstcol || col1 > lastcol) + continue; + } + for (row = row1; row <= row2; row++) + { + expand_glyph_range: ; + loc = (row - firstrow) * (lastcol + 1 - firstcol) + + (col1 - firstcol); + for (col = col1; col <= col2; col++, loc++) + { + if (GLYPH_UNDEFINED(loc)) + { + if (row1 == row2 && + (((col1 & 0xf) && col1 > firstcol) || + (col2 & 0xf) != 0xf) && (col2 < lastcol)) + { + /* If we're loading from a single row, expand + range of glyphs loaded to a multiple of + a 16-glyph range -- attempt to reduce number + of round trips to the font server. */ + col1 &= 0xf0; + col2 = (col2 & 0xf0) + 15; + if (col1 < firstcol) col1 = firstcol; + if (col2 > lastcol) col2 = lastcol; + goto expand_glyph_range; + } + range.min_char_low = range.max_char_low = col; + range.min_char_high = range.max_char_high = row; + if ((err = add_range(&range, nranges, ranges, FALSE)) != + Successful) return err; + encoding[loc].bits = &_fs_glyph_requested; + access_done = FALSE; + } + } + } + } + } + + return access_done ? + AccessDone : + Successful; +} + +#undef GLYPH_UNDEFINED +#undef ENCODING_UNDEFINED + + +/* _fs_clean_aborted_loadglyphs(): Undoes the changes to the encoding array + performed by fs_build_range(); for use if the associated LoadGlyphs + requests needs to be cancelled. */ + +void +_fs_clean_aborted_loadglyphs(FontPtr pfont, int num_expected_ranges, + fsRange *expected_ranges) +{ + register FSFontPtr fsfont; + register int i; + + fsfont = (FSFontPtr) pfont->fontPrivate; + if (fsfont->encoding) + { + fsRange full_range[1]; + if (!num_expected_ranges) + { + full_range[0].min_char_low = pfont->info.firstCol; + full_range[0].min_char_high = pfont->info.firstRow; + full_range[0].max_char_low = pfont->info.lastCol; + full_range[0].max_char_high = pfont->info.lastRow; + num_expected_ranges = 1; + expected_ranges = full_range; + } + + for (i = 0; i < num_expected_ranges; i++) + { + int row, col; + for (row = expected_ranges[i].min_char_high; + row <= expected_ranges[i].max_char_high; + row++) + { + register CharInfoPtr encoding = fsfont->encoding + + ((row - pfont->info.firstRow) * + (pfont->info.lastCol - + pfont->info.firstCol + 1) + + expected_ranges[i].min_char_low - + pfont->info.firstCol); + for (col = expected_ranges[i].min_char_low; + col <= expected_ranges[i].max_char_low; + encoding++, col++) + { + if (encoding->bits == &_fs_glyph_requested) + encoding->bits = &_fs_glyph_undefined; + } + } + } + } +} + +static int +_fs_get_glyphs(FontPtr pFont, unsigned long count, unsigned char *chars, + FontEncoding charEncoding, + unsigned long *glyphCount, /* RETURN */ + CharInfoPtr *glyphs) /* RETURN */ +{ + FSFontPtr fsdata; + unsigned int firstCol; + register unsigned int numCols; + unsigned int firstRow; + unsigned int numRows; + CharInfoPtr *glyphsBase; + register unsigned int c; + register CharInfoPtr pci; + unsigned int r; + CharInfoPtr encoding; + CharInfoPtr pDefault; + FSFontDataPtr fsd = (FSFontDataPtr) pFont->fpePrivate; + int err = Successful; + + fsdata = (FSFontPtr) pFont->fontPrivate; + encoding = fsdata->encoding; + pDefault = fsdata->pDefault; + firstCol = pFont->info.firstCol; + numCols = pFont->info.lastCol - firstCol + 1; + glyphsBase = glyphs; + + /* In this age of glyph caching, any glyphs gotten through this + procedure should already be loaded. If they are not, we are + dealing with someone (perhaps a ddx driver optimizing a font) + that doesn't understand the finer points of glyph caching. The + CHECK_ENCODING macro checks for this condition... if found, it + calls fs_load_all_glyphs(), which corrects it. Since the caller + of this code will not know how to handle a return value of + Suspended, the fs_load_all_glyphs() procedure will block and + freeze the server until the load operation is done. Moral: the + glyphCachingMode flag really must indicate the capabilities of + the ddx drivers. */ + +#define CHECK_ENCODING(cnum) \ + ( pci = encoding + (cnum), \ + fsd->glyphs_to_get ? \ + ( pci->bits == &_fs_glyph_undefined || pci->bits == &_fs_glyph_requested ? \ + ((err = fs_load_all_glyphs(pFont)), pci) : \ + pci ) : \ + pci ) + + switch (charEncoding) { + + case Linear8Bit: + case TwoD8Bit: + if (pFont->info.firstRow > 0) + break; + if (pFont->info.allExist && pDefault) { + while (err == Successful && count--) { + c = (*chars++) - firstCol; + if (c < numCols) + *glyphs++ = CHECK_ENCODING(c); + else + *glyphs++ = pDefault; + } + } else { + while (err == Successful && count--) { + c = (*chars++) - firstCol; + if (c < numCols && CHECK_ENCODING(c)->bits) + *glyphs++ = pci; + else if (pDefault) + *glyphs++ = pDefault; + } + } + break; + case Linear16Bit: + if (pFont->info.allExist && pDefault) { + while (err == Successful && count--) { + c = *chars++ << 8; + c = (c | *chars++) - firstCol; + if (c < numCols) + *glyphs++ = CHECK_ENCODING(c); + else + *glyphs++ = pDefault; + } + } else { + while (err == Successful && count--) { + c = *chars++ << 8; + c = (c | *chars++) - firstCol; + if (c < numCols && CHECK_ENCODING(c)->bits) + *glyphs++ = pci; + else if (pDefault) + *glyphs++ = pDefault; + } + } + break; + + case TwoD16Bit: + firstRow = pFont->info.firstRow; + numRows = pFont->info.lastRow - firstRow + 1; + while (err == Successful && count--) { + r = (*chars++) - firstRow; + c = (*chars++) - firstCol; + if (r < numRows && c < numCols && + CHECK_ENCODING(r * numCols + c)->bits) + *glyphs++ = pci; + else if (pDefault) + *glyphs++ = pDefault; + } + break; + } + *glyphCount = glyphs - glyphsBase; + return err; +} + + +static int +_fs_get_metrics(FontPtr pFont, unsigned long count, unsigned char *chars, + FontEncoding charEncoding, + unsigned long *glyphCount, /* RETURN */ + xCharInfo **glyphs) /* RETURN */ +{ + FSFontPtr fsdata; + unsigned int firstCol; + register unsigned int numCols; + unsigned int firstRow; + unsigned int numRows; + xCharInfo **glyphsBase; + register unsigned int c; + unsigned int r; + CharInfoPtr encoding; + CharInfoPtr pDefault; + + fsdata = (FSFontPtr) pFont->fontPrivate; + encoding = fsdata->inkMetrics; + pDefault = fsdata->pDefault; + /* convert default bitmap metric to default ink metric */ + if (pDefault) + pDefault = encoding + (pDefault - fsdata->encoding); + firstCol = pFont->info.firstCol; + numCols = pFont->info.lastCol - firstCol + 1; + glyphsBase = glyphs; + + + /* XXX - this should be much smarter */ + /* make sure the glyphs are there */ + switch (charEncoding) { + + case Linear8Bit: + case TwoD8Bit: + if (pFont->info.firstRow > 0) + break; + if (pFont->info.allExist && pDefault) { + while (count--) { + c = (*chars++) - firstCol; + if (c < numCols) + *glyphs++ = (xCharInfo *)&encoding[c]; + else + *glyphs++ = (xCharInfo *)pDefault; + } + } else { + while (count--) { + c = (*chars++) - firstCol; + if (c < numCols) + *glyphs++ = (xCharInfo *)(encoding + c); + else if (pDefault) + *glyphs++ = (xCharInfo *)pDefault; + } + } + break; + case Linear16Bit: + if (pFont->info.allExist && pDefault) { + while (count--) { + c = *chars++ << 8; + c = (c | *chars++) - firstCol; + if (c < numCols) + *glyphs++ = (xCharInfo *)(encoding + c); + else + *glyphs++ = (xCharInfo *)pDefault; + } + } else { + while (count--) { + c = *chars++ << 8; + c = (c | *chars++) - firstCol; + if (c < numCols) + *glyphs++ = (xCharInfo *)(encoding + c); + else if (pDefault) + *glyphs++ = (xCharInfo *)pDefault; + } + } + break; + + case TwoD16Bit: + firstRow = pFont->info.firstRow; + numRows = pFont->info.lastRow - firstRow + 1; + while (count--) { + r = (*chars++) - firstRow; + c = (*chars++) - firstCol; + if (r < numRows && c < numCols) + *glyphs++ = (xCharInfo *)(encoding + (r * numCols + c)); + else if (pDefault) + *glyphs++ = (xCharInfo *)pDefault; + } + break; + } + *glyphCount = glyphs - glyphsBase; + return Successful; +} + + +static void +_fs_unload_font(FontPtr pfont) +{ + FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate; + FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate; + CharInfoPtr encoding = fsdata->encoding; + FSGlyphPtr glyphs; + + /* + * fsdata points at FSFontRec, FSFontDataRec and name + */ + if (encoding) + free(encoding); + + while ((glyphs = fsdata->glyphs)) + { + fsdata->glyphs = glyphs->next; + free (glyphs); + } + + /* XXX we may get called after the resource DB has been cleaned out */ + if (find_old_font(fsd->fontid)) + DeleteFontClientID (fsd->fontid); + + _fs_free_props (&pfont->info); + + free(fsdata); + + DestroyFontRec(pfont); +} + +FontPtr +fs_create_font (FontPathElementPtr fpe, + char *name, + int namelen, + fsBitmapFormat format, + fsBitmapFormatMask fmask) +{ + FontPtr pfont; + FSFontPtr fsfont; + FSFontDataPtr fsd; + int bit, byte, scan, glyph; + + pfont = CreateFontRec (); + if (!pfont) + return 0; + fsfont = malloc (sizeof (FSFontRec) + sizeof (FSFontDataRec) + namelen + 1); + if (!fsfont) + { + DestroyFontRec (pfont); + return 0; + } + fsd = (FSFontDataPtr) (fsfont + 1); + bzero((char *) fsfont, sizeof(FSFontRec)); + bzero((char *) fsd, sizeof(FSFontDataRec)); + + pfont->fpe = fpe; + pfont->fontPrivate = (pointer) fsfont; + pfont->fpePrivate = (pointer) fsd; + + /* These font components will be needed in packGlyphs */ + CheckFSFormat(format, BitmapFormatMaskBit | + BitmapFormatMaskByte | + BitmapFormatMaskScanLineUnit | + BitmapFormatMaskScanLinePad, + &bit, + &byte, + &scan, + &glyph, + NULL); + pfont->format = format; + pfont->bit = bit; + pfont->byte = byte; + pfont->scan = scan; + pfont->glyph = glyph; + + pfont->info.nprops = 0; + pfont->info.props = 0; + pfont->info.isStringProp = 0; + + /* set font function pointers */ + pfont->get_glyphs = _fs_get_glyphs; + pfont->get_metrics = _fs_get_metrics; + pfont->unload_font = _fs_unload_font; + pfont->unload_glyphs = NULL; + + /* set the FPE private information */ + fsd->format = format; + fsd->fmask = fmask; + fsd->name = (char *) (fsd + 1); + memcpy (fsd->name, name, namelen); + fsd->name[namelen] = '\0'; + fsd->fontid = GetNewFontClientID (); + + /* save the ID */ + if (!StoreFontClientFont(pfont, fsd->fontid)) + { + free (fsfont); + DestroyFontRec (pfont); + return 0; + } + + return pfont; +} + +pointer +fs_alloc_glyphs (FontPtr pFont, int size) +{ + FSGlyphPtr glyphs; + FSFontPtr fsfont = (FSFontPtr) pFont->fontPrivate; + + glyphs = malloc (sizeof (FSGlyphRec) + size); + glyphs->next = fsfont->glyphs; + fsfont->glyphs = glyphs; + return (pointer) (glyphs + 1); +} diff --git a/src/fc/fserve.c b/src/fc/fserve.c new file mode 100755 index 0000000..b02b0b7 --- /dev/null +++ b/src/fc/fserve.c @@ -0,0 +1,3198 @@ +/* + +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Copyright 1990 Network Computing Devices + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the names of Network Computing Devices, or Digital + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * + * NETWORK COMPUTING DEVICES, AND DIGITAL AND DISCLAIM ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, + * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + * THIS SOFTWARE. + * + * Author: Dave Lemke, Network Computing Devices, Inc + */ +/* + * font server specific font access + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef WIN32 +#define _WILLWINSOCK_ +#endif +#define FONT_t +#define TRANS_CLIENT +#include "X11/Xtrans/Xtrans.h" +#include "X11/Xpoll.h" +#include +#include +#include +#include +#include +#include +#include "fservestr.h" +#include +#include + +#include +#define Time_t time_t + +#ifdef NCD +#include +#endif + +#include + +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif +#define TimeCmp(a,c,b) ((int) ((a) - (b)) c 0) + +#define NONZEROMETRICS(pci) ((pci)->leftSideBearing || \ + (pci)->rightSideBearing || \ + (pci)->ascent || \ + (pci)->descent || \ + (pci)->characterWidth) + +extern void ErrorF(const char *f, ...); + +static int fs_read_glyphs ( FontPathElementPtr fpe, FSBlockDataPtr blockrec ); +static int fs_read_list ( FontPathElementPtr fpe, FSBlockDataPtr blockrec ); +static int fs_read_list_info ( FontPathElementPtr fpe, + FSBlockDataPtr blockrec ); + +extern fd_set _fs_fd_mask; + +static void fs_block_handler ( pointer data, OSTimePtr wt, + pointer LastSelectMask ); +static int fs_wakeup ( FontPathElementPtr fpe, unsigned long *mask ); + +/* + * List of all FPEs + */ +static FSFpePtr fs_fpes; +/* + * Union of all FPE blockStates + */ +static CARD32 fs_blockState; + +static int _fs_restart_connection ( FSFpePtr conn ); +static void fs_send_query_bitmaps ( FontPathElementPtr fpe, + FSBlockDataPtr blockrec ); +static int fs_send_close_font ( FontPathElementPtr fpe, Font id ); +static void fs_client_died ( pointer client, FontPathElementPtr fpe ); +static void _fs_client_access ( FSFpePtr conn, pointer client, Bool sync ); +static void _fs_client_resolution ( FSFpePtr conn ); +static fsGenericReply *fs_get_reply (FSFpePtr conn, int *error); +static int fs_await_reply (FSFpePtr conn); +static void _fs_do_blocked (FSFpePtr conn); +static void fs_cleanup_bfont (FSBlockedFontPtr bfont); + +char _fs_glyph_undefined; +char _fs_glyph_requested; +static char _fs_glyph_zero_length; + +static int generationCount; + +static int FontServerRequestTimeout = 30 * 1000; + +static void +_fs_close_server (FSFpePtr conn); + +static FSFpePtr +_fs_init_conn (char *servername); + +static int +_fs_wait_connect (FSFpePtr conn); + +static int +_fs_send_init_packets (FSFpePtr conn); + +static void +_fs_check_reconnect (FSFpePtr conn); + +static void +_fs_start_reconnect (FSFpePtr conn); + +static void +_fs_free_conn (FSFpePtr conn); + +static int +fs_free_fpe(FontPathElementPtr fpe); + +/* + * Font server access + * + * the basic idea for the non-blocking access is to have the function + * called multiple times until the actual data is returned, instead + * of ClientBlocked. + * + * the first call to the function will cause the request to be sent to + * the font server, and a block record to be stored in the fpe's list + * of outstanding requests. the FS block handler also sticks the + * proper set of fd's into the select mask. when data is ready to be + * read in, the FS wakup handler will be hit. this will read the + * data off the wire into the proper block record, and then signal the + * client that caused the block so that it can restart. it will then + * call the access function again, which will realize that the data has + * arrived and return it. + */ + + +#ifdef DEBUG +static void +_fs_add_req_log(FSFpePtr conn, int opcode) +{ + conn->current_seq++; + fprintf (stderr, "\t\tRequest: %5d Opcode: %2d\n", + conn->current_seq, opcode); + conn->reqbuffer[conn->reqindex].opcode = opcode; + conn->reqbuffer[conn->reqindex].sequence = conn->current_seq; + conn->reqindex++; + if (conn->reqindex == REQUEST_LOG_SIZE) + conn->reqindex = 0; +} + +static void +_fs_add_rep_log (FSFpePtr conn, fsGenericReply *rep) +{ + int i; + + for (i = 0; i < REQUEST_LOG_SIZE; i++) + if (conn->reqbuffer[i].sequence == rep->sequenceNumber) + break; + if (i == REQUEST_LOG_SIZE) + fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: unknown\n", + rep->sequenceNumber); + else + fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: %d\n", + rep->sequenceNumber, + conn->reqbuffer[i].opcode); +} +#else +#define _fs_add_req_log(conn,op) ((conn)->current_seq++) +#define _fs_add_rep_log(conn,rep) +#endif + +static Bool +fs_name_check(char *name) +{ + /* Just make sure there is a protocol/ prefix */ + return (name && *name != '/' && strchr(name, '/')); +} + +static void +_fs_client_resolution(FSFpePtr conn) +{ + fsSetResolutionReq srreq; + int num_res; + FontResolutionPtr res; + + res = GetClientResolutions(&num_res); + + if (num_res) { + srreq.reqType = FS_SetResolution; + srreq.num_resolutions = num_res; + srreq.length = (SIZEOF(fsSetResolutionReq) + + (num_res * SIZEOF(fsResolution)) + 3) >> 2; + + _fs_add_req_log(conn, FS_SetResolution); + if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != -1) + (void)_fs_write_pad(conn, (char *) res, + (num_res * SIZEOF(fsResolution))); + } +} + +/* + * close font server and remove any state associated with + * this connection - this includes any client records. + */ + +static void +fs_close_conn(FSFpePtr conn) +{ + FSClientPtr client, nclient; + + _fs_close_server (conn); + + for (client = conn->clients; client; client = nclient) + { + nclient = client->next; + free (client); + } + conn->clients = NULL; +} + +/* + * the wakeup handlers have to be set when the FPE is open, and not + * removed until it is freed, in order to handle unexpected data, like + * events + */ +/* ARGSUSED */ +static int +fs_init_fpe(FontPathElementPtr fpe) +{ + FSFpePtr conn; + char *name; + int err; + int ret; + + /* open font server */ + /* create FS specific fpe info */ + name = fpe->name; + + /* hack for old style names */ + if (*name == ':') + name++; /* skip ':' */ + + conn = _fs_init_conn (name); + if (!conn) + err = AllocError; + else + { + err = init_fs_handlers (fpe, fs_block_handler); + if (err != Successful) + { + _fs_free_conn (conn); + err = AllocError; + } + else + { + fpe->private = conn; + conn->next = fs_fpes; + fs_fpes = conn; + ret = _fs_wait_connect (conn); + if (ret != FSIO_READY) + { + fs_free_fpe (fpe); + err = BadFontPath; + } + else + err = Successful; + } + } + + if (err == Successful) + { +#ifdef NCD + if (configData.ExtendedFontDiags) + printf("Connected to font server \"%s\"\n", name); +#endif +#ifdef DEBUG + fprintf (stderr, "connected to FS \"%s\"\n", name); +#endif + } + else + { +#ifdef DEBUG + fprintf(stderr, "failed to connect to FS \"%s\" %d\n", name, err); +#endif +#ifdef NCD + if (configData.ExtendedFontDiags) + printf("Failed to connect to font server \"%s\"\n", name); +#endif + ; + } + return err; +} + +static int +fs_reset_fpe(FontPathElementPtr fpe) +{ + (void) _fs_send_init_packets((FSFpePtr) fpe->private); + return Successful; +} + +/* + * this shouldn't be called till all refs to the FPE are gone + */ + +static int +fs_free_fpe(FontPathElementPtr fpe) +{ + FSFpePtr conn = (FSFpePtr) fpe->private, *prev; + + /* unhook from chain of all font servers */ + for (prev = &fs_fpes; *prev; prev = &(*prev)->next) + { + if (*prev == conn) + { + *prev = conn->next; + break; + } + } + _fs_unmark_block (conn, conn->blockState); + fs_close_conn(conn); + remove_fs_handlers(fpe, fs_block_handler, fs_fpes == 0); + _fs_free_conn (conn); + fpe->private = (pointer) 0; + +#ifdef NCD + if (configData.ExtendedFontDiags) + printf("Disconnected from font server \"%s\"\n", fpe->name); +#endif +#ifdef DEBUG + fprintf (stderr, "disconnect from FS \"%s\"\n", fpe->name); +#endif + + return Successful; +} + +static FSBlockDataPtr +fs_new_block_rec(FontPathElementPtr fpe, pointer client, int type) +{ + FSBlockDataPtr blockrec, + *prev; + FSFpePtr conn = (FSFpePtr) fpe->private; + int size; + + switch (type) { + case FS_OPEN_FONT: + size = sizeof(FSBlockedFontRec); + break; + case FS_LOAD_GLYPHS: + size = sizeof(FSBlockedGlyphRec); + break; + case FS_LIST_FONTS: + size = sizeof(FSBlockedListRec); + break; + case FS_LIST_WITH_INFO: + size = sizeof(FSBlockedListInfoRec); + break; + default: + size = 0; + break; + } + blockrec = malloc(sizeof(FSBlockDataRec) + size); + if (!blockrec) + return (FSBlockDataPtr) 0; + blockrec->data = (pointer) (blockrec + 1); + blockrec->client = client; + blockrec->sequenceNumber = -1; + blockrec->errcode = StillWorking; + blockrec->type = type; + blockrec->depending = 0; + blockrec->next = (FSBlockDataPtr) 0; + + /* stick it on the end of the list (since its expected last) */ + for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next) + ; + *prev = blockrec; + + return blockrec; +} + +static void +_fs_set_pending_reply (FSFpePtr conn) +{ + FSBlockDataPtr blockrec; + + for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) + if (blockrec->errcode == StillWorking) + break; + if (blockrec) + { + conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; + _fs_mark_block (conn, FS_PENDING_REPLY); + } + else + _fs_unmark_block (conn, FS_PENDING_REPLY); +} + +static void +_fs_remove_block_rec(FSFpePtr conn, FSBlockDataPtr blockrec) +{ + FSBlockDataPtr *prev; + + for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next) + if (*prev == blockrec) + { + *prev = blockrec->next; + break; + } + if (blockrec->type == FS_LOAD_GLYPHS) + { + FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data; + if (bglyph->num_expected_ranges) + free(bglyph->expected_ranges); + } + free(blockrec); + _fs_set_pending_reply (conn); +} + +static void +_fs_signal_clients_depending(FSClientsDependingPtr *clients_depending) +{ + FSClientsDependingPtr p; + + while ((p = *clients_depending)) + { + *clients_depending = p->next; + ClientSignal(p->client); + free(p); + } +} + +static int +_fs_add_clients_depending(FSClientsDependingPtr *clients_depending, pointer client) +{ + FSClientsDependingPtr new, cd; + + for (; (cd = *clients_depending); + clients_depending = &(*clients_depending)->next) + { + if (cd->client == client) + return Suspended; + } + + new = malloc (sizeof (FSClientsDependingRec)); + if (!new) + return BadAlloc; + + new->client = client; + new->next = 0; + *clients_depending = new; + return Suspended; +} + +/* + * When a request is aborted due to a font server failure, + * signal any depending clients to restart their dependant + * requests + */ +static void +_fs_clean_aborted_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec) +{ + switch(blockrec->type) { + case FS_OPEN_FONT: { + FSBlockedFontPtr bfont = (FSBlockedFontPtr)blockrec->data; + + fs_cleanup_bfont (bfont); + _fs_signal_clients_depending(&bfont->clients_depending); + break; + } + case FS_LOAD_GLYPHS: { + FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data; + + _fs_clean_aborted_loadglyphs(bglyph->pfont, + bglyph->num_expected_ranges, + bglyph->expected_ranges); + _fs_signal_clients_depending(&bglyph->clients_depending); + break; + } + case FS_LIST_FONTS: + break; + case FS_LIST_WITH_INFO: { + FSBlockedListInfoPtr binfo; + binfo = (FSBlockedListInfoPtr) blockrec->data; + if (binfo->status == FS_LFWI_REPLY) + FD_SET(conn->fs_fd, &_fs_fd_mask); + _fs_free_props (&binfo->info); + } + default: + break; + } +} + +static void +fs_abort_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec) +{ + _fs_clean_aborted_blockrec (conn, blockrec); + _fs_remove_block_rec (conn, blockrec); +} + +/* + * Tell the font server we've failed to complete an open and + * then unload the partially created font + */ +static void +fs_cleanup_bfont (FSBlockedFontPtr bfont) +{ + FSFontDataRec *fsd; + + if (bfont->pfont) + { + fsd = (FSFontDataRec *) bfont->pfont->fpePrivate; + + /* make sure the FS knows we choked on it */ + fs_send_close_font(bfont->pfont->fpe, bfont->fontid); + + /* + * Either unload the font if it's being opened for + * the first time, or smash the generation field to + * mark this font as an orphan + */ + if (!(bfont->flags & FontReopen)) + { + if (bfont->freeFont) + (*bfont->pfont->unload_font) (bfont->pfont); +#ifdef DEBUG + else + fprintf (stderr, "Not freeing other font in cleanup_bfont\n"); +#endif + bfont->pfont = 0; + } + else + fsd->generation = -1; + } +} + +/* + * Check to see if a complete reply is waiting + */ +static fsGenericReply * +fs_get_reply (FSFpePtr conn, int *error) +{ + char *buf; + fsGenericReply *rep; + int ret; + + /* block if the connection is down or paused in lfwi */ + if (conn->fs_fd == -1 || !FD_ISSET (conn->fs_fd, &_fs_fd_mask)) + { + *error = FSIO_BLOCK; + return 0; + } + + ret = _fs_start_read (conn, sizeof (fsGenericReply), &buf); + if (ret != FSIO_READY) + { + *error = FSIO_BLOCK; + return 0; + } + + rep = (fsGenericReply *) buf; + + ret = _fs_start_read (conn, rep->length << 2, &buf); + if (ret != FSIO_READY) + { + *error = FSIO_BLOCK; + return 0; + } + + *error = FSIO_READY; + + return (fsGenericReply *) buf; +} + +static Bool +fs_reply_ready (FSFpePtr conn) +{ + fsGenericReply *rep; + + if (conn->fs_fd == -1 || !FD_ISSET (conn->fs_fd, &_fs_fd_mask)) + return FALSE; + if (fs_data_read (conn) < sizeof (fsGenericReply)) + return FALSE; + rep = (fsGenericReply *) (conn->inBuf.buf + conn->inBuf.remove); + if (fs_data_read (conn) < rep->length << 2) + return FALSE; + return TRUE; +} + +static void +_fs_pending_reply (FSFpePtr conn) +{ + if (!(conn->blockState & FS_PENDING_REPLY)) + { + _fs_mark_block (conn, FS_PENDING_REPLY); + conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; + } +} + +static void +_fs_prepare_for_reply (FSFpePtr conn) +{ + _fs_pending_reply (conn); + _fs_flush (conn); +} + +/* + * Block (for a while) awaiting a complete reply + */ +static int +fs_await_reply (FSFpePtr conn) +{ + int ret; + + if (conn->blockState & FS_COMPLETE_REPLY) + return FSIO_READY; + + while (!fs_get_reply (conn, &ret)) + { + if (ret != FSIO_BLOCK) + return ret; + if (_fs_wait_for_readable (conn, FontServerRequestTimeout) != FSIO_READY) + { + _fs_connection_died (conn); + return FSIO_ERROR; + } + } + return FSIO_READY; +} + +/* + * Process the reply to an OpenBitmapFont request + */ +static int +fs_read_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; + fsOpenBitmapFontReply *rep; + FSBlockDataPtr blockOrig; + FSBlockedFontPtr origBfont; + int ret; + + rep = (fsOpenBitmapFontReply *) fs_get_reply (conn, &ret); + if (!rep || rep->type == FS_Error) + { + if (ret == FSIO_BLOCK) + return StillWorking; + if (rep) + _fs_done_read (conn, rep->length << 2); + fs_cleanup_bfont (bfont); + return BadFontName; + } + + /* If we're not reopening a font and FS detected a duplicate font + open request, replace our reference to the new font with a + reference to an existing font (possibly one not finished + opening). If this is a reopen, keep the new font reference... + it's got the metrics and extents we read when the font was opened + before. This also gives us the freedom to easily close the font + if we we decide (in fs_read_query_info()) that we don't like what + we got. */ + + if (rep->otherid && !(bfont->flags & FontReopen)) + { + fs_cleanup_bfont (bfont); + + /* Find old font if we're completely done getting it from server. */ + bfont->pfont = find_old_font(rep->otherid); + bfont->freeFont = FALSE; + bfont->fontid = rep->otherid; + bfont->state = FS_DONE_REPLY; + /* + * look for a blocked request to open the same font + */ + for (blockOrig = conn->blockedRequests; + blockOrig; + blockOrig = blockOrig->next) + { + if (blockOrig != blockrec && blockOrig->type == FS_OPEN_FONT) + { + origBfont = (FSBlockedFontPtr) blockOrig->data; + if (origBfont->fontid == rep->otherid) + { + blockrec->depending = blockOrig->depending; + blockOrig->depending = blockrec; + bfont->state = FS_DEPENDING; + bfont->pfont = origBfont->pfont; + break; + } + } + } + if (bfont->pfont == NULL) + { + /* XXX - something nasty happened */ + ret = BadFontName; + } + else + ret = AccessDone; + } + else + { + bfont->pfont->info.cachable = rep->cachable != 0; + bfont->state = FS_INFO_REPLY; + /* + * Reset the blockrec for the next reply + */ + blockrec->sequenceNumber = bfont->queryInfoSequence; + conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; + ret = StillWorking; + } + _fs_done_read (conn, rep->length << 2); + return ret; +} + +static Bool +fs_fonts_match (FontInfoPtr pInfo1, FontInfoPtr pInfo2) +{ + int i; + + if (pInfo1->firstCol != pInfo2->firstCol || + pInfo1->lastCol != pInfo2->lastCol || + pInfo1->firstRow != pInfo2->firstRow || + pInfo1->lastRow != pInfo2->lastRow || + pInfo1->defaultCh != pInfo2->defaultCh || + pInfo1->noOverlap != pInfo2->noOverlap || + pInfo1->terminalFont != pInfo2->terminalFont || + pInfo1->constantMetrics != pInfo2->constantMetrics || + pInfo1->constantWidth != pInfo2->constantWidth || + pInfo1->inkInside != pInfo2->inkInside || + pInfo1->inkMetrics != pInfo2->inkMetrics || + pInfo1->allExist != pInfo2->allExist || + pInfo1->drawDirection != pInfo2->drawDirection || + pInfo1->cachable != pInfo2->cachable || + pInfo1->anamorphic != pInfo2->anamorphic || + pInfo1->maxOverlap != pInfo2->maxOverlap || + pInfo1->fontAscent != pInfo2->fontAscent || + pInfo1->fontDescent != pInfo2->fontDescent || + pInfo1->nprops != pInfo2->nprops) + return FALSE; + +#define MATCH(xci1, xci2) \ + (((xci1).leftSideBearing == (xci2).leftSideBearing) && \ + ((xci1).rightSideBearing == (xci2).rightSideBearing) && \ + ((xci1).characterWidth == (xci2).characterWidth) && \ + ((xci1).ascent == (xci2).ascent) && \ + ((xci1).descent == (xci2).descent) && \ + ((xci1).attributes == (xci2).attributes)) + + if (!MATCH(pInfo1->maxbounds, pInfo2->maxbounds) || + !MATCH(pInfo1->minbounds, pInfo2->minbounds) || + !MATCH(pInfo1->ink_maxbounds, pInfo2->ink_maxbounds) || + !MATCH(pInfo1->ink_minbounds, pInfo2->ink_minbounds)) + return FALSE; + +#undef MATCH + + for (i = 0; i < pInfo1->nprops; i++) + if (pInfo1->isStringProp[i] != + pInfo2->isStringProp[i] || + pInfo1->props[i].name != + pInfo2->props[i].name || + pInfo1->props[i].value != + pInfo2->props[i].value) + { + return FALSE; + } + return TRUE; +} + +static int +fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) +{ + FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; + FSFpePtr conn = (FSFpePtr) fpe->private; + fsQueryXInfoReply *rep; + char *buf; + fsPropInfo *pi; + fsPropOffset *po; + pointer pd; + FontInfoPtr pInfo; + FontInfoRec tempInfo; + int err; + int ret; + + rep = (fsQueryXInfoReply *) fs_get_reply (conn, &ret); + if (!rep || rep->type == FS_Error) + { + if (ret == FSIO_BLOCK) + return StillWorking; + if (rep) + _fs_done_read (conn, rep->length << 2); + fs_cleanup_bfont (bfont); + return BadFontName; + } + + /* If this is a reopen, accumulate the query info into a dummy + font and compare to our original data. */ + if (bfont->flags & FontReopen) + pInfo = &tempInfo; + else + pInfo = &bfont->pfont->info; + + buf = (char *) rep; + buf += SIZEOF(fsQueryXInfoReply); + + /* move the data over */ + fsUnpack_XFontInfoHeader(rep, pInfo); + + /* compute accelerators */ + _fs_init_fontinfo(conn, pInfo); + + /* Compute offsets into the reply */ + pi = (fsPropInfo *) buf; + buf += SIZEOF (fsPropInfo); + + po = (fsPropOffset *) buf; + buf += pi->num_offsets * SIZEOF(fsPropOffset); + + pd = (pointer) buf; + buf += pi->data_len; + + /* convert the properties and step over the reply */ + ret = _fs_convert_props(pi, po, pd, pInfo); + _fs_done_read (conn, rep->length << 2); + + if (ret == -1) + { + fs_cleanup_bfont (bfont); + return AllocError; + } + + if (bfont->flags & FontReopen) + { + /* We're reopening a font that we lost because of a downed + connection. In the interest of avoiding corruption from + opening a different font than the old one (we already have + its metrics, extents, and probably some of its glyphs), + verify that the metrics and properties all match. */ + + if (fs_fonts_match (pInfo, &bfont->pfont->info)) + { + err = Successful; + bfont->state = FS_DONE_REPLY; + } + else + { + fs_cleanup_bfont (bfont); + err = BadFontName; + } + _fs_free_props (pInfo); + + return err; + } + + /* + * Ask for terminal format fonts if possible + */ + if (bfont->pfont->info.terminalFont) + bfont->format = ((bfont->format & ~ (BitmapFormatImageRectMask)) | + BitmapFormatImageRectMax); + + /* + * Figure out if the whole font should get loaded right now. + */ + if (glyphCachingMode == CACHING_OFF || + (glyphCachingMode == CACHE_16_BIT_GLYPHS + && !bfont->pfont->info.lastRow)) + { + bfont->flags |= FontLoadAll; + } + + /* + * Ready to send the query bitmaps; the terminal font bit has + * been computed and glyphCaching has been considered + */ + if (bfont->flags & FontLoadBitmaps) + { + fs_send_query_bitmaps (fpe, blockrec); + _fs_flush (conn); + } + + bfont->state = FS_EXTENT_REPLY; + + /* + * Reset the blockrec for the next reply + */ + blockrec->sequenceNumber = bfont->queryExtentsSequence; + conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; + + return StillWorking; +} + +static int +fs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; + FSFontDataPtr fsd = (FSFontDataPtr) bfont->pfont->fpePrivate; + FSFontPtr fsfont = (FSFontPtr) bfont->pfont->fontPrivate; + fsQueryXExtents16Reply *rep; + char *buf; + int i; + int numExtents; + int numInfos; + int ret; + Bool haveInk = FALSE; /* need separate ink metrics? */ + CharInfoPtr ci, pCI; + char *fsci; + fsXCharInfo fscilocal; + FontInfoRec *fi = &bfont->pfont->info; + + rep = (fsQueryXExtents16Reply *) fs_get_reply (conn, &ret); + if (!rep || rep->type == FS_Error) + { + if (ret == FSIO_BLOCK) + return StillWorking; + if (rep) + _fs_done_read (conn, rep->length << 2); + fs_cleanup_bfont (bfont); + return BadFontName; + } + + /* move the data over */ + /* need separate inkMetrics for fixed font server protocol version */ + numExtents = rep->num_extents; + numInfos = numExtents; + if (bfont->pfont->info.terminalFont && conn->fsMajorVersion > 1) + { + numInfos *= 2; + haveInk = TRUE; + } + ci = pCI = malloc(sizeof(CharInfoRec) * numInfos); + + if (!pCI) + { + _fs_done_read (conn, rep->length << 2); + fs_cleanup_bfont(bfont); + return AllocError; + } + fsfont->encoding = pCI; + if (haveInk) + fsfont->inkMetrics = pCI + numExtents; + else + fsfont->inkMetrics = pCI; + + buf = (char *) rep; + buf += SIZEOF (fsQueryXExtents16Reply); + fsci = buf; + + fsd->glyphs_to_get = 0; + ci = fsfont->inkMetrics; + for (i = 0; i < numExtents; i++) + { + memcpy(&fscilocal, fsci, SIZEOF(fsXCharInfo)); /* align it */ + _fs_convert_char_info(&fscilocal, &ci->metrics); + /* Bounds check. */ + if (ci->metrics.ascent > fi->maxbounds.ascent) + { + ErrorF("fserve: warning: %s %s ascent (%d) > maxascent (%d)\n", + fpe->name, fsd->name, + ci->metrics.ascent, fi->maxbounds.ascent); + ci->metrics.ascent = fi->maxbounds.ascent; + } + if (ci->metrics.descent > fi->maxbounds.descent) + { + ErrorF("fserve: warning: %s %s descent (%d) > maxdescent (%d)\n", + fpe->name, fsd->name, + ci->metrics.descent, fi->maxbounds.descent); + ci->metrics.descent = fi->maxbounds.descent; + } + fsci = fsci + SIZEOF(fsXCharInfo); + /* Initialize the bits field for later glyph-caching use */ + if (NONZEROMETRICS(&ci->metrics)) + { + if (!haveInk && + (ci->metrics.leftSideBearing == ci->metrics.rightSideBearing || + ci->metrics.ascent == -ci->metrics.descent)) + pCI[i].bits = &_fs_glyph_zero_length; + else + { + pCI[i].bits = &_fs_glyph_undefined; + fsd->glyphs_to_get++; + } + } + else + pCI[i].bits = (char *)0; + ci++; + } + + /* Done with reply */ + _fs_done_read (conn, rep->length << 2); + + /* build bitmap metrics, ImageRectMax style */ + if (haveInk) + { + CharInfoPtr ii; + + ci = fsfont->encoding; + ii = fsfont->inkMetrics; + for (i = 0; i < numExtents; i++, ci++, ii++) + { + if (NONZEROMETRICS(&ii->metrics)) + { + ci->metrics.leftSideBearing = FONT_MIN_LEFT(fi); + ci->metrics.rightSideBearing = FONT_MAX_RIGHT(fi); + ci->metrics.ascent = FONT_MAX_ASCENT(fi); + ci->metrics.descent = FONT_MAX_DESCENT(fi); + ci->metrics.characterWidth = FONT_MAX_WIDTH(fi); + ci->metrics.attributes = ii->metrics.attributes; + } + else + { + ci->metrics = ii->metrics; + } + /* Bounds check. */ + if (ci->metrics.ascent > fi->maxbounds.ascent) + { + ErrorF("fserve: warning: %s %s ascent (%d) " + "> maxascent (%d)\n", + fpe->name, fsd->name, + ci->metrics.ascent, fi->maxbounds.ascent); + ci->metrics.ascent = fi->maxbounds.ascent; + } + if (ci->metrics.descent > fi->maxbounds.descent) + { + ErrorF("fserve: warning: %s %s descent (%d) " + "> maxdescent (%d)\n", + fpe->name, fsd->name, + ci->metrics.descent, fi->maxbounds.descent); + ci->metrics.descent = fi->maxbounds.descent; + } + } + } + { + unsigned int r, c, numCols, firstCol; + + firstCol = bfont->pfont->info.firstCol; + numCols = bfont->pfont->info.lastCol - firstCol + 1; + c = bfont->pfont->info.defaultCh; + fsfont->pDefault = 0; + if (bfont->pfont->info.lastRow) + { + r = c >> 8; + r -= bfont->pfont->info.firstRow; + c &= 0xff; + c -= firstCol; + if (r < bfont->pfont->info.lastRow-bfont->pfont->info.firstRow+1 && + c < numCols) + fsfont->pDefault = &pCI[r * numCols + c]; + } + else + { + c -= firstCol; + if (c < numCols) + fsfont->pDefault = &pCI[c]; + } + } + bfont->state = FS_GLYPHS_REPLY; + + if (bfont->flags & FontLoadBitmaps) + { + /* + * Reset the blockrec for the next reply + */ + blockrec->sequenceNumber = bfont->queryBitmapsSequence; + conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; + return StillWorking; + } + return Successful; +} + +#ifdef DEBUG +static char *fs_open_states[] = { + "OPEN_REPLY ", + "INFO_REPLY ", + "EXTENT_REPLY", + "GLYPHS_REPLY", + "DONE_REPLY ", + "DEPENDING ", +}; +#endif + +static int +fs_do_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec) +{ + FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; + int err; + +#ifdef DEBUG + fprintf (stderr, "fs_do_open_font state %s %s\n", + fs_open_states[bfont->state], + ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name); +#endif + err = BadFontName; + switch (bfont->state) { + case FS_OPEN_REPLY: + err = fs_read_open_font(fpe, blockrec); + if (err != StillWorking) { /* already loaded, or error */ + /* if font's already loaded, massage error code */ + switch (bfont->state) { + case FS_DONE_REPLY: + err = Successful; + break; + case FS_DEPENDING: + err = StillWorking; + break; + } + } + break; + case FS_INFO_REPLY: + err = fs_read_query_info(fpe, blockrec); + break; + case FS_EXTENT_REPLY: + err = fs_read_extent_info(fpe, blockrec); + break; + case FS_GLYPHS_REPLY: + if (bfont->flags & FontLoadBitmaps) + err = fs_read_glyphs(fpe, blockrec); + break; + case FS_DEPENDING: /* can't happen */ + default: + break; + } +#ifdef DEBUG + fprintf (stderr, "fs_do_open_font err %d\n", err); +#endif + if (err != StillWorking) + { + bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */ + while ((blockrec = blockrec->depending)) + { + bfont = (FSBlockedFontPtr) blockrec->data; + bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */ + } + } + return err; +} + +void +_fs_mark_block (FSFpePtr conn, CARD32 mask) +{ + conn->blockState |= mask; + fs_blockState |= mask; +} + +void +_fs_unmark_block (FSFpePtr conn, CARD32 mask) +{ + FSFpePtr c; + + if (conn->blockState & mask) + { + conn->blockState &= ~mask; + fs_blockState = 0; + for (c = fs_fpes; c; c = c->next) + fs_blockState |= c->blockState; + } +} + +/* ARGSUSED */ +static void +fs_block_handler(pointer data, OSTimePtr wt, pointer LastSelectMask) +{ + static struct timeval block_timeout; + CARD32 now, earliest, wakeup; + int soonest; + FSFpePtr conn; + + XFD_ORSET((fd_set *)LastSelectMask, (fd_set *)LastSelectMask, + &_fs_fd_mask); + /* + * Flush all pending output + */ + if (fs_blockState & FS_PENDING_WRITE) + for (conn = fs_fpes; conn; conn = conn->next) + if (conn->blockState & FS_PENDING_WRITE) + _fs_flush (conn); + /* + * Check for any fpe with a complete reply, set sleep time to zero + */ + if (fs_blockState & FS_COMPLETE_REPLY) + { + block_timeout.tv_sec = 0; + block_timeout.tv_usec = 0; + if (*wt == NULL) + *wt = &block_timeout; + else + **wt = block_timeout; + } + /* + * Walk through fpe list computing sleep time + */ + else if (fs_blockState & (FS_BROKEN_WRITE| + FS_BROKEN_CONNECTION| + FS_PENDING_REPLY| + FS_RECONNECTING)) + { + now = GetTimeInMillis (); + earliest = now + 10000000; + for (conn = fs_fpes; conn; conn = conn->next) + { + if (conn->blockState & FS_RECONNECTING) + { + wakeup = conn->blockedConnectTime; + if (TimeCmp (wakeup, <, earliest)) + earliest = wakeup; + } + if (conn->blockState & FS_BROKEN_CONNECTION) + { + wakeup = conn->brokenConnectionTime; + if (TimeCmp (wakeup, <, earliest)) + earliest = wakeup; + } + if (conn->blockState & FS_BROKEN_WRITE) + { + wakeup = conn->brokenWriteTime; + if (TimeCmp (wakeup, <, earliest)) + earliest = wakeup; + } + if (conn->blockState & FS_PENDING_REPLY) + { + wakeup = conn->blockedReplyTime; + if (TimeCmp (wakeup, <, earliest)) + earliest = wakeup; + } + } + soonest = earliest - now; + if (soonest < 0) + soonest = 0; + block_timeout.tv_sec = soonest / 1000; + block_timeout.tv_usec = (soonest % 1000) * 1000; + if (*wt == NULL) + *wt = &block_timeout; + else if (soonest < (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000) + **wt = block_timeout; + } +} + +static void +fs_handle_unexpected(FSFpePtr conn, fsGenericReply *rep) +{ + if (rep->type == FS_Event && rep->data1 == KeepAlive) + { + fsNoopReq req; + + /* ping it back */ + req.reqType = FS_Noop; + req.length = SIZEOF(fsNoopReq) >> 2; + _fs_add_req_log(conn, FS_Noop); + _fs_write(conn, (char *) &req, SIZEOF(fsNoopReq)); + } + /* this should suck up unexpected replies and events */ + _fs_done_read (conn, rep->length << 2); +} + +static void +fs_read_reply (FontPathElementPtr fpe, pointer client) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockDataPtr blockrec; + int ret; + int err; + fsGenericReply *rep; + + if ((rep = fs_get_reply (conn, &ret))) + { + _fs_add_rep_log (conn, rep); + for (blockrec = conn->blockedRequests; + blockrec; + blockrec = blockrec->next) + { + if (blockrec->sequenceNumber == rep->sequenceNumber) + break; + } + err = Successful; + if (!blockrec) + { + fs_handle_unexpected(conn, rep); + } + else + { + /* + * go read it, and if we're done, + * wake up the appropriate client + */ + switch (blockrec->type) { + case FS_OPEN_FONT: + blockrec->errcode = fs_do_open_font(fpe, blockrec); + break; + case FS_LOAD_GLYPHS: + blockrec->errcode = fs_read_glyphs(fpe, blockrec); + break; + case FS_LIST_FONTS: + blockrec->errcode = fs_read_list(fpe, blockrec); + break; + case FS_LIST_WITH_INFO: + blockrec->errcode = fs_read_list_info(fpe, blockrec); + break; + default: + break; + } + err = blockrec->errcode; + if (err != StillWorking) + { + while (blockrec) + { + blockrec->errcode = err; + if (client != blockrec->client) + ClientSignal(blockrec->client); + blockrec = blockrec->depending; + } + _fs_unmark_block (conn, FS_PENDING_REPLY); + } + } + if (fs_reply_ready (conn)) + _fs_mark_block (conn, FS_COMPLETE_REPLY); + else + _fs_unmark_block (conn, FS_COMPLETE_REPLY); + } +} + +static int +fs_wakeup(FontPathElementPtr fpe, unsigned long *mask) +{ + fd_set *LastSelectMask = (fd_set *) mask; + FSFpePtr conn = (FSFpePtr) fpe->private; + + /* + * Don't continue if the fd is -1 (which will be true when the + * font server terminates + */ + if ((conn->blockState & FS_RECONNECTING)) + _fs_check_reconnect (conn); + else if ((conn->blockState & FS_COMPLETE_REPLY) || + (conn->fs_fd != -1 && FD_ISSET(conn->fs_fd, LastSelectMask))) + fs_read_reply (fpe, 0); + if (conn->blockState & (FS_PENDING_REPLY|FS_BROKEN_CONNECTION|FS_BROKEN_WRITE)) + _fs_do_blocked (conn); +#ifdef DEBUG + { + FSBlockDataPtr blockrec; + FSBlockedFontPtr bfont; + FSBlockedListPtr blist; + static CARD32 lastState; + static FSBlockDataPtr lastBlock; + + if (conn->blockState || conn->blockedRequests || lastState || lastBlock) + { + fprintf (stderr, " Block State 0x%x\n", (int) conn->blockState); + lastState = conn->blockState; + lastBlock = conn->blockedRequests; + } + for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) + { + switch (blockrec->type) { + case FS_OPEN_FONT: + bfont = (FSBlockedFontPtr) blockrec->data; + fprintf (stderr, " Blocked font errcode %d sequence %d state %s %s\n", + blockrec->errcode, + blockrec->sequenceNumber, + fs_open_states[bfont->state], + bfont->pfont ? + ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name : + ""); + break; + case FS_LIST_FONTS: + blist = (FSBlockedListPtr) blockrec->data; + fprintf (stderr, " Blocked list errcode %d sequence %d\n", + blockrec->errcode, blockrec->sequenceNumber); + break; + default: + fprintf (stderr, " Blocked type %d errcode %d sequence %d\n", + blockrec->type, + blockrec->errcode, + blockrec->sequenceNumber); + break; + } + } + } +#endif + return FALSE; +} + +/* + * Notice a dead connection and prepare for reconnect + */ + +void +_fs_connection_died(FSFpePtr conn) +{ + if (conn->blockState & FS_BROKEN_CONNECTION) + return; + fs_close_conn(conn); + conn->brokenConnectionTime = GetTimeInMillis (); + _fs_mark_block (conn, FS_BROKEN_CONNECTION); + _fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE|FS_RECONNECTING); +} + +/* + * Signal clients that the connection has come back up + */ +static int +_fs_restart_connection(FSFpePtr conn) +{ + FSBlockDataPtr block; + + _fs_unmark_block (conn, FS_GIVE_UP); + while ((block = (FSBlockDataPtr) conn->blockedRequests)) + { + if (block->errcode == StillWorking) + { + ClientSignal(block->client); + fs_abort_blockrec(conn, block); + } + } + return TRUE; +} + +/* + * Declare this font server connection useless + */ +static void +_fs_giveup (FSFpePtr conn) +{ + FSBlockDataPtr block; + + if (conn->blockState & FS_GIVE_UP) + return; +#ifdef DEBUG + fprintf (stderr, "give up on FS \"%s\"\n", conn->servername); +#endif + _fs_mark_block (conn, FS_GIVE_UP); + while ((block = (FSBlockDataPtr) conn->blockedRequests)) + { + if (block->errcode == StillWorking) + { + ClientSignal (block->client); + fs_abort_blockrec (conn, block); + } + } + if (conn->fs_fd >= 0) + _fs_connection_died (conn); +} + +static void +_fs_do_blocked (FSFpePtr conn) +{ + CARD32 now; + + now = GetTimeInMillis (); + if ((conn->blockState & FS_PENDING_REPLY) && + TimeCmp (conn->blockedReplyTime, <=, now)) + { + _fs_giveup (conn); + } + else + { + if (conn->blockState & FS_BROKEN_CONNECTION) + { + /* Try to reconnect broken connections */ + if (TimeCmp (conn->brokenConnectionTime, <=, now)) + _fs_start_reconnect (conn); + } + else if (conn->blockState & FS_BROKEN_WRITE) + { + /* Try to flush blocked connections */ + if (TimeCmp (conn->brokenWriteTime, <=, now)) + _fs_flush (conn); + } + } +} + +/* + * sends the actual request out + */ +/* ARGSUSED */ +static int +fs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags, + char *name, int namelen, + fsBitmapFormat format, fsBitmapFormatMask fmask, + XID id, FontPtr *ppfont) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FontPtr font; + FSBlockDataPtr blockrec = NULL; + FSBlockedFontPtr bfont; + FSFontDataPtr fsd; + fsOpenBitmapFontReq openreq; + fsQueryXInfoReq inforeq; + fsQueryXExtents16Req extreq; + int err; + unsigned char buf[1024]; + + if (conn->blockState & FS_GIVE_UP) + return BadFontName; + + if (namelen <= 0 || namelen > sizeof (buf) - 1) + return BadFontName; + + /* + * Get the font structure put together, either by reusing + * the existing one or creating a new one + */ + if (flags & FontReopen) + { + Atom nameatom, fn = None; + int i; + + font = *ppfont; + fsd = (FSFontDataPtr)font->fpePrivate; + /* This is an attempt to reopen a font. Did the font have a + NAME property? */ + if ((nameatom = MakeAtom("FONT", 4, 0)) != None) + { + for (i = 0; i < font->info.nprops; i++) + if (font->info.props[i].name == nameatom && + font->info.isStringProp[i]) + { + fn = font->info.props[i].value; + break; + } + } + if (fn == None || !(name = NameForAtom(fn))) + { + name = fsd->name; + namelen = fsd->namelen; + } + else + namelen = strlen(name); + } + else + { + font = fs_create_font (fpe, name, namelen, format, fmask); + if (!font) + return AllocError; + + fsd = (FSFontDataPtr)font->fpePrivate; + } + + /* make a new block record, and add it to the end of the list */ + blockrec = fs_new_block_rec(font->fpe, client, FS_OPEN_FONT); + if (!blockrec) + { + if (!(flags & FontReopen)) + (*font->unload_font) (font); + return AllocError; + } + + /* + * Must check this before generating any protocol, otherwise we'll + * mess up a reconnect in progress + */ + if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) + { + _fs_pending_reply (conn); + return Suspended; + } + + fsd->generation = conn->generation; + + bfont = (FSBlockedFontPtr) blockrec->data; + bfont->fontid = fsd->fontid; + bfont->pfont = font; + bfont->state = FS_OPEN_REPLY; + bfont->flags = flags; + bfont->format = fsd->format; + bfont->clients_depending = (FSClientsDependingPtr)0; + bfont->freeFont = (flags & FontReopen) == 0; + + _fs_client_access (conn, client, (flags & FontOpenSync) != 0); + _fs_client_resolution(conn); + + /* do an FS_OpenFont, FS_QueryXInfo and FS_QueryXExtents */ + buf[0] = (unsigned char) namelen; + memcpy(&buf[1], name, namelen); + openreq.reqType = FS_OpenBitmapFont; + openreq.pad = 0; + openreq.fid = fsd->fontid; + openreq.format_hint = fsd->format; + openreq.format_mask = fsd->fmask; + openreq.length = (SIZEOF(fsOpenBitmapFontReq) + namelen + 4) >> 2; + + _fs_add_req_log(conn, FS_OpenBitmapFont); + _fs_write(conn, (char *) &openreq, SIZEOF(fsOpenBitmapFontReq)); + _fs_write_pad(conn, (char *) buf, namelen + 1); + + blockrec->sequenceNumber = conn->current_seq; + + inforeq.reqType = FS_QueryXInfo; + inforeq.pad = 0; + inforeq.id = fsd->fontid; + inforeq.length = SIZEOF(fsQueryXInfoReq) >> 2; + + bfont->queryInfoSequence = conn->current_seq + 1; + + _fs_add_req_log(conn, FS_QueryXInfo); + _fs_write(conn, (char *) &inforeq, SIZEOF(fsQueryXInfoReq)); + + if (!(bfont->flags & FontReopen)) + { + extreq.reqType = FS_QueryXExtents16; + extreq.range = fsTrue; + extreq.fid = fsd->fontid; + extreq.num_ranges = 0; + extreq.length = SIZEOF(fsQueryXExtents16Req) >> 2; + + bfont->queryExtentsSequence = conn->current_seq + 1; + + _fs_add_req_log(conn, FS_QueryXExtents16); + _fs_write(conn, (char *) &extreq, SIZEOF(fsQueryXExtents16Req)); + } + +#ifdef NCD + if (configData.ExtendedFontDiags) + { + memcpy(buf, name, MIN(256, namelen)); + buf[MIN(256, namelen)] = '\0'; + printf("Requesting font \"%s\" from font server \"%s\"\n", + buf, font->fpe->name); + } +#endif + _fs_prepare_for_reply (conn); + + err = blockrec->errcode; + if (bfont->flags & FontOpenSync) + { + while (blockrec->errcode == StillWorking) + { + if (fs_await_reply (conn) != FSIO_READY) + { + blockrec->errcode = BadFontName; + break; + } + fs_read_reply (font->fpe, client); + } + err = blockrec->errcode; + if (err == Successful) + *ppfont = bfont->pfont; + else + fs_cleanup_bfont (bfont); + bfont->freeFont = FALSE; + _fs_remove_block_rec (conn, blockrec); + } + return err == StillWorking ? Suspended : err; +} + +static void +fs_send_query_bitmaps(FontPathElementPtr fpe, FSBlockDataPtr blockrec) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; + fsQueryXBitmaps16Req bitreq; + + /* send the request */ + bitreq.reqType = FS_QueryXBitmaps16; + bitreq.fid = bfont->fontid; + bitreq.format = bfont->format; + bitreq.range = TRUE; + bitreq.length = SIZEOF(fsQueryXBitmaps16Req) >> 2; + bitreq.num_ranges = 0; + + bfont->queryBitmapsSequence = conn->current_seq + 1; + + _fs_add_req_log(conn, FS_QueryXBitmaps16); + _fs_write(conn, (char *) &bitreq, SIZEOF(fsQueryXBitmaps16Req)); +} + +/* ARGSUSED */ +static int +fs_open_font(pointer client, FontPathElementPtr fpe, Mask flags, + char *name, int namelen, + fsBitmapFormat format, fsBitmapFormatMask fmask, + XID id, FontPtr *ppfont, + char **alias, FontPtr non_cachable_font) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockDataPtr blockrec; + FSBlockedFontPtr bfont; + int err; + + /* libfont interface expects ImageRectMin glyphs */ + format = (format & ~BitmapFormatImageRectMask) | BitmapFormatImageRectMin; + + *alias = (char *) 0; + for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) + { + if (blockrec->type == FS_OPEN_FONT && blockrec->client == client) + { + err = blockrec->errcode; + if (err == StillWorking) + return Suspended; + + bfont = (FSBlockedFontPtr) blockrec->data; + if (err == Successful) + *ppfont = bfont->pfont; + else + fs_cleanup_bfont (bfont); + _fs_remove_block_rec (conn, blockrec); + return err; + } + } + return fs_send_open_font(client, fpe, flags, name, namelen, format, fmask, + id, ppfont); +} + +/* ARGSUSED */ +static int +fs_send_close_font(FontPathElementPtr fpe, Font id) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + fsCloseReq req; + + if (conn->blockState & FS_GIVE_UP) + return Successful; + /* tell the font server to close the font */ + req.reqType = FS_CloseFont; + req.pad = 0; + req.length = SIZEOF(fsCloseReq) >> 2; + req.id = id; + _fs_add_req_log(conn, FS_CloseFont); + _fs_write(conn, (char *) &req, SIZEOF(fsCloseReq)); + + return Successful; +} + +/* ARGSUSED */ +static void +fs_close_font(FontPathElementPtr fpe, FontPtr pfont) +{ + FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate; + FSFpePtr conn = (FSFpePtr) fpe->private; + + if (conn->generation == fsd->generation) + fs_send_close_font(fpe, fsd->fontid); + +#ifdef DEBUG + { + FSBlockDataPtr blockrec; + FSBlockedFontPtr bfont; + + for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) + { + if (blockrec->type == FS_OPEN_FONT) + { + bfont = (FSBlockedFontPtr) blockrec->data; + if (bfont->pfont == pfont) + fprintf (stderr, "closing font which hasn't been opened\n"); + } + } + } +#endif + (*pfont->unload_font) (pfont); +} + +static int +fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec) +{ + FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr) blockrec->data; + FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; + FSFpePtr conn = (FSFpePtr) fpe->private; + FontPtr pfont = bglyph->pfont; + /* works for either blocked font + or glyph rec... pfont is at + the very beginning of both + blockrec->data structures */ + FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate); + FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate; + FontInfoPtr pfi = &pfont->info; + fsQueryXBitmaps16Reply *rep; + char *buf; + fsOffset32 *ppbits; + fsOffset32 local_off; + char *off_adr; + pointer pbitmaps; + char *bits, *allbits; +#ifdef DEBUG + char *origallbits; +#endif + int i, + err; + int nranges = 0; + int ret; + fsRange *nextrange = 0; + unsigned long minchar, maxchar; + + rep = (fsQueryXBitmaps16Reply *) fs_get_reply (conn, &ret); + if (!rep || rep->type == FS_Error) + { + if (ret == FSIO_BLOCK) + return StillWorking; + if (rep) + _fs_done_read (conn, rep->length << 2); + err = AllocError; + goto bail; + } + + buf = (char *) rep; + buf += SIZEOF (fsQueryXBitmaps16Reply); + + ppbits = (fsOffset32 *) buf; + buf += SIZEOF (fsOffset32) * (rep->num_chars); + + pbitmaps = (pointer ) buf; + + if (blockrec->type == FS_LOAD_GLYPHS) + { + nranges = bglyph->num_expected_ranges; + nextrange = bglyph->expected_ranges; + } + + /* place the incoming glyphs */ + if (nranges) + { + /* We're operating under the assumption that the ranges + requested in the LoadGlyphs call were all legal for this + font, and that individual ranges do not cover multiple + rows... fs_build_range() is designed to ensure this. */ + minchar = (nextrange->min_char_high - pfi->firstRow) * + (pfi->lastCol - pfi->firstCol + 1) + + nextrange->min_char_low - pfi->firstCol; + maxchar = (nextrange->max_char_high - pfi->firstRow) * + (pfi->lastCol - pfi->firstCol + 1) + + nextrange->max_char_low - pfi->firstCol; + nextrange++; + } + else + { + minchar = 0; + maxchar = rep->num_chars; + } + + off_adr = (char *)ppbits; + + allbits = fs_alloc_glyphs (pfont, rep->nbytes); + + if (!allbits) + { + err = AllocError; + goto bail; + } + +#ifdef DEBUG + origallbits = allbits; + fprintf (stderr, "Reading %d glyphs in %d bytes for %s\n", + (int) rep->num_chars, (int) rep->nbytes, fsd->name); +#endif + + for (i = 0; i < rep->num_chars; i++) + { + memcpy(&local_off, off_adr, SIZEOF(fsOffset32)); /* align it */ + if (blockrec->type == FS_OPEN_FONT || + fsdata->encoding[minchar].bits == &_fs_glyph_requested) + { + /* + * Broken X font server returns bits for missing characters + * when font is padded + */ + if (NONZEROMETRICS(&fsdata->encoding[minchar].metrics)) + { + if (local_off.length) + { + bits = allbits; + allbits += local_off.length; + memcpy(bits, (char *)pbitmaps + local_off.position, + local_off.length); + } + else + bits = &_fs_glyph_zero_length; + } + else + bits = 0; + if (fsdata->encoding[minchar].bits == &_fs_glyph_requested) + fsd->glyphs_to_get--; + fsdata->encoding[minchar].bits = bits; + } + if (minchar++ == maxchar) + { + if (!--nranges) break; + minchar = (nextrange->min_char_high - pfi->firstRow) * + (pfi->lastCol - pfi->firstCol + 1) + + nextrange->min_char_low - pfi->firstCol; + maxchar = (nextrange->max_char_high - pfi->firstRow) * + (pfi->lastCol - pfi->firstCol + 1) + + nextrange->max_char_low - pfi->firstCol; + nextrange++; + } + off_adr += SIZEOF(fsOffset32); + } +#ifdef DEBUG + fprintf (stderr, "Used %d bytes instead of %d\n", + (int) (allbits - origallbits), (int) rep->nbytes); +#endif + + if (blockrec->type == FS_OPEN_FONT) + { + fsd->glyphs_to_get = 0; + bfont->state = FS_DONE_REPLY; + } + err = Successful; + +bail: + _fs_done_read (conn, rep->length << 2); + return err; +} + +static int +fs_send_load_glyphs(pointer client, FontPtr pfont, + int nranges, fsRange *ranges) +{ + FontPathElementPtr fpe = pfont->fpe; + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockedGlyphPtr blockedglyph; + fsQueryXBitmaps16Req req; + FSBlockDataPtr blockrec; + + if (conn->blockState & FS_GIVE_UP) + return BadCharRange; + + /* make a new block record, and add it to the end of the list */ + blockrec = fs_new_block_rec(fpe, client, FS_LOAD_GLYPHS); + if (!blockrec) + return AllocError; + blockedglyph = (FSBlockedGlyphPtr) blockrec->data; + blockedglyph->pfont = pfont; + blockedglyph->num_expected_ranges = nranges; + /* Assumption: it's our job to free ranges */ + blockedglyph->expected_ranges = ranges; + blockedglyph->clients_depending = (FSClientsDependingPtr)0; + + if (conn->blockState & (FS_BROKEN_CONNECTION|FS_RECONNECTING)) + { + _fs_pending_reply (conn); + return Suspended; + } + + /* send the request */ + req.reqType = FS_QueryXBitmaps16; + req.fid = ((FSFontDataPtr) pfont->fpePrivate)->fontid; + req.format = pfont->format; + if (pfont->info.terminalFont) + req.format = (req.format & ~(BitmapFormatImageRectMask)) | + BitmapFormatImageRectMax; + req.range = TRUE; + /* each range takes up 4 bytes */ + req.length = (SIZEOF(fsQueryXBitmaps16Req) >> 2) + nranges; + req.num_ranges = nranges * 2; /* protocol wants count of fsChar2bs */ + _fs_add_req_log(conn, FS_QueryXBitmaps16); + _fs_write(conn, (char *) &req, SIZEOF(fsQueryXBitmaps16Req)); + + blockrec->sequenceNumber = conn->current_seq; + + /* Send ranges to the server... pack into a char array by hand + to avoid structure-packing portability problems and to + handle swapping for version1 protocol */ + if (nranges) + { +#define RANGE_BUFFER_SIZE 64 +#define RANGE_BUFFER_SIZE_MASK 63 + int i; + char range_buffer[RANGE_BUFFER_SIZE * 4]; + char *range_buffer_p; + + range_buffer_p = range_buffer; + for (i = 0; i < nranges;) + { + if (conn->fsMajorVersion > 1) + { + *range_buffer_p++ = ranges[i].min_char_high; + *range_buffer_p++ = ranges[i].min_char_low; + *range_buffer_p++ = ranges[i].max_char_high; + *range_buffer_p++ = ranges[i].max_char_low; + } + else + { + *range_buffer_p++ = ranges[i].min_char_low; + *range_buffer_p++ = ranges[i].min_char_high; + *range_buffer_p++ = ranges[i].max_char_low; + *range_buffer_p++ = ranges[i].max_char_high; + } + + if (!(++i & RANGE_BUFFER_SIZE_MASK)) + { + _fs_write(conn, range_buffer, RANGE_BUFFER_SIZE * 4); + range_buffer_p = range_buffer; + } + } + if (i &= RANGE_BUFFER_SIZE_MASK) + _fs_write(conn, range_buffer, i * 4); + } + + _fs_prepare_for_reply (conn); + return Suspended; +} + + +extern pointer serverClient; /* This could be any number that + doesn't conflict with existing + client values. */ + +static int +_fs_load_glyphs(pointer client, FontPtr pfont, Bool range_flag, + unsigned int nchars, int item_size, unsigned char *data) +{ + FSFpePtr conn = (FSFpePtr) pfont->fpe->private; + int nranges = 0; + fsRange *ranges = NULL; + int res; + FSBlockDataPtr blockrec; + FSBlockedGlyphPtr blockedglyph; + FSClientsDependingPtr *clients_depending = NULL; + int err; + + /* see if the result is already there */ + for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) + { + if (blockrec->type == FS_LOAD_GLYPHS) + { + blockedglyph = (FSBlockedGlyphPtr) blockrec->data; + if (blockedglyph->pfont == pfont) + { + /* Look for this request */ + if (blockrec->client == client) + { + err = blockrec->errcode; + if (err == StillWorking) + return Suspended; + _fs_signal_clients_depending(&blockedglyph->clients_depending); + _fs_remove_block_rec(conn, blockrec); + return err; + } + /* We've found an existing LoadGlyphs blockrec for this + font but for another client. Rather than build a + blockrec for it now (which entails some complex + maintenance), we'll add it to a queue of clients to + be signalled when the existing LoadGlyphs is + completed. */ + clients_depending = &blockedglyph->clients_depending; + break; + } + } + else if (blockrec->type == FS_OPEN_FONT) + { + FSBlockedFontPtr bfont; + bfont = (FSBlockedFontPtr) blockrec->data; + if (bfont->pfont == pfont) + { + /* + * An OpenFont is pending for this font, this must + * be from a reopen attempt, so finish the open + * attempt and retry the LoadGlyphs + */ + if (blockrec->client == client) + { + err = blockrec->errcode; + if (err == StillWorking) + return Suspended; + + _fs_signal_clients_depending(&bfont->clients_depending); + _fs_remove_block_rec(conn, blockrec); + if (err != Successful) + return err; + break; + } + /* We've found an existing OpenFont blockrec for this + font but for another client. Rather than build a + blockrec for it now (which entails some complex + maintenance), we'll add it to a queue of clients to + be signalled when the existing OpenFont is + completed. */ + if (blockrec->errcode == StillWorking) + { + clients_depending = &bfont->clients_depending; + break; + } + } + } + } + + /* + * see if the desired glyphs already exist, and return Successful if they + * do, otherwise build up character range/character string + */ + res = fs_build_range(pfont, range_flag, nchars, item_size, data, + &nranges, &ranges); + + switch (res) + { + case AccessDone: + return Successful; + + case Successful: + break; + + default: + return res; + } + + /* + * If clients_depending is not null, this request must wait for + * some prior request(s) to complete. + */ + if (clients_depending) + { + /* Since we're not ready to send the load_glyphs request yet, + clean up the damage (if any) caused by the fs_build_range() + call. */ + if (nranges) + { + _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); + free(ranges); + } + return _fs_add_clients_depending(clients_depending, client); + } + + /* + * If fsd->generation != conn->generation, the font has been closed + * due to a lost connection. We will reopen it, which will result + * in one of three things happening: + * 1) The open will succeed and obtain the same font. Life + * is wonderful. + * 2) The open will fail. There is code above to recognize this + * and flunk the LoadGlyphs request. The client might not be + * thrilled. + * 3) Worst case: the open will succeed but the font we open will + * be different. The fs_read_query_info() procedure attempts + * to detect this by comparing the existing metrics and + * properties against those of the reopened font... if they + * don't match, we flunk the reopen, which eventually results + * in flunking the LoadGlyphs request. We could go a step + * further and compare the extents, but this should be + * sufficient. + */ + if (((FSFontDataPtr)pfont->fpePrivate)->generation != conn->generation) + { + /* Since we're not ready to send the load_glyphs request yet, + clean up the damage caused by the fs_build_range() call. */ + _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); + free(ranges); + + /* Now try to reopen the font. */ + return fs_send_open_font(client, pfont->fpe, + (Mask)FontReopen, (char *)0, 0, + (fsBitmapFormat)0, (fsBitmapFormatMask)0, + (XID)0, &pfont); + } + + return fs_send_load_glyphs(client, pfont, nranges, ranges); +} + +int +fs_load_all_glyphs(FontPtr pfont) +{ + int err; + FSFpePtr conn = (FSFpePtr) pfont->fpe->private; + + /* + * The purpose of this procedure is to load all glyphs in the event + * that we're dealing with someone who doesn't understand the finer + * points of glyph caching... it is called from _fs_get_glyphs() if + * the latter is called to get glyphs that have not yet been loaded. + * We assume that the caller will not know how to handle a return + * value of Suspended (usually the case for a GetGlyphs() caller), + * so this procedure hangs around, freezing the server, for the + * request to complete. This is an unpleasant kluge called to + * perform an unpleasant job that, we hope, will never be required. + */ + + while ((err = _fs_load_glyphs(serverClient, pfont, TRUE, 0, 0, NULL)) == + Suspended) + { + if (fs_await_reply (conn) != FSIO_READY) + { + /* Get rid of blockrec */ + fs_client_died(serverClient, pfont->fpe); + err = BadCharRange; + break; + } + fs_read_reply (pfont->fpe, serverClient); + } + return err; +} + +static int +fs_read_list(FontPathElementPtr fpe, FSBlockDataPtr blockrec) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockedListPtr blist = (FSBlockedListPtr) blockrec->data; + fsListFontsReply *rep; + char *data; + int length, + i, + ret; + int err; + + rep = (fsListFontsReply *) fs_get_reply (conn, &ret); + if (!rep || rep->type == FS_Error) + { + if (ret == FSIO_BLOCK) + return StillWorking; + if (rep) + _fs_done_read (conn, rep->length << 2); + return AllocError; + } + data = (char *) rep + SIZEOF (fsListFontsReply); + + err = Successful; + /* copy data into FontPathRecord */ + for (i = 0; i < rep->nFonts; i++) + { + length = *(unsigned char *)data++; + err = AddFontNamesName(blist->names, data, length); + if (err != Successful) + break; + data += length; + } + _fs_done_read (conn, rep->length << 2); + return err; +} + +static int +fs_send_list_fonts(pointer client, FontPathElementPtr fpe, char *pattern, + int patlen, int maxnames, FontNamesPtr newnames) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockDataPtr blockrec; + FSBlockedListPtr blockedlist; + fsListFontsReq req; + + if (conn->blockState & FS_GIVE_UP) + return BadFontName; + + /* make a new block record, and add it to the end of the list */ + blockrec = fs_new_block_rec(fpe, client, FS_LIST_FONTS); + if (!blockrec) + return AllocError; + blockedlist = (FSBlockedListPtr) blockrec->data; + blockedlist->names = newnames; + + if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) + { + _fs_pending_reply (conn); + return Suspended; + } + + _fs_client_access (conn, client, FALSE); + _fs_client_resolution(conn); + + /* send the request */ + req.reqType = FS_ListFonts; + req.pad = 0; + req.maxNames = maxnames; + req.nbytes = patlen; + req.length = (SIZEOF(fsListFontsReq) + patlen + 3) >> 2; + _fs_add_req_log(conn, FS_ListFonts); + _fs_write(conn, (char *) &req, SIZEOF(fsListFontsReq)); + _fs_write_pad(conn, (char *) pattern, patlen); + + blockrec->sequenceNumber = conn->current_seq; + +#ifdef NCD + if (configData.ExtendedFontDiags) { + char buf[256]; + + memcpy(buf, pattern, MIN(256, patlen)); + buf[MIN(256, patlen)] = '\0'; + printf("Listing fonts on pattern \"%s\" from font server \"%s\"\n", + buf, fpe->name); + } +#endif + + _fs_prepare_for_reply (conn); + return Suspended; +} + +static int +fs_list_fonts(pointer client, FontPathElementPtr fpe, + char *pattern, int patlen, int maxnames, FontNamesPtr newnames) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockDataPtr blockrec; + int err; + + /* see if the result is already there */ + for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) + { + if (blockrec->type == FS_LIST_FONTS && blockrec->client == client) + { + err = blockrec->errcode; + if (err == StillWorking) + return Suspended; + _fs_remove_block_rec(conn, blockrec); + return err; + } + } + + /* didn't find waiting record, so send a new one */ + return fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames); +} + +/* + * Read a single list info reply and restart for the next reply + */ +static int +fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) +{ + FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data; + fsListFontsWithXInfoReply *rep; + char *buf; + FSFpePtr conn = (FSFpePtr) fpe->private; + fsPropInfo *pi; + fsPropOffset *po; + pointer pd; + int ret; + int err; + + /* clean up anything from the last trip */ + _fs_free_props (&binfo->info); + + rep = (fsListFontsWithXInfoReply *) fs_get_reply (conn, &ret); + if (!rep || rep->type == FS_Error) + { + if (ret == FSIO_BLOCK) + return StillWorking; + binfo->status = FS_LFWI_FINISHED; + err = AllocError; + goto done; + } + /* + * Normal termination -- the list ends with a name of length 0 + */ + if (rep->nameLength == 0) + { +#ifdef DEBUG + fprintf (stderr, "fs_read_list_info done\n"); +#endif + binfo->status = FS_LFWI_FINISHED; + err = BadFontName; + goto done; + } + + buf = (char *) rep + SIZEOF (fsListFontsWithXInfoReply); + + /* + * The original FS implementation didn't match + * the spec, version 1 was respecified to match the FS. + * Version 2 matches the original intent + */ + if (conn->fsMajorVersion <= 1) + { + memcpy (binfo->name, buf, rep->nameLength); + buf += _fs_pad_length (rep->nameLength); + } + pi = (fsPropInfo *) buf; + buf += SIZEOF (fsPropInfo); + po = (fsPropOffset *) buf; + buf += pi->num_offsets * SIZEOF (fsPropOffset); + pd = (pointer) buf; + buf += pi->data_len; + if (conn->fsMajorVersion > 1) + { + memcpy (binfo->name, buf, rep->nameLength); + buf += _fs_pad_length (rep->nameLength); + } + +#ifdef DEBUG + binfo->name[rep->nameLength] = '\0'; + fprintf (stderr, "fs_read_list_info %s\n", binfo->name); +#endif + err = _fs_convert_lfwi_reply(conn, &binfo->info, rep, pi, po, pd); + if (err != Successful) + { + binfo->status = FS_LFWI_FINISHED; + goto done; + } + binfo->namelen = rep->nameLength; + binfo->remaining = rep->nReplies; + + binfo->status = FS_LFWI_REPLY; + + /* disable this font server until we've processed this response */ + _fs_unmark_block (conn, FS_COMPLETE_REPLY); + FD_CLR(conn->fs_fd, &_fs_fd_mask); +done: + _fs_done_read (conn, rep->length << 2); + return err; +} + +/* ARGSUSED */ +static int +fs_start_list_with_info(pointer client, FontPathElementPtr fpe, + char *pattern, int len, int maxnames, pointer *pdata) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockDataPtr blockrec; + FSBlockedListInfoPtr binfo; + fsListFontsWithXInfoReq req; + + if (conn->blockState & FS_GIVE_UP) + return BadFontName; + + /* make a new block record, and add it to the end of the list */ + blockrec = fs_new_block_rec(fpe, client, FS_LIST_WITH_INFO); + if (!blockrec) + return AllocError; + + binfo = (FSBlockedListInfoPtr) blockrec->data; + bzero((char *) binfo, sizeof(FSBlockedListInfoRec)); + binfo->status = FS_LFWI_WAITING; + + if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) + { + _fs_pending_reply (conn); + return Suspended; + } + + _fs_client_access (conn, client, FALSE); + _fs_client_resolution(conn); + + /* send the request */ + req.reqType = FS_ListFontsWithXInfo; + req.pad = 0; + req.maxNames = maxnames; + req.nbytes = len; + req.length = (SIZEOF(fsListFontsWithXInfoReq) + len + 3) >> 2; + _fs_add_req_log(conn, FS_ListFontsWithXInfo); + (void) _fs_write(conn, (char *) &req, SIZEOF(fsListFontsWithXInfoReq)); + (void) _fs_write_pad(conn, pattern, len); + + blockrec->sequenceNumber = conn->current_seq; + +#ifdef NCD + if (configData.ExtendedFontDiags) { + char buf[256]; + + memcpy(buf, pattern, MIN(256, len)); + buf[MIN(256, len)] = '\0'; + printf("Listing fonts with info on pattern \"%s\" from font server \"%s\"\n", + buf, fpe->name); + } +#endif + + _fs_prepare_for_reply (conn); + return Successful; +} + +/* ARGSUSED */ +static int +fs_next_list_with_info(pointer client, FontPathElementPtr fpe, + char **namep, int *namelenp, + FontInfoPtr *pFontInfo, int *numFonts, + pointer private) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockDataPtr blockrec; + FSBlockedListInfoPtr binfo; + int err; + + /* see if the result is already there */ + for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) + if (blockrec->type == FS_LIST_WITH_INFO && blockrec->client == client) + break; + + if (!blockrec) + { + /* The only good reason for not finding a blockrec would be if + disconnect/reconnect to the font server wiped it out and the + code that called us didn't do the right thing to create + another one. Under those circumstances, we need to return an + error to prevent that code from attempting to interpret the + information we don't return. */ + return BadFontName; + } + + binfo = (FSBlockedListInfoPtr) blockrec->data; + + if (binfo->status == FS_LFWI_WAITING) + return Suspended; + + *namep = binfo->name; + *namelenp = binfo->namelen; + *pFontInfo = &binfo->info; + *numFonts = binfo->remaining; + + /* Restart reply processing from this font server */ + FD_SET(conn->fs_fd, &_fs_fd_mask); + if (fs_reply_ready (conn)) + _fs_mark_block (conn, FS_COMPLETE_REPLY); + + err = blockrec->errcode; + switch (binfo->status) { + case FS_LFWI_FINISHED: + _fs_remove_block_rec(conn, blockrec); + break; + case FS_LFWI_REPLY: + binfo->status = FS_LFWI_WAITING; + blockrec->errcode = StillWorking; + conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; + _fs_mark_block (conn, FS_PENDING_REPLY); + break; + } + + return err; +} + +/* + * Called when client exits + */ + +static void +fs_client_died(pointer client, FontPathElementPtr fpe) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockDataPtr blockrec, + depending; + FSClientPtr *prev, cur; + fsFreeACReq freeac; + + for (prev = &conn->clients; (cur = *prev); prev = &cur->next) + { + if (cur->client == client) { + freeac.reqType = FS_FreeAC; + freeac.pad = 0; + freeac.id = cur->acid; + freeac.length = sizeof (fsFreeACReq) >> 2; + _fs_add_req_log(conn, FS_FreeAC); + _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq)); + *prev = cur->next; + free (cur); + break; + } + } + /* find a pending requests */ + for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) + if (blockrec->client == client) + break; + + if (!blockrec) + return; + + /* replace the client pointers in this block rec with the chained one */ + if ((depending = blockrec->depending)) + { + blockrec->client = depending->client; + blockrec->depending = depending->depending; + blockrec = depending; + } + fs_abort_blockrec(conn, blockrec); +} + +static void +_fs_client_access (FSFpePtr conn, pointer client, Bool sync) +{ + FSClientPtr *prev, cur; + fsCreateACReq crac; + fsSetAuthorizationReq setac; + char *authorizations; + int authlen; + Bool new_cur = FALSE; + char padding[4] = { 0, 0, 0, 0 }; + +#ifdef DEBUG + if (conn->blockState & (FS_RECONNECTING|FS_BROKEN_CONNECTION)) + { + fprintf (stderr, "Sending requests without a connection\n"); + } +#endif + for (prev = &conn->clients; (cur = *prev); prev = &cur->next) + { + if (cur->client == client) + { + if (prev != &conn->clients) + { + *prev = cur->next; + cur->next = conn->clients; + conn->clients = cur; + } + break; + } + } + if (!cur) + { + cur = malloc (sizeof (FSClientRec)); + if (!cur) + return; + cur->client = client; + cur->next = conn->clients; + conn->clients = cur; + cur->acid = GetNewFontClientID (); + new_cur = TRUE; + } + if (new_cur || cur->auth_generation != client_auth_generation(client)) + { + if (!new_cur) + { + fsFreeACReq freeac; + freeac.reqType = FS_FreeAC; + freeac.pad = 0; + freeac.id = cur->acid; + freeac.length = sizeof (fsFreeACReq) >> 2; + _fs_add_req_log(conn, FS_FreeAC); + _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq)); + } + crac.reqType = FS_CreateAC; + crac.num_auths = set_font_authorizations(&authorizations, &authlen, + client); + /* Work around bug in xfs versions up through modular release 1.0.8 + which rejects CreateAC packets with num_auths = 0 & authlen < 4 */ + if (crac.num_auths == 0) { + authorizations = padding; + authlen = 4; + } else { + authlen = (authlen + 3) & ~0x3; + } + crac.length = (sizeof (fsCreateACReq) + authlen) >> 2; + crac.acid = cur->acid; + _fs_add_req_log(conn, FS_CreateAC); + _fs_write(conn, (char *) &crac, sizeof (fsCreateACReq)); + _fs_write(conn, authorizations, authlen); + /* ignore reply; we don't even care about it */ + conn->curacid = 0; + cur->auth_generation = client_auth_generation(client); + } + if (conn->curacid != cur->acid) + { + setac.reqType = FS_SetAuthorization; + setac.pad = 0; + setac.length = sizeof (fsSetAuthorizationReq) >> 2; + setac.id = cur->acid; + _fs_add_req_log(conn, FS_SetAuthorization); + _fs_write(conn, (char *) &setac, sizeof (fsSetAuthorizationReq)); + conn->curacid = cur->acid; + } +} + +/* + * Poll a pending connect + */ + +static int +_fs_check_connect (FSFpePtr conn) +{ + int ret; + + ret = _fs_poll_connect (conn->trans_conn, 0); + switch (ret) { + case FSIO_READY: + conn->fs_fd = _FontTransGetConnectionNumber (conn->trans_conn); + FD_SET (conn->fs_fd, &_fs_fd_mask); + break; + case FSIO_BLOCK: + break; + } + return ret; +} + +/* + * Return an FSIO status while waiting for the completed connection + * reply to arrive + */ + +static fsConnSetup * +_fs_get_conn_setup (FSFpePtr conn, int *error, int *setup_len) +{ + int ret; + char *data; + int headlen; + int len; + fsConnSetup *setup; + fsConnSetupAccept *accept; + + ret = _fs_start_read (conn, SIZEOF (fsConnSetup), &data); + if (ret != FSIO_READY) + { + *error = ret; + return 0; + } + + setup = (fsConnSetup *) data; + if (setup->major_version > FS_PROTOCOL) + { + *error = FSIO_ERROR; + return 0; + } + + headlen = (SIZEOF (fsConnSetup) + + (setup->alternate_len << 2) + + (setup->auth_len << 2)); + /* On anything but Success, no extra data is sent */ + if (setup->status != AuthSuccess) + { + len = headlen; + } + else + { + ret = _fs_start_read (conn, headlen + SIZEOF (fsConnSetupAccept), &data); + if (ret != FSIO_READY) + { + *error = ret; + return 0; + } + setup = (fsConnSetup *) data; + accept = (fsConnSetupAccept *) (data + headlen); + len = headlen + (accept->length << 2); + } + ret = _fs_start_read (conn, len, &data); + if (ret != FSIO_READY) + { + *error = ret; + return 0; + } + *setup_len = len; + return (fsConnSetup *) data; +} + +static int +_fs_send_conn_client_prefix (FSFpePtr conn) +{ + fsConnClientPrefix req; + int endian; + int ret; + + /* send setup prefix */ + endian = 1; + if (*(char *) &endian) + req.byteOrder = 'l'; + else + req.byteOrder = 'B'; + + req.major_version = FS_PROTOCOL; + req.minor_version = FS_PROTOCOL_MINOR; + +/* XXX add some auth info here */ + req.num_auths = 0; + req.auth_len = 0; + ret = _fs_write (conn, (char *) &req, SIZEOF (fsConnClientPrefix)); + if (ret != FSIO_READY) + return FSIO_ERROR; + conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; + return ret; +} + +static int +_fs_recv_conn_setup (FSFpePtr conn) +{ + int ret = FSIO_ERROR; + fsConnSetup *setup; + FSFpeAltPtr alts; + int i, alt_len; + int setup_len; + char *alt_save, *alt_names; + + setup = _fs_get_conn_setup (conn, &ret, &setup_len); + if (!setup) + return ret; + conn->current_seq = 0; + conn->fsMajorVersion = setup->major_version; + /* + * Create an alternate list from the initial server, but + * don't chain looking for alternates. + */ + if (conn->alternate == 0) + { + /* + * free any existing alternates list, allowing the list to + * be updated + */ + if (conn->alts) + { + free (conn->alts); + conn->alts = 0; + conn->numAlts = 0; + } + if (setup->num_alternates) + { + alts = malloc (setup->num_alternates * sizeof (FSFpeAltRec) + + (setup->alternate_len << 2)); + if (alts) + { + alt_names = (char *) (setup + 1); + alt_save = (char *) (alts + setup->num_alternates); + for (i = 0; i < setup->num_alternates; i++) + { + alts[i].subset = alt_names[0]; + alt_len = alt_names[1]; + alts[i].name = alt_save; + memcpy (alt_save, alt_names + 2, alt_len); + alt_save[alt_len] = '\0'; + alt_save += alt_len + 1; + alt_names += _fs_pad_length (alt_len + 2); + } + conn->numAlts = setup->num_alternates; + conn->alts = alts; + } + } + } + _fs_done_read (conn, setup_len); + if (setup->status != AuthSuccess) + return FSIO_ERROR; + return FSIO_READY; +} + +static int +_fs_open_server (FSFpePtr conn) +{ + int ret; + char *servername; + + if (conn->alternate == 0) + servername = conn->servername; + else + servername = conn->alts[conn->alternate-1].name; + conn->trans_conn = _fs_connect (servername, &ret); + conn->blockedConnectTime = GetTimeInMillis () + FS_RECONNECT_WAIT; + return ret; +} + +static char * +_fs_catalog_name (char *servername) +{ + char *sp; + + sp = strchr (servername, '/'); + if (!sp) + return 0; + return strrchr (sp + 1, '/'); +} + +static int +_fs_send_init_packets (FSFpePtr conn) +{ + fsSetResolutionReq srreq; + fsSetCataloguesReq screq; + int num_cats, + clen; + char *catalogues; + char *cat; + char len; + char *end; + int num_res; + FontResolutionPtr res; + +#define CATALOGUE_SEP '+' + + res = GetClientResolutions(&num_res); + if (num_res) + { + srreq.reqType = FS_SetResolution; + srreq.num_resolutions = num_res; + srreq.length = (SIZEOF(fsSetResolutionReq) + + (num_res * SIZEOF(fsResolution)) + 3) >> 2; + + _fs_add_req_log(conn, FS_SetResolution); + if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != FSIO_READY) + return FSIO_ERROR; + if (_fs_write_pad(conn, (char *) res, (num_res * SIZEOF(fsResolution))) != FSIO_READY) + return FSIO_ERROR; + } + + catalogues = 0; + if (conn->alternate != 0) + catalogues = _fs_catalog_name (conn->alts[conn->alternate-1].name); + if (!catalogues) + catalogues = _fs_catalog_name (conn->servername); + + if (!catalogues) + { + conn->has_catalogues = FALSE; + return FSIO_READY; + } + conn->has_catalogues = TRUE; + + /* turn cats into counted list */ + catalogues++; + + cat = catalogues; + num_cats = 0; + clen = 0; + while (*cat) + { + num_cats++; + end = strchr(cat, CATALOGUE_SEP); + if (!end) + end = cat + strlen (cat); + clen += (end - cat) + 1; /* length byte + string */ + cat = end; + } + + screq.reqType = FS_SetCatalogues; + screq.num_catalogues = num_cats; + screq.length = (SIZEOF(fsSetCataloguesReq) + clen + 3) >> 2; + + _fs_add_req_log(conn, FS_SetCatalogues); + if (_fs_write(conn, (char *) &screq, SIZEOF(fsSetCataloguesReq)) != FSIO_READY) + return FSIO_ERROR; + + while (*cat) + { + num_cats++; + end = strchr(cat, CATALOGUE_SEP); + if (!end) + end = cat + strlen (cat); + len = end - cat; + if (_fs_write (conn, &len, 1) != FSIO_READY) + return FSIO_ERROR; + if (_fs_write (conn, cat, (int) len) != FSIO_READY) + return FSIO_ERROR; + cat = end; + } + + if (_fs_write (conn, "....", _fs_pad_length (clen) - clen) != FSIO_READY) + return FSIO_ERROR; + + return FSIO_READY; +} + +static int +_fs_send_cat_sync (FSFpePtr conn) +{ + fsListCataloguesReq lcreq; + + /* + * now sync up with the font server, to see if an error was generated + * by a bogus catalogue + */ + lcreq.reqType = FS_ListCatalogues; + lcreq.length = (SIZEOF(fsListCataloguesReq)) >> 2; + lcreq.maxNames = 0; + lcreq.nbytes = 0; + lcreq.pad2 = 0; + _fs_add_req_log(conn, FS_SetCatalogues); + if (_fs_write(conn, (char *) &lcreq, SIZEOF(fsListCataloguesReq)) != FSIO_READY) + return FSIO_ERROR; + conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; + return FSIO_READY; +} + +static int +_fs_recv_cat_sync (FSFpePtr conn) +{ + fsGenericReply *reply; + fsError *error; + int err; + int ret; + + reply = fs_get_reply (conn, &err); + if (!reply) + return err; + + ret = FSIO_READY; + if (reply->type == FS_Error) + { + error = (fsError *) reply; + if (error->major_opcode == FS_SetCatalogues) + ret = FSIO_ERROR; + } + _fs_done_read (conn, reply->length << 2); + return ret; +} + +static void +_fs_close_server (FSFpePtr conn) +{ + _fs_unmark_block (conn, FS_PENDING_WRITE|FS_BROKEN_WRITE|FS_COMPLETE_REPLY|FS_BROKEN_CONNECTION); + if (conn->trans_conn) + { + _FontTransClose (conn->trans_conn); + conn->trans_conn = 0; + _fs_io_reinit (conn); + } + if (conn->fs_fd >= 0) + { + FD_CLR (conn->fs_fd, &_fs_fd_mask); + conn->fs_fd = -1; + } + conn->fs_conn_state = FS_CONN_UNCONNECTED; +} + +static int +_fs_do_setup_connection (FSFpePtr conn) +{ + int ret; + + do + { +#ifdef DEBUG + fprintf (stderr, "fs_do_setup_connection state %d\n", conn->fs_conn_state); +#endif + switch (conn->fs_conn_state) { + case FS_CONN_UNCONNECTED: + ret = _fs_open_server (conn); + if (ret == FSIO_BLOCK) + conn->fs_conn_state = FS_CONN_CONNECTING; + break; + case FS_CONN_CONNECTING: + ret = _fs_check_connect (conn); + break; + case FS_CONN_CONNECTED: + ret = _fs_send_conn_client_prefix (conn); + break; + case FS_CONN_SENT_PREFIX: + ret = _fs_recv_conn_setup (conn); + break; + case FS_CONN_RECV_INIT: + ret = _fs_send_init_packets (conn); + if (conn->has_catalogues) + ret = _fs_send_cat_sync (conn); + break; + case FS_CONN_SENT_CAT: + if (conn->has_catalogues) + ret = _fs_recv_cat_sync (conn); + else + ret = FSIO_READY; + break; + default: + ret = FSIO_READY; + break; + } + switch (ret) { + case FSIO_READY: + if (conn->fs_conn_state < FS_CONN_RUNNING) + conn->fs_conn_state++; + break; + case FSIO_BLOCK: + if (TimeCmp (GetTimeInMillis (), <, conn->blockedConnectTime)) + break; + ret = FSIO_ERROR; + /* fall through... */ + case FSIO_ERROR: + _fs_close_server (conn); + /* + * Try the next alternate + */ + if (conn->alternate < conn->numAlts) + { + conn->alternate++; + ret = FSIO_READY; + } + else + conn->alternate = 0; + break; + } + } while (conn->fs_conn_state != FS_CONN_RUNNING && ret == FSIO_READY); + if (ret == FSIO_READY) + conn->generation = ++generationCount; + return ret; +} + +static int +_fs_wait_connect (FSFpePtr conn) +{ + int ret; + + for (;;) + { + ret = _fs_do_setup_connection (conn); + if (ret != FSIO_BLOCK) + break; + if (conn->fs_conn_state <= FS_CONN_CONNECTING) + ret = _fs_poll_connect (conn->trans_conn, 1000); + else + ret = _fs_wait_for_readable (conn, 1000); + if (ret == FSIO_ERROR) + break; + } + return ret; +} + +/* + * Poll a connection in the process of reconnecting + */ +static void +_fs_check_reconnect (FSFpePtr conn) +{ + int ret; + + ret = _fs_do_setup_connection (conn); + switch (ret) { + case FSIO_READY: + _fs_unmark_block (conn, FS_RECONNECTING|FS_GIVE_UP); + _fs_restart_connection (conn); + break; + case FSIO_BLOCK: + break; + case FSIO_ERROR: + conn->brokenConnectionTime = GetTimeInMillis () + FS_RECONNECT_POLL; + break; + } +} + +/* + * Start the reconnection process + */ +static void +_fs_start_reconnect (FSFpePtr conn) +{ + if (conn->blockState & FS_RECONNECTING) + return; + conn->alternate = 0; + _fs_mark_block (conn, FS_RECONNECTING); + _fs_unmark_block (conn, FS_BROKEN_CONNECTION); + _fs_check_reconnect (conn); +} + + +static FSFpePtr +_fs_init_conn (char *servername) +{ + FSFpePtr conn; + + conn = calloc (1, sizeof (FSFpeRec) + strlen (servername) + 1); + if (!conn) + return 0; + if (!_fs_io_init (conn)) + { + free (conn); + return 0; + } + conn->servername = (char *) (conn + 1); + conn->fs_conn_state = FS_CONN_UNCONNECTED; + conn->fs_fd = -1; + strcpy (conn->servername, servername); + return conn; +} + +static void +_fs_free_conn (FSFpePtr conn) +{ + _fs_close_server (conn); + _fs_io_fini (conn); + if (conn->alts) + free (conn->alts); + free (conn); +} + +/* + * called at server init time + */ + +void +fs_register_fpe_functions(void) +{ + RegisterFPEFunctions(fs_name_check, + fs_init_fpe, + fs_free_fpe, + fs_reset_fpe, + fs_open_font, + fs_close_font, + fs_list_fonts, + fs_start_list_with_info, + fs_next_list_with_info, + fs_wakeup, + fs_client_died, + _fs_load_glyphs, + NULL, + NULL, + NULL); +} diff --git a/src/fc/fserve.h b/src/fc/fserve.h new file mode 100755 index 0000000..5999861 --- /dev/null +++ b/src/fc/fserve.h @@ -0,0 +1,91 @@ +/* + * Copyright 1990 Network Computing Devices + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Network Computing Devices not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Network Computing + * Devices makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Dave Lemke, Network Computing Devices, Inc + * + */ + +#ifndef _FSERVE_H_ +#define _FSERVE_H_ +/* + * font server data structures + */ + +/* types of block records */ +#define FS_OPEN_FONT 1 +#define FS_LOAD_GLYPHS 2 +#define FS_LIST_FONTS 3 +#define FS_LIST_WITH_INFO 4 + +/* states of OpenFont */ +#define FS_OPEN_REPLY 0 +#define FS_INFO_REPLY 1 +#define FS_EXTENT_REPLY 2 +#define FS_GLYPHS_REPLY 3 +#define FS_DONE_REPLY 4 +#define FS_DEPENDING 5 + +/* status of ListFontsWithInfo */ +#define FS_LFWI_WAITING 0 +#define FS_LFWI_REPLY 1 +#define FS_LFWI_FINISHED 2 + +/* states of connection */ +#define FS_CONN_CLOSED 0 +#define FS_CONN_CONNECTING 1 +#define FS_CONN_READ_HEADER 2 +#define FS_CONN_READ_DATA 3 + +#define AccessDone 0x400 + +typedef struct _fs_font_data *FSFontDataPtr; +typedef struct _fs_blocked_font *FSBlockedFontPtr; +typedef struct _fs_blocked_glyphs *FSBlockedGlyphPtr; +typedef struct _fs_blocked_list *FSBlockedListPtr; +typedef struct _fs_blocked_list_info *FSBlockedListInfoPtr; +typedef struct _fs_block_data *FSBlockDataPtr; +typedef struct _fs_font_table *FSFontTablePtr; +typedef struct _fs_fpe_data *FSFpePtr; + +typedef struct _fs_blocked_bitmaps *FSBlockedBitmapPtr; +typedef struct _fs_blocked_extents *FSBlockedExtentPtr; + +extern void _fs_convert_char_info ( fsXCharInfo *src, xCharInfo *dst ); +extern void _fs_free_props (FontInfoPtr pfi); +extern FontPtr fs_create_font (FontPathElementPtr fpe, + char *name, + int namelen, + fsBitmapFormat format, + fsBitmapFormatMask fmask); + +extern int fs_load_all_glyphs ( FontPtr pfont ); + +/* + * These should be declared elsewhere, but I'm concerned that moving them + * would cause problems building other pieces + */ +extern FontPtr find_old_font (Font id); +extern int set_font_authorizations (char **a, int *len, pointer client); +extern long GetTimeInMillis (void); + + +#endif /* _FSERVE_H_ */ diff --git a/src/fc/fservestr.h b/src/fc/fservestr.h new file mode 100755 index 0000000..a6d0d1d --- /dev/null +++ b/src/fc/fservestr.h @@ -0,0 +1,200 @@ +/* + * Copyright 1990 Network Computing Devices + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Network Computing Devices not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Network Computing + * Devices makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Dave Lemke, Network Computing Devices, Inc + */ + +#ifndef _FSERVESTR_H_ +#define _FSERVESTR_H_ + +#include "fserve.h" +#include "fsio.h" + +/* + * font server data structures + */ +/* + * font server private storage + */ + +typedef struct _fs_glyph { + struct _fs_glyph *next; +} FSGlyphRec, *FSGlyphPtr; + +typedef struct _fs_font { + CharInfoPtr pDefault; + CharInfoPtr encoding; + CharInfoPtr inkMetrics; + FSGlyphPtr glyphs; +} FSFontRec, *FSFontPtr; + +/* FS special data for the font */ +typedef struct _fs_font_data { + long fontid; + int generation; /* FS generation when opened */ + unsigned long glyphs_to_get; /* # glyphs remaining to be gotten */ + + /* Following data needed in case font needs to be reopened. */ + int namelen; + char *name; + fsBitmapFormat format; + fsBitmapFormatMask fmask; +} FSFontDataRec; + +typedef struct fs_clients_depending { + pointer client; + struct fs_clients_depending *next; +} FSClientsDependingRec, *FSClientsDependingPtr; + +/* OpenFont specific data for blocked request */ +typedef struct _fs_blocked_font { + FontPtr pfont; /* must be first for fs_read_glyphs */ + long fontid; + int state; /* how many of the replies have landed */ + int flags; + Bool freeFont; /* free this font on failure */ + CARD16 queryInfoSequence; + CARD16 queryExtentsSequence; + CARD16 queryBitmapsSequence; + fsBitmapFormat format; + FSClientsDependingPtr clients_depending; +} FSBlockedFontRec; + +/* LoadGlyphs data for blocked request */ +typedef struct _fs_blocked_glyphs { + FontPtr pfont; /* must be first for fs_read_glyphs */ + int num_expected_ranges; + fsRange *expected_ranges; + FSClientsDependingPtr clients_depending; +} FSBlockedGlyphRec; + +/* LoadExtents data for blocked request */ +typedef struct _fs_blocked_extents { + FontPtr pfont; + fsRange *expected_ranges; + int nranges; + unsigned long nextents; + fsXCharInfo *extents; +} FSBlockedExtentRec; + +/* LoadBitmaps data for blocked request */ +typedef struct _fs_blocked_bitmaps { + FontPtr pfont; + fsRange *expected_ranges; + int nranges; + unsigned long size; + unsigned long nglyphs; + fsOffset32 *offsets; + pointer gdata; +} FSBlockedBitmapRec; + +/* state for blocked ListFonts */ +typedef struct _fs_blocked_list { + FontNamesPtr names; +} FSBlockedListRec; + +/* state for blocked ListFontsWithInfo */ +typedef struct _fs_blocked_list_info { + int status; + int namelen; + FontInfoRec info; + char name[256]; + int remaining; +} FSBlockedListInfoRec; + +/* state for blocked request */ +typedef struct _fs_block_data { + int type; /* Open Font, LoadGlyphs, ListFonts, + * ListWithInfo */ + pointer client; /* who wants it */ + CARD16 sequenceNumber; /* expected */ + pointer data; /* type specific data */ + int errcode; /* Suspended, et al. */ + struct _fs_block_data *depending; /* clients depending on this one */ + struct _fs_block_data *next; +} FSBlockDataRec; + +/* state for reconnected to dead font server */ +typedef struct _fs_reconnect { + int i; +} FSReconnectRec, *FSReconnectPtr; + + +#if !defined(UNIXCPP) || defined(ANSICPP) +#define fsCat(x,y) x##_##y +#else +#define fsCat(x,y) x/**/_/**/y +#endif + + +/* copy XCharInfo parts of a protocol reply into a xCharInfo */ + +#define fsUnpack_XCharInfo(packet, structure) \ + (structure)->leftSideBearing = fsCat(packet,left); \ + (structure)->rightSideBearing = fsCat(packet,right); \ + (structure)->characterWidth = fsCat(packet,width); \ + (structure)->ascent = fsCat(packet,ascent); \ + (structure)->descent = fsCat(packet,descent); \ + (structure)->attributes = fsCat(packet,attributes) + + +/* copy XFontInfoHeader parts of a protocol reply into a FontInfoRec */ + +#define fsUnpack_XFontInfoHeader(packet, structure) \ + (structure)->allExist = ((packet)->font_header_flags & FontInfoAllCharsExist) != 0; \ + (structure)->drawDirection = \ + ((packet)->font_header_draw_direction == LeftToRightDrawDirection) ? \ + LeftToRight : RightToLeft; \ + (structure)->inkInside = ((packet)->font_header_flags & FontInfoInkInside) != 0; \ + \ + (structure)->firstRow = (packet)->font_hdr_char_range_min_char_high; \ + (structure)->firstCol = (packet)->font_hdr_char_range_min_char_low; \ + (structure)->lastRow = (packet)->font_hdr_char_range_max_char_high; \ + (structure)->lastCol = (packet)->font_hdr_char_range_max_char_low; \ + (structure)->defaultCh = (packet)->font_header_default_char_low \ + + ((packet)->font_header_default_char_high << 8); \ + \ + (structure)->fontDescent = (packet)->font_header_font_descent; \ + (structure)->fontAscent = (packet)->font_header_font_ascent; \ + \ + fsUnpack_XCharInfo((packet)->font_header_min_bounds, &(structure)->minbounds); \ + fsUnpack_XCharInfo((packet)->font_header_min_bounds, &(structure)->ink_minbounds); \ + fsUnpack_XCharInfo((packet)->font_header_max_bounds, &(structure)->maxbounds); \ + fsUnpack_XCharInfo((packet)->font_header_max_bounds, &(structure)->ink_maxbounds) + +extern void _fs_init_fontinfo ( FSFpePtr conn, FontInfoPtr pfi ); +extern int _fs_convert_props ( fsPropInfo *pi, fsPropOffset *po, pointer pd, + FontInfoPtr pfi ); +extern int _fs_convert_lfwi_reply ( FSFpePtr conn, FontInfoPtr pfi, + fsListFontsWithXInfoReply *fsrep, + fsPropInfo *pi, fsPropOffset *po, + pointer pd ); +extern int fs_build_range ( FontPtr pfont, Bool range_flag, + unsigned int count, int item_size, + unsigned char *data, int *nranges, + fsRange **ranges ); +extern void _fs_clean_aborted_loadglyphs ( FontPtr pfont, + int num_expected_ranges, + fsRange *expected_ranges ); +extern void _fs_init_font ( FontPtr pfont ); +extern pointer fs_alloc_glyphs (FontPtr pFont, int size); +#endif /* _FSERVESTR_H_ */ diff --git a/src/fc/fsio.c b/src/fc/fsio.c new file mode 100755 index 0000000..63d3b4f --- /dev/null +++ b/src/fc/fsio.c @@ -0,0 +1,451 @@ +/* + * Copyright 1990 Network Computing Devices + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Network Computing Devices not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Network Computing + * Devices makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Dave Lemke, Network Computing Devices, Inc + */ +/* + * font server i/o routines + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef WIN32 +#define _WILLWINSOCK_ +#include "X11/Xwindows.h" +#endif + +#define FONT_t +#define TRANS_CLIENT +#include "X11/Xtrans/Xtrans.h" +#include "X11/Xpoll.h" +#include +#include +#include +#include +#include "fservestr.h" + +#include +#include +#include +#if !defined(WIN32) +#ifndef Lynx +#include +#else +#include +#endif +#endif +#include +#ifdef WIN32 +#define EWOULDBLOCK WSAEWOULDBLOCK +#undef EINTR +#define EINTR WSAEINTR +#endif + + + +static int padlength[4] = {0, 3, 2, 1}; +fd_set _fs_fd_mask; + +static int +_fs_resize (FSBufPtr buf, long size); + +static void +_fs_downsize (FSBufPtr buf, long size); + +int +_fs_poll_connect (XtransConnInfo trans_conn, int timeout) +{ + fd_set w_mask; + struct timeval tv; + int fs_fd = _FontTransGetConnectionNumber (trans_conn); + int ret; + + do + { + tv.tv_usec = 0; + tv.tv_sec = timeout; + FD_ZERO (&w_mask); + FD_SET (fs_fd, &w_mask); + ret = Select (fs_fd + 1, NULL, &w_mask, NULL, &tv); + } while (ret < 0 && ECHECK(EINTR)); + if (ret == 0) + return FSIO_BLOCK; + if (ret < 0) + return FSIO_ERROR; + return FSIO_READY; +} + +XtransConnInfo +_fs_connect(char *servername, int *err) +{ + XtransConnInfo trans_conn; /* transport connection object */ + int ret; + int i = 0; + int retries = 5; + + /* + * Open the network connection. + */ + if( (trans_conn=_FontTransOpenCOTSClient(servername)) == NULL ) + { + *err = FSIO_ERROR; + return 0; + } + + /* + * Set the connection non-blocking since we use select() to block. + */ + + _FontTransSetOption(trans_conn, TRANS_NONBLOCKING, 1); + + do { + i = _FontTransConnect(trans_conn,servername); + } while ((i == TRANS_TRY_CONNECT_AGAIN) && (retries-- > 0)); + + if (i < 0) + { + if (i == TRANS_IN_PROGRESS) + ret = FSIO_BLOCK; + else + ret = FSIO_ERROR; + } + else + ret = FSIO_READY; + + if (ret == FSIO_ERROR) + { + _FontTransClose(trans_conn); + trans_conn = 0; + } + + *err = ret; + return trans_conn; +} + +static int +_fs_fill (FSFpePtr conn) +{ + long avail; + long bytes_read; + Bool waited = FALSE; + + if (_fs_flush (conn) < 0) + return FSIO_ERROR; + /* + * Don't go overboard here; stop reading when we've + * got enough to satisfy the pending request + */ + while ((conn->inNeed - (conn->inBuf.insert - conn->inBuf.remove)) > 0) + { + avail = conn->inBuf.size - conn->inBuf.insert; + /* + * For SVR4 with a unix-domain connection, ETEST() after selecting + * readable means the server has died. To do this here, we look for + * two consecutive reads returning ETEST(). + */ + ESET (0); + bytes_read =_FontTransRead(conn->trans_conn, + conn->inBuf.buf + conn->inBuf.insert, + avail); + if (bytes_read > 0) { + conn->inBuf.insert += bytes_read; + waited = FALSE; + } + else + { + if (bytes_read == 0 || ETEST ()) + { + if (!waited) + { + waited = TRUE; + if (_fs_wait_for_readable (conn, 0) == FSIO_BLOCK) + return FSIO_BLOCK; + continue; + } + } + _fs_connection_died (conn); + return FSIO_ERROR; + } + } + return FSIO_READY; +} + +/* + * Make space and return whether data have already arrived + */ + +int +_fs_start_read (FSFpePtr conn, long size, char **buf) +{ + int ret; + + conn->inNeed = size; + if (fs_inqueued(conn) < size) + { + if (_fs_resize (&conn->inBuf, size) != FSIO_READY) + { + _fs_connection_died (conn); + return FSIO_ERROR; + } + ret = _fs_fill (conn); + if (ret == FSIO_ERROR) + return ret; + if (ret == FSIO_BLOCK || fs_inqueued(conn) < size) + return FSIO_BLOCK; + } + if (buf) + *buf = conn->inBuf.buf + conn->inBuf.remove; + return FSIO_READY; +} + +void +_fs_done_read (FSFpePtr conn, long size) +{ + if (conn->inBuf.insert - conn->inBuf.remove < size) + { +#ifdef DEBUG + fprintf (stderr, "_fs_done_read skipping to many bytes\n"); +#endif + return; + } + conn->inBuf.remove += size; + conn->inNeed -= size; + _fs_downsize (&conn->inBuf, FS_BUF_MAX); +} + +long +_fs_pad_length (long len) +{ + return len + padlength[len&3]; +} + +int +_fs_flush (FSFpePtr conn) +{ + long bytes_written; + long remain; + + /* XXX - hack. The right fix is to remember that the font server + has gone away when we first discovered it. */ + if (conn->fs_fd < 0) + return FSIO_ERROR; + + while ((remain = conn->outBuf.insert - conn->outBuf.remove) > 0) + { + bytes_written = _FontTransWrite(conn->trans_conn, + conn->outBuf.buf + conn->outBuf.remove, + (int) remain); + if (bytes_written > 0) + { + conn->outBuf.remove += bytes_written; + } + else + { + if (bytes_written == 0 || ETEST ()) + { + conn->brokenWriteTime = GetTimeInMillis () + FS_FLUSH_POLL; + _fs_mark_block (conn, FS_BROKEN_WRITE); + break; + } + if (!ECHECK (EINTR)) + { + _fs_connection_died (conn); + return FSIO_ERROR; + } + } + } + if (conn->outBuf.remove == conn->outBuf.insert) + { + _fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE); + if (conn->outBuf.size > FS_BUF_INC) + conn->outBuf.buf = realloc (conn->outBuf.buf, FS_BUF_INC); + conn->outBuf.remove = conn->outBuf.insert = 0; + } + return FSIO_READY; +} + +static int +_fs_resize (FSBufPtr buf, long size) +{ + char *new; + long new_size; + + if (buf->remove) + { + if (buf->remove != buf->insert) + { + memmove (buf->buf, + buf->buf + buf->remove, + buf->insert - buf->remove); + } + buf->insert -= buf->remove; + buf->remove = 0; + } + if (buf->size - buf->remove < size) + { + new_size = ((buf->remove + size + FS_BUF_INC) / FS_BUF_INC) * FS_BUF_INC; + new = realloc (buf->buf, new_size); + if (!new) + return FSIO_ERROR; + buf->buf = new; + buf->size = new_size; + } + return FSIO_READY; +} + +static void +_fs_downsize (FSBufPtr buf, long size) +{ + if (buf->insert == buf->remove) + { + buf->insert = buf->remove = 0; + if (buf->size > size) + { + buf->buf = realloc (buf->buf, size); + buf->size = size; + } + } +} + +void +_fs_io_reinit (FSFpePtr conn) +{ + conn->outBuf.insert = conn->outBuf.remove = 0; + _fs_downsize (&conn->outBuf, FS_BUF_INC); + conn->inBuf.insert = conn->inBuf.remove = 0; + _fs_downsize (&conn->inBuf, FS_BUF_MAX); +} + +Bool +_fs_io_init (FSFpePtr conn) +{ + conn->outBuf.insert = conn->outBuf.remove = 0; + conn->outBuf.buf = malloc (FS_BUF_INC); + if (!conn->outBuf.buf) + return FALSE; + conn->outBuf.size = FS_BUF_INC; + + conn->inBuf.insert = conn->inBuf.remove = 0; + conn->inBuf.buf = malloc (FS_BUF_INC); + if (!conn->inBuf.buf) + { + free (conn->outBuf.buf); + conn->outBuf.buf = 0; + return FALSE; + } + conn->inBuf.size = FS_BUF_INC; + + return TRUE; +} + +void +_fs_io_fini (FSFpePtr conn) +{ + if (conn->outBuf.buf) + free (conn->outBuf.buf); + if (conn->inBuf.buf) + free (conn->inBuf.buf); +} + +static int +_fs_do_write(FSFpePtr conn, char *data, long len, long size) +{ + if (size == 0) { +#ifdef DEBUG + fprintf(stderr, "tried to write 0 bytes \n"); +#endif + return FSIO_READY; + } + + if (conn->fs_fd == -1) + return FSIO_ERROR; + + while (conn->outBuf.insert + size > conn->outBuf.size) + { + if (_fs_flush (conn) < 0) + return FSIO_ERROR; + if (_fs_resize (&conn->outBuf, size) < 0) + { + _fs_connection_died (conn); + return FSIO_ERROR; + } + } + memcpy (conn->outBuf.buf + conn->outBuf.insert, data, len); + /* Clear pad data */ + memset (conn->outBuf.buf + conn->outBuf.insert + len, 0, size - len); + conn->outBuf.insert += size; + _fs_mark_block (conn, FS_PENDING_WRITE); + return FSIO_READY; +} + +/* + * Write the indicated bytes + */ +int +_fs_write (FSFpePtr conn, char *data, long len) +{ + return _fs_do_write (conn, data, len, len); +} + +/* + * Write the indicated bytes adding any appropriate pad + */ +int +_fs_write_pad(FSFpePtr conn, char *data, long len) +{ + return _fs_do_write (conn, data, len, len + padlength[len & 3]); +} + +int +_fs_wait_for_readable(FSFpePtr conn, int ms) +{ + fd_set r_mask; + fd_set e_mask; + int result; + struct timeval tv; + + for (;;) { + if (conn->fs_fd < 0) + return FSIO_ERROR; + FD_ZERO(&r_mask); + FD_ZERO(&e_mask); + tv.tv_sec = ms / 1000; + tv.tv_usec = (ms % 1000) * 1000; + FD_SET(conn->fs_fd, &r_mask); + FD_SET(conn->fs_fd, &e_mask); + result = Select(conn->fs_fd + 1, &r_mask, NULL, &e_mask, &tv); + if (result < 0) + { + if (ECHECK(EINTR) || ECHECK(EAGAIN)) + continue; + else + return FSIO_ERROR; + } + if (result == 0) + return FSIO_BLOCK; + if (FD_ISSET(conn->fs_fd, &r_mask)) + return FSIO_READY; + return FSIO_ERROR; + } +} diff --git a/src/fc/fsio.h b/src/fc/fsio.h new file mode 100755 index 0000000..bd0c621 --- /dev/null +++ b/src/fc/fsio.h @@ -0,0 +1,178 @@ +/* + * Copyright 1990 Network Computing Devices + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Network Computing Devices not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Network Computing + * Devices makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Dave Lemke, Network Computing Devices, Inc + */ + +#ifndef _FSIO_H_ +#define _FSIO_H_ + +#undef DEBUG +#define REQUEST_LOG_SIZE 100 + +typedef struct _fs_fpe_alternate { + char *name; + Bool subset; +} FSFpeAltRec, *FSFpeAltPtr; + + +/* Per client access contexts */ +typedef struct _fs_client_data { + pointer client; + struct _fs_client_data *next; + XID acid; + int auth_generation; +} FSClientRec, *FSClientPtr; + +#define FS_RECONNECT_POLL 1000 +#define FS_RECONNECT_WAIT 5000 +#define FS_GIVEUP_WAIT 20000 +#define FS_REQUEST_TIMEOUT 20000 +#define FS_OPEN_TIMEOUT 30000 +#define FS_REOPEN_TIMEOUT 10000 +#define FS_FLUSH_POLL 1000 + +typedef struct _fs_buf { + char *buf; /* data */ + long size; /* sizeof data */ + long insert; /* where to insert new data */ + long remove; /* where to remove old data */ +} FSBufRec, *FSBufPtr; + +#define FS_BUF_INC 1024 +#define FS_BUF_MAX 32768 + +#define FS_PENDING_WRITE 0x01 /* some write data is queued */ +#define FS_BROKEN_WRITE 0x02 /* writes are broken */ +#define FS_BROKEN_CONNECTION 0x04 /* connection is broken */ +#define FS_PENDING_REPLY 0x08 /* waiting for a reply */ +#define FS_GIVE_UP 0x10 /* font server declared useless */ +#define FS_COMPLETE_REPLY 0x20 /* complete reply ready */ +#define FS_RECONNECTING 0x40 + +#define FS_CONN_UNCONNECTED 0 +#define FS_CONN_CONNECTING 1 +#define FS_CONN_CONNECTED 2 +#define FS_CONN_SENT_PREFIX 3 +#define FS_CONN_RECV_INIT 4 +#define FS_CONN_SENT_CAT 5 +#define FS_CONN_RUNNING 6 + +/* FS specific font FontPathElement data */ +typedef struct _fs_fpe_data { + FSFpePtr next; /* list of all active fs fpes */ + int fs_fd; /* < 0 when not running */ + int fs_conn_state; /* connection state */ + int current_seq; + char *servername; + Bool has_catalogues; + + int generation; + int numAlts; + int alternate; /* which alternate is in use +1 */ + int fsMajorVersion; /* font server major version number */ + FSFpeAltPtr alts; + + FSClientPtr clients; + XID curacid; +#ifdef DEBUG + int reqindex; + struct { + int opcode; + int sequence; + } reqbuffer[REQUEST_LOG_SIZE]; +#endif + FSBufRec outBuf; /* request queue */ + FSBufRec inBuf; /* reply queue */ + long inNeed; /* amount needed for reply */ + + CARD32 blockState; + CARD32 blockedReplyTime; /* time to abort blocked read */ + CARD32 brokenWriteTime; /* time to retry broken write */ + CARD32 blockedConnectTime; /* time to abort blocked connect */ + CARD32 brokenConnectionTime; /* time to retry broken connection */ + + FSBlockDataPtr blockedRequests; + + struct _XtransConnInfo *trans_conn; /* transport connection object */ +} FSFpeRec; + +#define fs_outspace(conn) ((conn)->outBuf.size - (conn)->outBuf.insert) +#define fs_outqueued(conn) ((conn)->outBuf.insert - (conn)->outBuf.remove) +#define fs_inqueued(conn) ((conn)->inBuf.insert - (conn)->inBuf.remove) +#define fs_needsflush(conn) (fs_outqueued(conn) != 0) +#define fs_needsfill(conn) (fs_inqueued(conn) < (conn)->inNeed) +#define fs_needsconnect(conn) ((conn)->fs_fd < 0) +#define fs_data_read(conn) ((conn)->inBuf.insert - (conn)->inBuf.remove) + +#define FSIO_READY 1 +#define FSIO_BLOCK 0 +#define FSIO_ERROR -1 + +extern Bool _fs_reopen_server ( FSFpePtr conn ); +extern int _fs_write ( FSFpePtr conn, char *data, long size ); +extern int _fs_write_pad ( FSFpePtr conn, char *data, long len ); +extern int _fs_wait_for_readable ( FSFpePtr conn, int ms ); +extern long _fs_pad_length (long len); + +extern void _fs_connection_died ( FSFpePtr conn ); + +extern int _fs_flush (FSFpePtr conn); +extern void _fs_mark_block (FSFpePtr conn, CARD32 mask); +extern void _fs_unmark_block (FSFpePtr conn, CARD32 mask); +extern void _fs_done_read (FSFpePtr conn, long size); +extern void _fs_io_reinit (FSFpePtr conn); +extern int _fs_start_read (FSFpePtr conn, long size, char **buf); +extern Bool _fs_io_init (FSFpePtr conn); +extern void _fs_io_fini (FSFpePtr conn); +extern int _fs_poll_connect (XtransConnInfo trans_conn, int timeout); +extern XtransConnInfo _fs_connect(char *servername, int *ret); + +/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX + * systems are broken and return EWOULDBLOCK when they should return EAGAIN + */ +#ifdef WIN32 +#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK) +#else +#if defined(EAGAIN) && defined(EWOULDBLOCK) +#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK) +#else +#ifdef EAGAIN +#define ETEST() (errno == EAGAIN) +#else +#define ETEST() (errno == EWOULDBLOCK) +#endif +#endif +#endif +#ifdef WIN32 +#define ECHECK(err) (WSAGetLastError() == err) +#define ESET(val) WSASetLastError(val) +#else +#ifdef ISC +#define ECHECK(err) ((errno == err) || ETEST()) +#else +#define ECHECK(err) (errno == err) +#endif +#define ESET(val) errno = val +#endif + +#endif /* _FSIO_H_ */ diff --git a/src/fc/fslibos.h b/src/fc/fslibos.h new file mode 100755 index 0000000..c49f52e --- /dev/null +++ b/src/fc/fslibos.h @@ -0,0 +1,218 @@ +/* + * Copyright 1990 Network Computing Devices; + * Portions Copyright 1987 by Digital Equipment Corporation + */ + +/* + +Copyright 1987, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * FSlib networking & os include file + */ + +#include + +#ifndef WIN32 + +/* + * makedepend screws up on #undef OPEN_MAX, so we define a new symbol + */ + +#ifndef FONT_OPEN_MAX + +#ifndef X_NOT_POSIX +# ifdef _POSIX_SOURCE +# include +# else +# define _POSIX_SOURCE +# include +# undef _POSIX_SOURCE +# endif +#endif +#ifndef SIZE_MAX +# ifdef ULONG_MAX +# define SIZE_MAX ULONG_MAX +# else +# define SIZE_MAX UINT_MAX +# endif +#endif +#ifndef OPEN_MAX +#if defined(SVR4) +#define OPEN_MAX 256 +#else +#include +#ifndef OPEN_MAX +#ifdef __OSF1__ +#define OPEN_MAX 256 +#else +#ifdef NOFILE +#define OPEN_MAX NOFILE +#else +#define OPEN_MAX NOFILES_MAX +#endif +#endif +#endif +#endif +#endif + +#if OPEN_MAX > 256 +#define FONT_OPEN_MAX 256 +#else +#define FONT_OPEN_MAX OPEN_MAX +#endif + +#endif /* FONT_OPEN_MAX */ + +#ifdef WORD64 +#define NMSKBITS 64 +#else +#define NMSKBITS 32 +#endif + +#define MSKCNT ((FONT_OPEN_MAX + NMSKBITS - 1) / NMSKBITS) + +typedef unsigned long FdSet[MSKCNT]; +typedef FdSet FdSetPtr; + +#if (MSKCNT==1) +#define BITMASK(i) (1 << (i)) +#define MASKIDX(i) 0 +#endif + +#if (MSKCNT>1) +#define BITMASK(i) (1 << ((i) & (NMSKBITS - 1))) +#define MASKIDX(i) ((i) / NMSKBITS) +#endif + +#define MASKWORD(buf, i) buf[MASKIDX(i)] +#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) +#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) +#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) + +#if (MSKCNT==1) +#define COPYBITS(src, dst) dst[0] = src[0] +#define CLEARBITS(buf) buf[0] = 0 +#define MASKANDSETBITS(dst, b1, b2) dst[0] = (b1[0] & b2[0]) +#define ORBITS(dst, b1, b2) dst[0] = (b1[0] | b2[0]) +#define UNSETBITS(dst, b1) (dst[0] &= ~b1[0]) +#define ANYSET(src) (src[0]) +#endif + +#if (MSKCNT==2) +#define COPYBITS(src, dst) { dst[0] = src[0]; dst[1] = src[1]; } +#define CLEARBITS(buf) { buf[0] = 0; buf[1] = 0; } +#define MASKANDSETBITS(dst, b1, b2) {\ + dst[0] = (b1[0] & b2[0]);\ + dst[1] = (b1[1] & b2[1]); } +#define ORBITS(dst, b1, b2) {\ + dst[0] = (b1[0] | b2[0]);\ + dst[1] = (b1[1] | b2[1]); } +#define UNSETBITS(dst, b1) {\ + dst[0] &= ~b1[0]; \ + dst[1] &= ~b1[1]; } +#define ANYSET(src) (src[0] || src[1]) +#endif + +#if (MSKCNT==3) +#define COPYBITS(src, dst) { dst[0] = src[0]; dst[1] = src[1]; \ + dst[2] = src[2]; } +#define CLEARBITS(buf) { buf[0] = 0; buf[1] = 0; buf[2] = 0; } +#define MASKANDSETBITS(dst, b1, b2) {\ + dst[0] = (b1[0] & b2[0]);\ + dst[1] = (b1[1] & b2[1]);\ + dst[2] = (b1[2] & b2[2]); } +#define ORBITS(dst, b1, b2) {\ + dst[0] = (b1[0] | b2[0]);\ + dst[1] = (b1[1] | b2[1]);\ + dst[2] = (b1[2] | b2[2]); } +#define UNSETBITS(dst, b1) {\ + dst[0] &= ~b1[0]; \ + dst[1] &= ~b1[1]; \ + dst[2] &= ~b1[2]; } +#define ANYSET(src) (src[0] || src[1] || src[2]) +#endif + +#if (MSKCNT==4) +#define COPYBITS(src, dst) dst[0] = src[0]; dst[1] = src[1]; \ + dst[2] = src[2]; dst[3] = src[3] +#define CLEARBITS(buf) buf[0] = 0; buf[1] = 0; buf[2] = 0; buf[3] = 0 +#define MASKANDSETBITS(dst, b1, b2) \ + dst[0] = (b1[0] & b2[0]);\ + dst[1] = (b1[1] & b2[1]);\ + dst[2] = (b1[2] & b2[2]);\ + dst[3] = (b1[3] & b2[3]) +#define ORBITS(dst, b1, b2) \ + dst[0] = (b1[0] | b2[0]);\ + dst[1] = (b1[1] | b2[1]);\ + dst[2] = (b1[2] | b2[2]);\ + dst[3] = (b1[3] | b2[3]) +#define UNSETBITS(dst, b1) \ + dst[0] &= ~b1[0]; \ + dst[1] &= ~b1[1]; \ + dst[2] &= ~b1[2]; \ + dst[3] &= ~b1[3] +#define ANYSET(src) (src[0] || src[1] || src[2] || src[3]) +#endif + +#if (MSKCNT>4) +#define COPYBITS(src, dst) memmove((caddr_t) dst, (caddr_t) src,\ + MSKCNT*sizeof(long)) +#define CLEARBITS(buf) bzero((caddr_t) buf, MSKCNT*sizeof(long)) +#define MASKANDSETBITS(dst, b1, b2) \ + { int cri; \ + for (cri=MSKCNT; --cri>=0; ) \ + dst[cri] = (b1[cri] & b2[cri]); } +#define ORBITS(dst, b1, b2) \ + { int cri; \ + for (cri=MSKCNT; --cri>=0; ) \ + dst[cri] = (b1[cri] | b2[cri]); } +#define UNSETBITS(dst, b1) \ + { int cri; \ + for (cri=MSKCNT; --cri>=0; ) \ + dst[cri] &= ~b1[cri]; } +#if (MSKCNT==8) +#define ANYSET(src) (src[0] || src[1] || src[2] || src[3] || \ + src[4] || src[5] || src[6] || src[7]) +#endif +#endif + +#else /* not WIN32 */ + +#include +#include + +typedef fd_set FdSet; +typedef FdSet *FdSetPtr; + +#define CLEARBITS(set) FD_ZERO(&set) +#define BITSET(set,s) FD_SET(s,&set) +#define BITCLEAR(set,s) FD_CLR(s,&set) +#define GETBIT(set,s) FD_ISSET(s,&set) +#define ANYSET(set) set->fd_count + +#endif diff --git a/src/fc/fstrans.c b/src/fc/fstrans.c new file mode 100644 index 0000000..c334c25 --- /dev/null +++ b/src/fc/fstrans.c @@ -0,0 +1,28 @@ +/* + * Copyright © 2004 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#define FONT_t +#define TRANS_CLIENT +#include diff --git a/src/fontfile/Makefile.am b/src/fontfile/Makefile.am new file mode 100644 index 0000000..aa64ca5 --- /dev/null +++ b/src/fontfile/Makefile.am @@ -0,0 +1,29 @@ +INCLUDES = -I${top_srcdir}/include + +AM_CFLAGS = $(XFONT_CFLAGS) $(OS_CFLAGS) $(CWARNFLAGS) + +noinst_LTLIBRARIES = libfontfile.la + +libfontfile_la_LIBADD = \ + $(Z_LIBS) + +libfontfile_la_SOURCES = \ + bitsource.c \ + bufio.c \ + decompress.c \ + defaults.c \ + dirfile.c \ + fileio.c \ + filewr.c \ + fontdir.c \ + fontencc.c \ + fontfile.c \ + fontscale.c \ + gunzip.c \ + register.c \ + renderers.c \ + catalogue.c + +if X_BZIP2_FONT_COMPRESSION +libfontfile_la_SOURCES += bunzip2.c +endif diff --git a/src/fontfile/bitsource.c b/src/fontfile/bitsource.c new file mode 100755 index 0000000..1b79c2b --- /dev/null +++ b/src/fontfile/bitsource.c @@ -0,0 +1,171 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +BitmapSourcesRec FontFileBitmapSources; + +Bool +FontFileRegisterBitmapSource (FontPathElementPtr fpe) +{ + FontPathElementPtr *new; + int i; + int newsize; + + for (i = 0; i < FontFileBitmapSources.count; i++) + if (FontFileBitmapSources.fpe[i] == fpe) + return TRUE; + if (FontFileBitmapSources.count == FontFileBitmapSources.size) + { + newsize = FontFileBitmapSources.size + 4; + new = realloc (FontFileBitmapSources.fpe, newsize * sizeof *new); + if (!new) + return FALSE; + FontFileBitmapSources.size = newsize; + FontFileBitmapSources.fpe = new; + } + FontFileBitmapSources.fpe[FontFileBitmapSources.count++] = fpe; + return TRUE; +} + +void +FontFileUnregisterBitmapSource (FontPathElementPtr fpe) +{ + int i; + + for (i = 0; i < FontFileBitmapSources.count; i++) + if (FontFileBitmapSources.fpe[i] == fpe) + { + FontFileBitmapSources.count--; + if (FontFileBitmapSources.count == 0) + { + FontFileBitmapSources.size = 0; + free (FontFileBitmapSources.fpe); + FontFileBitmapSources.fpe = 0; + } + else + { + for (; i < FontFileBitmapSources.count; i++) + FontFileBitmapSources.fpe[i] = FontFileBitmapSources.fpe[i+1]; + } + break; + } +} + +/* + * Our set_path_hook: unregister all bitmap sources. + * This is necessary because already open fonts will keep their FPEs + * allocated, but they may not be on the new font path. + * The bitmap sources in the new path will be registered by the init_func. + */ +void +FontFileEmptyBitmapSource(void) +{ + if (FontFileBitmapSources.count == 0) + return; + + FontFileBitmapSources.count = 0; + FontFileBitmapSources.size = 0; + free (FontFileBitmapSources.fpe); + FontFileBitmapSources.fpe = 0; +} + +int +FontFileMatchBitmapSource (FontPathElementPtr fpe, + FontPtr *pFont, + int flags, + FontEntryPtr entry, + FontNamePtr zeroPat, + FontScalablePtr vals, + fsBitmapFormat format, + fsBitmapFormatMask fmask, + Bool noSpecificSize) +{ + int source; + FontEntryPtr zero; + FontBitmapEntryPtr bitmap; + int ret; + FontDirectoryPtr dir; + FontScaledPtr scaled; + + /* + * Look through all the registered bitmap sources for + * the same zero name as ours; entries along that one + * can be scaled as desired. + */ + ret = BadFontName; + for (source = 0; source < FontFileBitmapSources.count; source++) + { + if (FontFileBitmapSources.fpe[source] == fpe) + continue; + dir = (FontDirectoryPtr) FontFileBitmapSources.fpe[source]->private; + zero = FontFileFindNameInDir (&dir->scalable, zeroPat); + if (!zero) + continue; + scaled = FontFileFindScaledInstance (zero, vals, noSpecificSize); + if (scaled) + { + if (scaled->pFont) + { + *pFont = scaled->pFont; + (*pFont)->fpe = FontFileBitmapSources.fpe[source]; + ret = Successful; + } + else if (scaled->bitmap) + { + entry = scaled->bitmap; + bitmap = &entry->u.bitmap; + if (bitmap->pFont) + { + *pFont = bitmap->pFont; + (*pFont)->fpe = FontFileBitmapSources.fpe[source]; + ret = Successful; + } + else + { + ret = FontFileOpenBitmap ( + FontFileBitmapSources.fpe[source], + pFont, flags, entry, format, fmask); + if (ret == Successful && *pFont) + (*pFont)->fpe = FontFileBitmapSources.fpe[source]; + } + } + else /* "cannot" happen */ + { + ret = BadFontName; + } + break; + } + } + return ret; +} diff --git a/src/fontfile/bufio.c b/src/fontfile/bufio.c new file mode 100755 index 0000000..34b7f36 --- /dev/null +++ b/src/fontfile/bufio.c @@ -0,0 +1,203 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +BufFilePtr +BufFileCreate (char *private, + int (*input)(BufFilePtr), + int (*output)(int, BufFilePtr), + int (*skip)(BufFilePtr, int), + int (*close)(BufFilePtr, int)) +{ + BufFilePtr f; + + f = malloc (sizeof *f); + if (!f) + return 0; + f->private = private; + f->bufp = f->buffer; + f->left = 0; + f->input = input; + f->output = output; + f->skip = skip; + f->eof = 0; + f->close = close; + return f; +} + +#define FileDes(f) ((int)(long) (f)->private) + +static int +BufFileRawFill (BufFilePtr f) +{ + int left; + + left = read (FileDes(f), (char *)f->buffer, BUFFILESIZE); + if (left <= 0) { + f->left = 0; + return BUFFILEEOF; + } + f->left = left - 1; + f->bufp = f->buffer + 1; + return f->buffer[0]; +} + +static int +BufFileRawSkip (BufFilePtr f, int count) +{ + int curoff; + int fileoff; + int todo; + + curoff = f->bufp - f->buffer; + fileoff = curoff + f->left; + if (curoff + count <= fileoff) { + f->bufp += count; + f->left -= count; + } else { + todo = count - (fileoff - curoff); + if (lseek (FileDes(f), todo, 1) == -1) { + if (errno != ESPIPE) + return BUFFILEEOF; + while (todo) { + curoff = BUFFILESIZE; + if (curoff > todo) + curoff = todo; + fileoff = read (FileDes(f), (char *)f->buffer, curoff); + if (fileoff <= 0) + return BUFFILEEOF; + todo -= fileoff; + } + } + f->left = 0; + } + return count; +} + +static int +BufFileRawClose (BufFilePtr f, int doClose) +{ + if (doClose) + close (FileDes (f)); + return 1; +} + +BufFilePtr +BufFileOpenRead (int fd) +{ +#if defined (WIN32) + /* hv: I'd bet WIN32 has the same effect here */ + setmode(fd,O_BINARY); +#endif + return BufFileCreate ((char *)(long) fd, BufFileRawFill, 0, BufFileRawSkip, BufFileRawClose); +} + +static int +BufFileRawFlush (int c, BufFilePtr f) +{ + int cnt; + + if (c != BUFFILEEOF) + *f->bufp++ = c; + cnt = f->bufp - f->buffer; + f->bufp = f->buffer; + f->left = BUFFILESIZE; + if (write (FileDes(f), (char *)f->buffer, cnt) != cnt) + return BUFFILEEOF; + return c; +} + +static int +BufFileFlush (BufFilePtr f, int doClose) +{ + if (f->bufp != f->buffer) + return (*f->output) (BUFFILEEOF, f); + return 0; +} + +BufFilePtr +BufFileOpenWrite (int fd) +{ + BufFilePtr f; + +#if defined(WIN32) + /* hv: I'd bet WIN32 has the same effect here */ + setmode(fd,O_BINARY); +#endif + f = BufFileCreate ((char *)(long) fd, 0, BufFileRawFlush, 0, BufFileFlush); + f->bufp = f->buffer; + f->left = BUFFILESIZE; + return f; +} + +int +BufFileRead (BufFilePtr f, char *b, int n) +{ + int c, cnt; + cnt = n; + while (cnt--) { + c = BufFileGet (f); + if (c == BUFFILEEOF) + break; + *b++ = c; + } + return n - cnt - 1; +} + +int +BufFileWrite (BufFilePtr f, char *b, int n) +{ + int cnt; + cnt = n; + while (cnt--) { + if (BufFilePut (*b++, f) == BUFFILEEOF) + return BUFFILEEOF; + } + return n; +} + +int +BufFileClose (BufFilePtr f, int doClose) +{ + int ret; + ret = (*f->close) (f, doClose); + free (f); + return ret; +} diff --git a/src/fontfile/bunzip2.c b/src/fontfile/bunzip2.c new file mode 100755 index 0000000..d927bd5 --- /dev/null +++ b/src/fontfile/bunzip2.c @@ -0,0 +1,174 @@ +/* Based on src/fontfile/gunzip.c + written by Mark Eichin September 1996. + intended for inclusion in X11 public releases. */ + +/* + * Copyright © 2008 Sun Microsystems, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + + +#include "config.h" + +#include +#include +#include + +typedef struct _xzip_buf { + bz_stream z; + int zstat; + BufChar b[BUFFILESIZE]; + BufChar b_in[BUFFILESIZE]; + BufFilePtr f; +} xzip_buf; + +static int BufBzip2FileClose ( BufFilePtr f, int flag ); +static int BufBzip2FileFill ( BufFilePtr f ); +static int BufBzip2FileSkip ( BufFilePtr f, int c ); + +_X_HIDDEN BufFilePtr +BufFilePushBZIP2 (BufFilePtr f) +{ + xzip_buf *x; + + x = malloc (sizeof (xzip_buf)); + if (!x) return NULL; + + bzero(&(x->z), sizeof(bz_stream)); + x->f = f; + + x->zstat = BZ2_bzDecompressInit(&(x->z), + 0, /* verbosity: 0 silent, 4 max */ + 0); /* 0: go faster, 1: use less memory */ + if (x->zstat != BZ_OK) { + free(x); + return NULL; + } + + /* now that the history buffer is allocated, we provide the data buffer */ + x->z.next_out = (char *) x->b; + x->z.avail_out = BUFFILESIZE; + x->z.next_in = (char *) x->b_in; + x->z.avail_in = 0; + + return BufFileCreate((char *)x, + BufBzip2FileFill, + NULL, + BufBzip2FileSkip, + BufBzip2FileClose); +} + +static int +BufBzip2FileClose(BufFilePtr f, int flag) +{ + xzip_buf *x = (xzip_buf *)f->private; + BZ2_bzDecompressEnd (&(x->z)); + BufFileClose (x->f, flag); + free (x); + return 1; +} + +/* here's the real work. + -- we need to put stuff in f.buffer, update f.left and f.bufp, + then return the first byte (or BUFFILEEOF). + -- to do this, we need to get stuff into avail_in, and next_in, + and call BZ2_bzDecompress appropriately. + -- we may also need to add CRC maintenance - if BZ2_bzDecompress tells us + BZ_STREAM_END, we then have 4bytes CRC and 4bytes length... +*/ +static int +BufBzip2FileFill (BufFilePtr f) +{ + xzip_buf *x = (xzip_buf *)f->private; + + /* we only get called when left == 0... */ + /* but just in case, deal */ + if (f->left >= 0) { + f->left--; + return *(f->bufp++); + } + /* did we run out last time? */ + switch (x->zstat) { + case BZ_OK: + break; + case BZ_STREAM_END: + case BZ_DATA_ERROR: + case BZ_DATA_ERROR_MAGIC: + f->left = 0; + return BUFFILEEOF; + default: + return BUFFILEEOF; + } + /* now we work to consume what we can */ + /* let libbz2 know what we can handle */ + x->z.next_out = (char *) x->b; + x->z.avail_out = BUFFILESIZE; + + /* and try to consume all of it */ + while (x->z.avail_out > 0) { + /* if we don't have anything to work from... */ + if (x->z.avail_in == 0) { + /* ... fill the z buf from underlying file */ + int i, c; + for (i = 0; i < sizeof(x->b_in); i++) { + c = BufFileGet(x->f); + if (c == BUFFILEEOF) break; + x->b_in[i] = c; + } + x->z.avail_in += i; + x->z.next_in = (char *) x->b_in; + } + /* so now we have some output space and some input data */ + x->zstat = BZ2_bzDecompress(&(x->z)); + /* the inflation output happens in the f buffer directly... */ + if (x->zstat == BZ_STREAM_END) { + /* deal with EOF, crc */ + break; + } + if (x->zstat != BZ_OK) { + break; + } + } + f->bufp = x->b; + f->left = BUFFILESIZE - x->z.avail_out; + + if (f->left >= 0) { + f->left--; + return *(f->bufp++); + } else { + return BUFFILEEOF; + } +} + +/* there should be a BufCommonSkip... */ +static int +BufBzip2FileSkip (BufFilePtr f, int c) +{ + /* BufFileRawSkip returns the count unchanged. + BufCompressedSkip returns 0. + That means it probably never gets called... */ + int retval = c; + while(c--) { + int get = BufFileGet(f); + if (get == BUFFILEEOF) return get; + } + return retval; +} diff --git a/src/fontfile/catalogue.c b/src/fontfile/catalogue.c new file mode 100755 index 0000000..3a04a75 --- /dev/null +++ b/src/fontfile/catalogue.c @@ -0,0 +1,476 @@ +/* + * Copyright © 2007 Red Hat, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: + * Kristian Høgsberg + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include + +static const char CataloguePrefix[] = "catalogue:"; + +static int CatalogueFreeFPE (FontPathElementPtr fpe); + +static int +CatalogueNameCheck (char *name) +{ + return strncmp(name, CataloguePrefix, sizeof(CataloguePrefix) - 1) == 0; +} + +typedef struct _CatalogueRec { + time_t mtime; + int fpeCount, fpeAlloc; + FontPathElementPtr *fpeList; +} CatalogueRec, *CataloguePtr; + +static int +CatalogueAddFPE (CataloguePtr cat, FontPathElementPtr fpe) +{ + FontPathElementPtr *new; + + if (cat->fpeCount >= cat->fpeAlloc) + { + if (cat->fpeAlloc == 0) + cat->fpeAlloc = 16; + else + cat->fpeAlloc *= 2; + + new = realloc(cat->fpeList, cat->fpeAlloc * sizeof(FontPathElementPtr)); + if (new == NULL) + return AllocError; + + cat->fpeList = new; + } + + cat->fpeList[cat->fpeCount++] = fpe; + + return Successful; +} + +static const char PriorityAttribute[] = "pri="; + +static int +ComparePriority(const void *p1, const void *p2) +{ + FontDirectoryPtr dir1 = (*(FontPathElementPtr*) p1)->private; + FontDirectoryPtr dir2 = (*(FontPathElementPtr*) p2)->private; + const char *pri1 = NULL; + const char *pri2 = NULL; + + if (dir1->attributes != NULL) + pri1 = strstr(dir1->attributes, PriorityAttribute); + if (dir2->attributes != NULL) + pri2 = strstr(dir2->attributes, PriorityAttribute); + + if (pri1 == NULL && pri2 == NULL) + return 0; + else if (pri1 == NULL) + return 1; + else if (pri2 == NULL) + return -1; + else + return + atoi(pri1 + strlen(PriorityAttribute)) - + atoi(pri2 + strlen(PriorityAttribute)); +} + +static void +CatalogueUnrefFPEs (FontPathElementPtr fpe) +{ + CataloguePtr cat = fpe->private; + FontPathElementPtr subfpe; + int i; + + for (i = 0; i < cat->fpeCount; i++) + { + subfpe = cat->fpeList[i]; + subfpe->refcount--; + if (subfpe->refcount == 0) + { + FontFileFreeFPE (subfpe); + free(subfpe->name); + free(subfpe); + } + } + + cat->fpeCount = 0; +} + +/* Rescan catalogue directory if modified timestamp has changed or + * the forceScan argument says to do it anyway (like on first load). */ +static int +CatalogueRescan (FontPathElementPtr fpe, Bool forceScan) +{ + CataloguePtr cat = fpe->private; + char link[MAXFONTFILENAMELEN]; + char dest[MAXFONTFILENAMELEN]; + char *attrib; + FontPathElementPtr subfpe; + struct stat statbuf; + const char *path; + DIR *dir; + struct dirent *entry; + int len; + int pathlen; + + path = fpe->name + strlen(CataloguePrefix); + if (stat(path, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode)) + return BadFontPath; + + if ((forceScan == FALSE) && (statbuf.st_mtime <= cat->mtime)) + return Successful; + + dir = opendir(path); + if (dir == NULL) + { + free(cat); + return BadFontPath; + } + + CatalogueUnrefFPEs (fpe); + while (entry = readdir(dir), entry != NULL) + { + snprintf(link, sizeof link, "%s/%s", path, entry->d_name); + len = readlink(link, dest, sizeof dest - 1); + if (len < 0) + continue; + + dest[len] = '\0'; + + if (dest[0] != '/') + { + pathlen = strlen(path); + memmove(dest + pathlen + 1, dest, sizeof dest - pathlen - 1); + memcpy(dest, path, pathlen); + memcpy(dest + pathlen, "/", 1); + len += pathlen + 1; + } + + attrib = strchr(link, ':'); + if (attrib && len + strlen(attrib) < sizeof dest) + { + memcpy(dest + len, attrib, strlen(attrib)); + len += strlen(attrib); + } + + subfpe = malloc(sizeof *subfpe); + if (subfpe == NULL) + continue; + + /* The fonts returned by OpenFont will point back to the + * subfpe they come from. So set the type of the subfpe to + * what the catalogue fpe was assigned, so calls to CloseFont + * (which uses font->fpe->type) goes to CatalogueCloseFont. */ + subfpe->type = fpe->type; + subfpe->name_length = len; + subfpe->name = malloc (len + 1); + if (subfpe == NULL) + { + free(subfpe); + continue; + } + + memcpy(subfpe->name, dest, len); + subfpe->name[len] = '\0'; + + /* The X server will manipulate the subfpe ref counts + * associated with the font in OpenFont and CloseFont, so we + * have to make sure it's valid. */ + subfpe->refcount = 1; + + if (FontFileInitFPE (subfpe) != Successful) + { + free(subfpe->name); + free(subfpe); + continue; + } + + if (CatalogueAddFPE(cat, subfpe) != Successful) + { + FontFileFreeFPE (subfpe); + free(subfpe); + continue; + } + } + + closedir(dir); + + qsort(cat->fpeList, + cat->fpeCount, sizeof cat->fpeList[0], ComparePriority); + + cat->mtime = statbuf.st_mtime; + + return Successful; +} + +static int +CatalogueInitFPE (FontPathElementPtr fpe) +{ + CataloguePtr cat; + + cat = malloc(sizeof *cat); + if (cat == NULL) + return AllocError; + + fpe->private = (pointer) cat; + cat->fpeCount = 0; + cat->fpeAlloc = 0; + cat->fpeList = NULL; + cat->mtime = 0; + + return CatalogueRescan (fpe, TRUE); +} + +static int +CatalogueResetFPE (FontPathElementPtr fpe) +{ + /* Always just tell the caller to close and re-open */ + return FPEResetFailed; +} + +static int +CatalogueFreeFPE (FontPathElementPtr fpe) +{ + CataloguePtr cat = fpe->private; + + /* If the catalogue is modified while the xserver has fonts open + * from the previous subfpes, we'll unref the old subfpes when we + * reload the catalogue, and the xserver will the call FreeFPE on + * them once it drops its last reference. Thus, the FreeFPE call + * for the subfpe ends up here and we just forward it to + * FontFileFreeFPE. */ + + if (!CatalogueNameCheck (fpe->name)) + return FontFileFreeFPE (fpe); + + CatalogueUnrefFPEs (fpe); + free(cat->fpeList); + free(cat); + + return Successful; +} + +static int +CatalogueOpenFont (pointer client, FontPathElementPtr fpe, Mask flags, + char *name, int namelen, + fsBitmapFormat format, fsBitmapFormatMask fmask, + XID id, FontPtr *pFont, char **aliasName, + FontPtr non_cachable_font) +{ + CataloguePtr cat = fpe->private; + FontPathElementPtr subfpe; + FontDirectoryPtr dir; + int i, status; + + CatalogueRescan (fpe, FALSE); + + for (i = 0; i < cat->fpeCount; i++) + { + subfpe = cat->fpeList[i]; + dir = subfpe->private; + status = FontFileOpenFont(client, subfpe, flags, + name, namelen, format, fmask, id, + pFont, aliasName, non_cachable_font); + if (status == Successful || status == FontNameAlias) + return status; + } + + return BadFontName; +} + +static void +CatalogueCloseFont (FontPathElementPtr fpe, FontPtr pFont) +{ + /* Note: this gets called with the actual subfpe where we found + * the font, not the catalogue fpe. */ + + FontFileCloseFont(fpe, pFont); +} + +static int +CatalogueListFonts (pointer client, FontPathElementPtr fpe, char *pat, + int len, int max, FontNamesPtr names) +{ + CataloguePtr cat = fpe->private; + FontPathElementPtr subfpe; + FontDirectoryPtr dir; + int i; + + CatalogueRescan (fpe, FALSE); + + for (i = 0; i < cat->fpeCount; i++) + { + subfpe = cat->fpeList[i]; + dir = subfpe->private; + FontFileListFonts(client, subfpe, pat, len, max, names); + } + + return Successful; +} + +int +FontFileStartListFonts(pointer client, FontPathElementPtr fpe, + char *pat, int len, int max, + pointer *privatep, int mark_aliases); + +typedef struct _LFWIData { + pointer *privates; + int current; +} LFWIDataRec, *LFWIDataPtr; + +static int +CatalogueStartListFonts(pointer client, FontPathElementPtr fpe, + char *pat, int len, int max, pointer *privatep, + int mark_aliases) +{ + CataloguePtr cat = fpe->private; + LFWIDataPtr data; + int ret, i, j; + + CatalogueRescan (fpe, FALSE); + + data = malloc (sizeof *data + sizeof data->privates[0] * cat->fpeCount); + if (!data) + return AllocError; + data->privates = (pointer *) (data + 1); + + for (i = 0; i < cat->fpeCount; i++) + { + ret = FontFileStartListFonts(client, cat->fpeList[i], pat, len, + max, &data->privates[i], mark_aliases); + if (ret != Successful) + goto bail; + } + + data->current = 0; + *privatep = (pointer) data; + return Successful; + + bail: + for (j = 0; j < i; j++) + /* FIXME: we have no way to free the per-fpe privates. */; + free (data); + + return AllocError; +} + +static int +CatalogueStartListFontsWithInfo(pointer client, FontPathElementPtr fpe, + char *pat, int len, int max, + pointer *privatep) +{ + return CatalogueStartListFonts(client, fpe, pat, len, max, privatep, 0); +} + +static int +CatalogueListNextFontWithInfo(pointer client, FontPathElementPtr fpe, + char **namep, int *namelenp, + FontInfoPtr *pFontInfo, + int *numFonts, pointer private) +{ + LFWIDataPtr data = private; + CataloguePtr cat = fpe->private; + int ret; + + if (data->current == cat->fpeCount) + { + free(data); + return BadFontName; + } + + ret = FontFileListNextFontWithInfo(client, cat->fpeList[data->current], + namep, namelenp, + pFontInfo, numFonts, + data->privates[data->current]); + if (ret == BadFontName) + { + data->current++; + return CatalogueListNextFontWithInfo(client, fpe, namep, namelenp, + pFontInfo, numFonts, private); + } + + return ret; +} + +static int +CatalogueStartListFontsAndAliases(pointer client, FontPathElementPtr fpe, + char *pat, int len, int max, + pointer *privatep) +{ + return CatalogueStartListFonts(client, fpe, pat, len, max, privatep, 1); +} + +static int +CatalogueListNextFontOrAlias(pointer client, FontPathElementPtr fpe, + char **namep, int *namelenp, char **resolvedp, + int *resolvedlenp, pointer private) +{ + LFWIDataPtr data = private; + CataloguePtr cat = fpe->private; + int ret; + + if (data->current == cat->fpeCount) + { + free(data); + return BadFontName; + } + + ret = FontFileListNextFontOrAlias(client, cat->fpeList[data->current], + namep, namelenp, + resolvedp, resolvedlenp, + data->privates[data->current]); + if (ret == BadFontName) + { + data->current++; + return CatalogueListNextFontOrAlias(client, fpe, namep, namelenp, + resolvedp, resolvedlenp, private); + } + + return ret; +} + +void +CatalogueRegisterLocalFpeFunctions (void) +{ + RegisterFPEFunctions(CatalogueNameCheck, + CatalogueInitFPE, + CatalogueFreeFPE, + CatalogueResetFPE, + CatalogueOpenFont, + CatalogueCloseFont, + CatalogueListFonts, + CatalogueStartListFontsWithInfo, + CatalogueListNextFontWithInfo, + NULL, + NULL, + NULL, + CatalogueStartListFontsAndAliases, + CatalogueListNextFontOrAlias, + FontFileEmptyBitmapSource); +} diff --git a/src/fontfile/decompress.c b/src/fontfile/decompress.c new file mode 100755 index 0000000..b1fc37b --- /dev/null +++ b/src/fontfile/decompress.c @@ -0,0 +1,408 @@ +/* + * Copyright 1985, 1986 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * James A. Woods, derived from original work by Spencer Thomas + * and Joseph Orost. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* + * decompress - cat a compressed file + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +#define BITS 16 + +/* + * a code_int must be able to hold 2**BITS values of type int, and also -1 + */ +#if BITS > 15 +typedef long int code_int; +#else +typedef int code_int; +#endif + +typedef long int count_int; + +#ifdef NO_UCHAR + typedef char char_type; +#else + typedef unsigned char char_type; +#endif /* UCHAR */ + +static char_type magic_header[] = { "\037\235" }; /* 1F 9D */ + +/* Defines for third byte of header */ +#define BIT_MASK 0x1f +#define BLOCK_MASK 0x80 +/* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is + a fourth header byte (for expansion). +*/ + +#define INIT_BITS 9 /* initial number of bits/code */ + +#ifdef COMPATIBLE /* But wrong! */ +# define MAXCODE(n_bits) (1 << (n_bits) - 1) +#else +# define MAXCODE(n_bits) ((1 << (n_bits)) - 1) +#endif /* COMPATIBLE */ + +/* + * the next two codes should not be changed lightly, as they must not + * lie within the contiguous general code space. + */ +#define FIRST 257 /* first free entry */ +#define CLEAR 256 /* table clear output code */ + +#define STACK_SIZE 8192 + +typedef struct _compressedFILE { + BufFilePtr file; + + char_type *stackp; + code_int oldcode; + char_type finchar; + + int block_compress; + int maxbits; + code_int maxcode, maxmaxcode; + + code_int free_ent; + int clear_flg; + int n_bits; + + /* bit buffer */ + int offset, size; + char_type buf[BITS]; + + char_type de_stack[STACK_SIZE]; + char_type *tab_suffix; + unsigned short *tab_prefix; +} CompressedFile; + + +static int hsize_table[] = { + 5003, /* 12 bits - 80% occupancy */ + 9001, /* 13 bits - 91% occupancy */ + 18013, /* 14 bits - 91% occupancy */ + 35023, /* 15 bits - 94% occupancy */ + 69001 /* 16 bits - 95% occupancy */ +}; + +static int BufCompressedClose ( BufFilePtr f, int doClose ); +static int BufCompressedFill ( BufFilePtr f ); +static code_int getcode ( CompressedFile *file ); +static int BufCompressedSkip ( BufFilePtr f, int bytes ); + +BufFilePtr +BufFilePushCompressed (BufFilePtr f) +{ + int code; + int maxbits; + int hsize; + CompressedFile *file; + int extra; + + if ((BufFileGet(f) != (magic_header[0] & 0xFF)) || + (BufFileGet(f) != (magic_header[1] & 0xFF))) + { + return 0; + } + code = BufFileGet (f); + if (code == BUFFILEEOF) return 0; + + maxbits = code & BIT_MASK; + if (maxbits > BITS || maxbits < 12) + return 0; + hsize = hsize_table[maxbits - 12]; + extra = (1 << maxbits) * sizeof (char_type) + + hsize * sizeof (unsigned short); + file = malloc (sizeof (CompressedFile) + extra); + if (!file) + return 0; + file->file = f; + file->maxbits = maxbits; + file->block_compress = code & BLOCK_MASK; + file->maxmaxcode = 1 << file->maxbits; + file->tab_suffix = (char_type *) &file[1]; + file->tab_prefix = (unsigned short *) (file->tab_suffix + file->maxmaxcode); + /* + * As above, initialize the first 256 entries in the table. + */ + file->maxcode = MAXCODE(file->n_bits = INIT_BITS); + for ( code = 255; code >= 0; code-- ) { + file->tab_prefix[code] = 0; + file->tab_suffix[code] = (char_type) code; + } + file->free_ent = ((file->block_compress) ? FIRST : 256 ); + file->clear_flg = 0; + file->offset = 0; + file->size = 0; + file->stackp = file->de_stack; + bzero(file->buf, BITS); + file->finchar = file->oldcode = getcode (file); + if (file->oldcode != -1) + *file->stackp++ = file->finchar; + return BufFileCreate ((char *) file, + BufCompressedFill, + 0, + BufCompressedSkip, + BufCompressedClose); +} + +static int +BufCompressedClose (BufFilePtr f, int doClose) +{ + CompressedFile *file; + BufFilePtr raw; + + file = (CompressedFile *) f->private; + raw = file->file; + free (file); + BufFileClose (raw, doClose); + return 1; +} + +static int +BufCompressedFill (BufFilePtr f) +{ + CompressedFile *file; + register char_type *stackp, *de_stack; + register char_type finchar; + register code_int code, oldcode, incode; + BufChar *buf, *bufend; + + file = (CompressedFile *) f->private; + + buf = f->buffer; + bufend = buf + BUFFILESIZE; + stackp = file->stackp; + de_stack = file->de_stack; + finchar = file->finchar; + oldcode = file->oldcode; + while (buf < bufend) { + while (stackp > de_stack && buf < bufend) + *buf++ = *--stackp; + + if (buf == bufend) + break; + + if (oldcode == -1) + break; + + code = getcode (file); + if (code == -1) + break; + + if ( (code == CLEAR) && file->block_compress ) { + for ( code = 255; code >= 0; code-- ) + file->tab_prefix[code] = 0; + file->clear_flg = 1; + file->free_ent = FIRST - 1; + if ( (code = getcode (file)) == -1 ) /* O, untimely death! */ + break; + } + incode = code; + /* + * Special case for KwKwK string. + */ + if ( code >= file->free_ent ) { + *stackp++ = finchar; + code = oldcode; + } + + /* + * Generate output characters in reverse order + */ + while ( code >= 256 ) + { + *stackp++ = file->tab_suffix[code]; + code = file->tab_prefix[code]; + } + finchar = file->tab_suffix[code]; + *stackp++ = finchar; + + /* + * Generate the new entry. + */ + if ( (code=file->free_ent) < file->maxmaxcode ) { + file->tab_prefix[code] = (unsigned short)oldcode; + file->tab_suffix[code] = finchar; + file->free_ent = code+1; + } + /* + * Remember previous code. + */ + oldcode = incode; + } + file->oldcode = oldcode; + file->stackp = stackp; + file->finchar = finchar; + if (buf == f->buffer) { + f->left = 0; + return BUFFILEEOF; + } + f->bufp = f->buffer + 1; + f->left = (buf - f->buffer) - 1; + return f->buffer[0]; +} + +/***************************************************************** + * TAG( getcode ) + * + * Read one code from the standard input. If BUFFILEEOF, return -1. + * Inputs: + * stdin + * Outputs: + * code or -1 is returned. + */ + +static char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; + +static code_int +getcode(CompressedFile *file) +{ + register code_int code; + register int r_off, bits; + register char_type *bp = file->buf; + register BufFilePtr raw; + + if ( file->clear_flg > 0 || file->offset >= file->size || + file->free_ent > file->maxcode ) + { + /* + * If the next entry will be too big for the current code + * size, then we must increase the size. This implies reading + * a new buffer full, too. + */ + if ( file->free_ent > file->maxcode ) { + file->n_bits++; + if ( file->n_bits == file->maxbits ) + file->maxcode = file->maxmaxcode; /* won't get any bigger now */ + else + file->maxcode = MAXCODE(file->n_bits); + } + if ( file->clear_flg > 0) { + file->maxcode = MAXCODE (file->n_bits = INIT_BITS); + file->clear_flg = 0; + } + bits = file->n_bits; + raw = file->file; + while (bits > 0 && (code = BufFileGet (raw)) != BUFFILEEOF) + { + *bp++ = code; + --bits; + } + bp = file->buf; + if (bits == file->n_bits) + return -1; /* end of file */ + file->size = file->n_bits - bits; + file->offset = 0; + /* Round size down to integral number of codes */ + file->size = (file->size << 3) - (file->n_bits - 1); + } + r_off = file->offset; + bits = file->n_bits; + /* + * Get to the first byte. + */ + bp += (r_off >> 3); + r_off &= 7; + /* Get first part (low order bits) */ +#ifdef NO_UCHAR + code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff; +#else + code = (*bp++ >> r_off); +#endif /* NO_UCHAR */ + bits -= (8 - r_off); + r_off = 8 - r_off; /* now, offset into code word */ + /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ + if ( bits >= 8 ) { +#ifdef NO_UCHAR + code |= (*bp++ & 0xff) << r_off; +#else + code |= *bp++ << r_off; +#endif /* NO_UCHAR */ + r_off += 8; + bits -= 8; + } + /* high order bits. */ + code |= (*bp & rmask[bits]) << r_off; + file->offset += file->n_bits; + + return code; +} + +static int +BufCompressedSkip (BufFilePtr f, int bytes) +{ + int c; + while (bytes--) + { + c = BufFileGet(f); + if (c == BUFFILEEOF) + return BUFFILEEOF; + } + return 0; +} + +#ifdef TEST +int +main (int argc, char *argv[]) +{ + BufFilePtr inputraw, input, output; + int c; + + inputraw = BufFileOpenRead (0); + input = BufFilePushCompressed (inputraw); + output = BufFileOpenWrite (1); + while ((c = BufFileGet (input)) != BUFFILEEOF) + BufFilePut (c, output); + BufFileClose (input, FALSE); + BufFileClose (output, FALSE); + return 0; +} +#endif diff --git a/src/fontfile/defaults.c b/src/fontfile/defaults.c new file mode 100755 index 0000000..1ad7d7c --- /dev/null +++ b/src/fontfile/defaults.c @@ -0,0 +1,74 @@ +/* + +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +#ifndef DEFAULT_BIT_ORDER +#ifdef BITMAP_BIT_ORDER +#define DEFAULT_BIT_ORDER BITMAP_BIT_ORDER +#else +#define DEFAULT_BIT_ORDER MSBFirst +#endif +#endif + +#ifndef DEFAULT_BYTE_ORDER +#ifdef IMAGE_BYTE_ORDER +#define DEFAULT_BYTE_ORDER IMAGE_BYTE_ORDER +#else +#define DEFAULT_BYTE_ORDER MSBFirst +#endif +#endif + +#ifndef DEFAULT_GLYPH_PAD +#ifdef GLYPHPADBYTES +#define DEFAULT_GLYPH_PAD GLYPHPADBYTES +#else +#define DEFAULT_GLYPH_PAD 4 +#endif +#endif + +#ifndef DEFAULT_SCAN_UNIT +#define DEFAULT_SCAN_UNIT 1 +#endif + +#include + +void +FontDefaultFormat (int *bit, int *byte, int *glyph, int *scan) +{ + *bit = DEFAULT_BIT_ORDER; + *byte = DEFAULT_BYTE_ORDER; + *glyph = DEFAULT_GLYPH_PAD; + *scan = DEFAULT_SCAN_UNIT; +} diff --git a/src/fontfile/dirfile.c b/src/fontfile/dirfile.c new file mode 100755 index 0000000..c8aff6f --- /dev/null +++ b/src/fontfile/dirfile.c @@ -0,0 +1,492 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +/* + * dirfile.c + * + * Read fonts.dir and fonts.alias files + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include + +static Bool AddFileNameAliases ( FontDirectoryPtr dir ); +static int ReadFontAlias ( char *directory, Bool isFile, + FontDirectoryPtr *pdir ); +static int lexAlias ( FILE *file, char **lexToken ); +static int lexc ( FILE *file ); + +int +FontFileReadDirectory (char *directory, FontDirectoryPtr *pdir) +{ + char file_name[MAXFONTFILENAMELEN]; + char font_name[MAXFONTNAMELEN]; + char dir_file[MAXFONTFILENAMELEN]; + char dir_path[MAXFONTFILENAMELEN]; + char *ptr; + FILE *file; + int count, + num_fonts, + status; + struct stat statb; + static char format[24] = ""; +#if defined(WIN32) + int i; +#endif + + FontDirectoryPtr dir = NullFontDirectory; + + if (strlen(directory) + 1 + sizeof(FontDirFile) > sizeof(dir_file)) + return BadFontPath; + + /* Check for font directory attributes */ +#if !defined(WIN32) + if ((ptr = strchr(directory, ':'))) { +#else + /* OS/2 and WIN32 path might start with a drive letter, don't clip this */ + if ((ptr = strchr(directory+2, ':'))) { +#endif + strncpy(dir_path, directory, ptr - directory); + dir_path[ptr - directory] = '\0'; + } else { + strcpy(dir_path, directory); + } + strcpy(dir_file, dir_path); + if (dir_file[strlen(dir_file) - 1] != '/') + strcat(dir_file, "/"); + strcat(dir_file, FontDirFile); + file = fopen(dir_file, "rt"); + if (file) { +#ifndef WIN32 + if (fstat (fileno(file), &statb) == -1) +#else + if (stat (dir_file, &statb) == -1) +#endif + { + fclose(file); + return BadFontPath; + } + count = fscanf(file, "%d\n", &num_fonts); + if ((count == EOF) || (count != 1)) { + fclose(file); + return BadFontPath; + } + dir = FontFileMakeDir(directory, num_fonts); + if (dir == NULL) { + fclose(file); + return BadFontPath; + } + dir->dir_mtime = statb.st_mtime; + if (format[0] == '\0') + sprintf(format, "%%%ds %%%d[^\n]\n", + MAXFONTFILENAMELEN-1, MAXFONTNAMELEN-1); + + while ((count = fscanf(file, format, file_name, font_name)) != EOF) { +#if defined(WIN32) + /* strip any existing trailing CR */ + for (i=0; idirectory) + sizeof(FontDirFile) > sizeof(dir_file)) + return FALSE; + + strcpy (dir_file, dir->directory); + strcat (dir_file, FontDirFile); + if (stat (dir_file, &statb) == -1) + { + if (errno != ENOENT || dir->dir_mtime != 0) + return TRUE; + return FALSE; /* doesn't exist and never did: no change */ + } + if (dir->dir_mtime != statb.st_mtime) + return TRUE; + + if ((strlen(dir->directory) + sizeof(FontAliasFile)) > sizeof(dir_file)) + return FALSE; + strcpy (dir_file, dir->directory); + strcat (dir_file, FontAliasFile); + if (stat (dir_file, &statb) == -1) + { + if (errno != ENOENT || dir->alias_mtime != 0) + return TRUE; + return FALSE; /* doesn't exist and never did: no change */ + } + if (dir->alias_mtime != statb.st_mtime) + return TRUE; + return FALSE; +} + +/* + * Make each of the file names an automatic alias for each of the files. + */ + +static Bool +AddFileNameAliases(FontDirectoryPtr dir) +{ + int i; + char copy[MAXFONTFILENAMELEN]; + char *fileName; + FontTablePtr table; + FontRendererPtr renderer; + int len; + FontNameRec name; + + table = &dir->nonScalable; + for (i = 0; i < table->used; i++) { + if (table->entries[i].type != FONT_ENTRY_BITMAP) + continue; + fileName = table->entries[i].u.bitmap.fileName; + renderer = FontFileMatchRenderer (fileName); + if (!renderer) + continue; + + len = strlen (fileName) - renderer->fileSuffixLen; + if (len >= sizeof(copy)) + continue; + CopyISOLatin1Lowered (copy, fileName, len); + copy[len] = '\0'; + name.name = copy; + name.length = len; + name.ndashes = FontFileCountDashes (copy, len); + + if (!FontFileFindNameInDir(table, &name)) { + if (!FontFileAddFontAlias (dir, copy, table->entries[i].name.name)) + return FALSE; + } + } + return TRUE; +} + +/* + * parse the font.alias file. Format is: + * + * alias font-name + * + * To imbed white-space in an alias name, enclose it like "font name" + * in double quotes. \ escapes and character, so + * "font name \"With Double Quotes\" \\ and \\ back-slashes" + * works just fine. + * + * A line beginning with a ! denotes a newline-terminated comment. + */ + +/* + * token types + */ + +#define NAME 0 +#define NEWLINE 1 +#define DONE 2 +#define EALLOC 3 + +static int +ReadFontAlias(char *directory, Bool isFile, FontDirectoryPtr *pdir) +{ + char alias[MAXFONTNAMELEN]; + char font_name[MAXFONTNAMELEN]; + char alias_file[MAXFONTFILENAMELEN]; + FILE *file; + FontDirectoryPtr dir; + int token; + char *lexToken; + int status = Successful; + struct stat statb; + + if (strlen(directory) >= sizeof(alias_file)) + return BadFontPath; + dir = *pdir; + strcpy(alias_file, directory); + if (!isFile) { + if (strlen(directory) + 1 + sizeof(FontAliasFile) > sizeof(alias_file)) + return BadFontPath; + if (directory[strlen(directory) - 1] != '/') + strcat(alias_file, "/"); + strcat(alias_file, FontAliasFile); + } + file = fopen(alias_file, "rt"); + if (!file) + return ((errno == ENOENT) ? Successful : BadFontPath); + if (!dir) + *pdir = dir = FontFileMakeDir(directory, 10); + if (!dir) + { + fclose (file); + return AllocError; + } +#ifndef WIN32 + if (fstat (fileno (file), &statb) == -1) +#else + if (stat (alias_file, &statb) == -1) +#endif + { + fclose (file); + return BadFontPath; + } + dir->alias_mtime = statb.st_mtime; + while (status == Successful) { + token = lexAlias(file, &lexToken); + switch (token) { + case NEWLINE: + break; + case DONE: + fclose(file); + return Successful; + case EALLOC: + status = AllocError; + break; + case NAME: + if (strlen(lexToken) >= sizeof(alias)) { + status = BadFontPath; + break; + } + strcpy(alias, lexToken); + token = lexAlias(file, &lexToken); + switch (token) { + case NEWLINE: + if (strcmp(alias, "FILE_NAMES_ALIASES")) + status = BadFontPath; + else if (!AddFileNameAliases(dir)) + status = AllocError; + break; + case DONE: + status = BadFontPath; + break; + case EALLOC: + status = AllocError; + break; + case NAME: + if (strlen(lexToken) >= sizeof(font_name)) { + status = BadFontPath; + break; + } + CopyISOLatin1Lowered(alias, alias, strlen(alias)); + CopyISOLatin1Lowered(font_name, lexToken, strlen(lexToken)); + if (!FontFileAddFontAlias (dir, alias, font_name)) + status = AllocError; + break; + } + } + } + fclose(file); + return status; +} + +#define QUOTE 0 +#define WHITE 1 +#define NORMAL 2 +#define END 3 +#define NL 4 +#define BANG 5 + +static int charClass; + +static int +lexAlias(FILE *file, char **lexToken) +{ + int c; + char *t; + enum state { + Begin, Normal, Quoted, Comment + } state; + int count; + + static char *tokenBuf = (char *) NULL; + static int tokenSize = 0; + + t = tokenBuf; + count = 0; + state = Begin; + for (;;) { + if (count == tokenSize) { + int nsize; + char *nbuf; + + nsize = tokenSize ? (tokenSize << 1) : 64; + nbuf = realloc(tokenBuf, nsize); + if (!nbuf) + return EALLOC; + tokenBuf = nbuf; + tokenSize = nsize; + t = tokenBuf + count; + } + c = lexc(file); + switch (charClass) { + case QUOTE: + switch (state) { + case Begin: + case Normal: + state = Quoted; + break; + case Quoted: + state = Normal; + break; + case Comment: + break; + } + break; + case WHITE: + switch (state) { + case Begin: + case Comment: + continue; + case Normal: + *t = '\0'; + *lexToken = tokenBuf; + return NAME; + case Quoted: + break; + } + /* fall through */ + case NORMAL: + switch (state) { + case Begin: + state = Normal; + break; + case Comment: + continue; + default: + break; + } + *t++ = c; + ++count; + break; + case END: + case NL: + switch (state) { + case Begin: + case Comment: + *lexToken = (char *) NULL; + return charClass == END ? DONE : NEWLINE; + default: + *t = '\0'; + *lexToken = tokenBuf; + ungetc(c, file); + return NAME; + } + break; + case BANG: + switch (state) { + case Begin: + state = Comment; + break; + case Comment: + break; + default: + *t++ = c; + ++count; + } + break; + } + } +} + +static int +lexc(FILE *file) +{ + int c; + + c = getc(file); + switch (c) { + case EOF: + charClass = END; + break; + case '\\': + c = getc(file); + if (c == EOF) + charClass = END; + else + charClass = NORMAL; + break; + case '"': + charClass = QUOTE; + break; + case ' ': + case '\t': + charClass = WHITE; + break; + case '\r': + case '\n': + charClass = NL; + break; + case '!': + charClass = BANG; + break; + default: + charClass = NORMAL; + break; + } + return c; +} diff --git a/src/fontfile/fileio.c b/src/fontfile/fileio.c new file mode 100755 index 0000000..80af511 --- /dev/null +++ b/src/fontfile/fileio.c @@ -0,0 +1,91 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#ifndef O_BINARY +#define O_BINARY O_RDONLY +#endif + +FontFilePtr +FontFileOpen (const char *name) +{ + int fd; + int len; + BufFilePtr raw, cooked; + + fd = open (name, O_BINARY); + if (fd < 0) + return 0; + raw = BufFileOpenRead (fd); + if (!raw) + { + close (fd); + return 0; + } + len = strlen (name); + if (len > 2 && !strcmp (name + len - 2, ".Z")) { + cooked = BufFilePushCompressed (raw); + if (!cooked) { + BufFileClose (raw, TRUE); + return 0; + } + raw = cooked; +#ifdef X_GZIP_FONT_COMPRESSION + } else if (len > 3 && !strcmp (name + len - 3, ".gz")) { + cooked = BufFilePushZIP (raw); + if (!cooked) { + BufFileClose (raw, TRUE); + return 0; + } + raw = cooked; +#endif +#ifdef X_BZIP2_FONT_COMPRESSION + } else if (len > 4 && !strcmp (name + len - 4, ".bz2")) { + cooked = BufFilePushBZIP2 (raw); + if (!cooked) { + BufFileClose (raw, TRUE); + return 0; + } + raw = cooked; +#endif + } + return (FontFilePtr) raw; +} + +int +FontFileClose (FontFilePtr f) +{ + return BufFileClose ((BufFilePtr) f, TRUE); +} + diff --git a/src/fontfile/filewr.c b/src/fontfile/filewr.c new file mode 100755 index 0000000..bcc7b1e --- /dev/null +++ b/src/fontfile/filewr.c @@ -0,0 +1,62 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +FontFilePtr +FontFileOpenWrite (const char *name) +{ + int fd; + +#if defined(WIN32) || defined(__CYGWIN__) + fd = open (name, O_CREAT|O_TRUNC|O_RDWR|O_BINARY, 0666); +#else + fd = creat (name, 0666); +#endif + if (fd < 0) + return 0; + return (FontFilePtr) BufFileOpenWrite (fd); +} + +FontFilePtr +FontFileOpenWriteFd (int fd) +{ + return (FontFilePtr) BufFileOpenWrite (fd); +} + +FontFilePtr +FontFileOpenFd (int fd) +{ + return (FontFilePtr) BufFileOpenRead (fd); +} diff --git a/src/fontfile/fontdir.c b/src/fontfile/fontdir.c new file mode 100755 index 0000000..e052bb3 --- /dev/null +++ b/src/fontfile/fontdir.c @@ -0,0 +1,825 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +#if HAVE_STDINT_H +#include +#elif !defined(INT32_MAX) +#define INT32_MAX 0x7fffffff +#endif + +Bool +FontFileInitTable (FontTablePtr table, int size) +{ + if (size < 0 || (size > INT32_MAX/sizeof(FontEntryRec))) + return FALSE; + if (size) + { + table->entries = malloc(sizeof(FontEntryRec) * size); + if (!table->entries) + return FALSE; + } + else + table->entries = 0; + table->used = 0; + table->size = size; + table->sorted = FALSE; + return TRUE; +} + +void +FontFileFreeEntry (FontEntryPtr entry) +{ + FontScalableExtraPtr extra; + int i; + + if (entry->name.name) + free(entry->name.name); + entry->name.name = NULL; + + switch (entry->type) + { + case FONT_ENTRY_SCALABLE: + free (entry->u.scalable.fileName); + extra = entry->u.scalable.extra; + for (i = 0; i < extra->numScaled; i++) + if (extra->scaled[i].vals.ranges) + free (extra->scaled[i].vals.ranges); + free (extra->scaled); + free (extra); + break; + case FONT_ENTRY_BITMAP: + free (entry->u.bitmap.fileName); + entry->u.bitmap.fileName = NULL; + break; + case FONT_ENTRY_ALIAS: + free (entry->u.alias.resolved); + entry->u.alias.resolved = NULL; + break; + } +} + +void +FontFileFreeTable (FontTablePtr table) +{ + int i; + + for (i = 0; i < table->used; i++) + FontFileFreeEntry (&table->entries[i]); + free (table->entries); +} + +FontDirectoryPtr +FontFileMakeDir(char *dirName, int size) +{ + FontDirectoryPtr dir; + int dirlen; + int needslash = 0; + char *attrib; + int attriblen; + +#if !defined(WIN32) + attrib = strchr(dirName, ':'); +#else + /* OS/2 uses the colon in the drive letter descriptor, skip this */ + attrib = strchr(dirName+2, ':'); +#endif + if (attrib) { + dirlen = attrib - dirName; + attriblen = strlen(attrib); + } else { + dirlen = strlen(dirName); + attriblen = 0; + } + if (dirName[dirlen - 1] != '/') +#ifdef NCD + if (dirlen) /* leave out slash for builtins */ +#endif + needslash = 1; + dir = malloc(sizeof *dir + dirlen + needslash + 1 + + (attriblen ? attriblen + 1 : 0)); + if (!dir) + return (FontDirectoryPtr)0; + if (!FontFileInitTable (&dir->scalable, 0)) + { + free (dir); + return (FontDirectoryPtr)0; + } + if (!FontFileInitTable (&dir->nonScalable, size)) + { + FontFileFreeTable (&dir->scalable); + free (dir); + return (FontDirectoryPtr)0; + } + dir->directory = (char *) (dir + 1); + dir->dir_mtime = 0; + dir->alias_mtime = 0; + if (attriblen) + dir->attributes = dir->directory + dirlen + needslash + 1; + else + dir->attributes = NULL; + strncpy(dir->directory, dirName, dirlen); + dir->directory[dirlen] = '\0'; + if (dir->attributes) + strcpy(dir->attributes, attrib); + if (needslash) + strcat(dir->directory, "/"); + return dir; +} + +void +FontFileFreeDir (FontDirectoryPtr dir) +{ + FontFileFreeTable (&dir->scalable); + FontFileFreeTable (&dir->nonScalable); + free(dir); +} + +FontEntryPtr +FontFileAddEntry(FontTablePtr table, FontEntryPtr prototype) +{ + FontEntryPtr entry; + int newsize; + + /* can't add entries to a sorted table, pointers get broken! */ + if (table->sorted) + return (FontEntryPtr) 0; /* "cannot" happen */ + if (table->used == table->size) { + newsize = table->size + 100; + entry = realloc(table->entries, newsize * sizeof(FontEntryRec)); + if (!entry) + return (FontEntryPtr)0; + table->size = newsize; + table->entries = entry; + } + entry = &table->entries[table->used]; + *entry = *prototype; + entry->name.name = malloc(prototype->name.length + 1); + if (!entry->name.name) + return (FontEntryPtr)0; + memcpy (entry->name.name, prototype->name.name, prototype->name.length); + entry->name.name[entry->name.length] = '\0'; + table->used++; + return entry; +} + +/* + * Compare two strings just like strcmp, but preserve decimal integer + * sorting order, i.e. "2" < "10" or "iso8859-2" < "iso8859-10" < + * "iso10646-1". Strings are sorted as if sequences of digits were + * prefixed by a length indicator (i.e., does not ignore leading zeroes). + * + * Markus Kuhn + */ +#define Xisdigit(c) ('\060' <= (c) && (c) <= '\071') + +static int strcmpn(const char *s1, const char *s2) +{ + int digits, predigits = 0; + const char *ss1, *ss2; + + while (1) { + if (*s1 == 0 && *s2 == 0) + return 0; + digits = Xisdigit(*s1) && Xisdigit(*s2); + if (digits && !predigits) { + ss1 = s1; + ss2 = s2; + while (Xisdigit(*ss1) && Xisdigit(*ss2)) + ss1++, ss2++; + if (!Xisdigit(*ss1) && Xisdigit(*ss2)) + return -1; + if (Xisdigit(*ss1) && !Xisdigit(*ss2)) + return 1; + } + if ((unsigned char)*s1 < (unsigned char)*s2) + return -1; + if ((unsigned char)*s1 > (unsigned char)*s2) + return 1; + predigits = digits; + s1++, s2++; + } +} + + +static int +FontFileNameCompare(const void* a, const void* b) +{ + FontEntryPtr a_name = (FontEntryPtr) a, + b_name = (FontEntryPtr) b; + + return strcmpn(a_name->name.name, b_name->name.name); +} + +void +FontFileSortTable (FontTablePtr table) +{ + if (!table->sorted) { + qsort((char *) table->entries, table->used, sizeof(FontEntryRec), + FontFileNameCompare); + table->sorted = TRUE; + } +} + +void +FontFileSortDir(FontDirectoryPtr dir) +{ + FontFileSortTable (&dir->scalable); + FontFileSortTable (&dir->nonScalable); + /* now that the table is fixed in size, swizzle the pointers */ + FontFileSwitchStringsToBitmapPointers (dir); +} + +/* + Given a Font Table, SetupWildMatch() sets up various pointers and state + information so the table can be searched for name(s) that match a given + fontname pattern -- which may contain wildcards. Under certain + circumstances, SetupWildMatch() will find the one table entry that + matches the pattern. If those circumstances do not pertain, + SetupWildMatch() returns a range within the the table that should be + searched for matching name(s). With the information established by + SetupWildMatch(), including state information in "private", the + PatternMatch() procedure is then used to test names in the range for a + match. +*/ + +#define isWild(c) ((c) == XK_asterisk || (c) == XK_question) +#define isDigit(c) (XK_0 <= (c) && (c) <= XK_9) + +static int +SetupWildMatch(FontTablePtr table, FontNamePtr pat, + int *leftp, int *rightp, int *privatep) +{ + int nDashes; + char c; + char *t; + char *firstWild; + char *firstDigit; + int first; + int center, + left, + right; + int result; + char *name; + + name = pat->name; + nDashes = pat->ndashes; + firstWild = 0; + firstDigit = 0; + t = name; + while ((c = *t++)) { + if (isWild(c)) { + if (!firstWild) + firstWild = t - 1; + } + if (isDigit(c)) { + if (!firstDigit) + firstDigit = t - 1; + } + } + left = 0; + right = table->used; + if (firstWild) + *privatep = nDashes; + else + *privatep = -1; + if (!table->sorted) { + *leftp = left; + *rightp = right; + return -1; + } else if (firstWild) { + if (firstDigit && firstDigit < firstWild) + first = firstDigit - name; + else + first = firstWild - name; + while (left < right) { + center = (left + right) / 2; + result = strncmp(name, table->entries[center].name.name, first); + if (result == 0) + break; + if (result < 0) + right = center; + else + left = center + 1; + } + *leftp = left; + *rightp = right; + return -1; + } else { + while (left < right) { + center = (left + right) / 2; + result = strcmpn(name, table->entries[center].name.name); + if (result == 0) + return center; + if (result < 0) + right = center; + else + left = center + 1; + } + *leftp = 1; + *rightp = 0; + return -1; + } +} + +static int +PatternMatch(char *pat, int patdashes, char *string, int stringdashes) +{ + char c, + t; + + if (stringdashes < patdashes) + return 0; + for (;;) { + switch (c = *pat++) { + case '*': + if (!(c = *pat++)) + return 1; + if (c == XK_minus) { + patdashes--; + for (;;) { + while ((t = *string++) != XK_minus) + if (!t) + return 0; + stringdashes--; + if (PatternMatch(pat, patdashes, string, stringdashes)) + return 1; + if (stringdashes == patdashes) + return 0; + } + } else { + for (;;) { + while ((t = *string++) != c) { + if (!t) + return 0; + if (t == XK_minus) { + if (stringdashes-- < patdashes) + return 0; + } + } + if (PatternMatch(pat, patdashes, string, stringdashes)) + return 1; + } + } + case '?': + if (*string++ == XK_minus) + stringdashes--; + break; + case '\0': + return (*string == '\0'); + case XK_minus: + if (*string++ == XK_minus) { + patdashes--; + stringdashes--; + break; + } + return 0; + default: + if (c == *string++) + break; + return 0; + } + } +} + +int +FontFileCountDashes (char *name, int namelen) +{ + int ndashes = 0; + + while (namelen--) + if (*name++ == '\055') /* avoid non ascii systems */ + ++ndashes; + return ndashes; +} + +char * +FontFileSaveString (char *s) +{ + char *n; + + n = malloc (strlen (s) + 1); + if (!n) + return 0; + strcpy (n, s); + return n; +} + +FontEntryPtr +FontFileFindNameInScalableDir(FontTablePtr table, FontNamePtr pat, + FontScalablePtr vals) +{ + int i, + start, + stop, + res, + private; + FontNamePtr name; + + if (!table->entries) + return NULL; + if ((i = SetupWildMatch(table, pat, &start, &stop, &private)) >= 0) + return &table->entries[i]; + for (i = start; i < stop; i++) { + name = &table->entries[i].name; + res = PatternMatch(pat->name, private, name->name, name->ndashes); + if (res > 0) + { + /* Check to see if enhancements requested are available */ + if (vals) + { + int vs = vals->values_supplied; + int cap; + + if (table->entries[i].type == FONT_ENTRY_SCALABLE) + cap = table->entries[i].u.scalable.renderer->capabilities; + else if (table->entries[i].type == FONT_ENTRY_ALIAS) + cap = ~0; /* Calling code will have to see if true */ + else + cap = 0; + if ((((vs & PIXELSIZE_MASK) == PIXELSIZE_ARRAY || + (vs & POINTSIZE_MASK) == POINTSIZE_ARRAY) && + !(cap & CAP_MATRIX)) || + ((vs & CHARSUBSET_SPECIFIED) && + !(cap & CAP_CHARSUBSETTING))) + continue; + } + return &table->entries[i]; + } + if (res < 0) + break; + } + return (FontEntryPtr)0; +} + +FontEntryPtr +FontFileFindNameInDir(FontTablePtr table, FontNamePtr pat) +{ + return FontFileFindNameInScalableDir(table, pat, (FontScalablePtr)0); +} + +int +FontFileFindNamesInScalableDir(FontTablePtr table, FontNamePtr pat, int max, + FontNamesPtr names, FontScalablePtr vals, + int alias_behavior, int *newmax) +{ + int i, + start, + stop, + res, + private; + int ret = Successful; + FontEntryPtr fname; + FontNamePtr name; + + if (max <= 0) + return Successful; + if ((i = SetupWildMatch(table, pat, &start, &stop, &private)) >= 0) { + if (alias_behavior == NORMAL_ALIAS_BEHAVIOR || + table->entries[i].type != FONT_ENTRY_ALIAS) + { + name = &table->entries[i].name; + if (newmax) *newmax = max - 1; + return AddFontNamesName(names, name->name, name->length); + } + start = i; + stop = i + 1; + } + for (i = start, fname = &table->entries[start]; i < stop; i++, fname++) { + res = PatternMatch(pat->name, private, fname->name.name, fname->name.ndashes); + if (res > 0) { + if (vals) + { + int vs = vals->values_supplied; + int cap; + + if (fname->type == FONT_ENTRY_SCALABLE) + cap = fname->u.scalable.renderer->capabilities; + else if (fname->type == FONT_ENTRY_ALIAS) + cap = ~0; /* Calling code will have to see if true */ + else + cap = 0; + if ((((vs & PIXELSIZE_MASK) == PIXELSIZE_ARRAY || + (vs & POINTSIZE_MASK) == POINTSIZE_ARRAY) && + !(cap & CAP_MATRIX)) || + ((vs & CHARSUBSET_SPECIFIED) && + !(cap & CAP_CHARSUBSETTING))) + continue; + } + + if ((alias_behavior & IGNORE_SCALABLE_ALIASES) && + fname->type == FONT_ENTRY_ALIAS) + { + FontScalableRec tmpvals; + if (FontParseXLFDName (fname->name.name, &tmpvals, + FONT_XLFD_REPLACE_NONE) && + !(tmpvals.values_supplied & SIZE_SPECIFY_MASK)) + continue; + } + + ret = AddFontNamesName(names, fname->name.name, fname->name.length); + if (ret != Successful) + goto bail; + + /* If alias_behavior is LIST_ALIASES_AND_TARGET_NAMES, mark + this entry as an alias by negating its length and follow + it by the resolved name */ + if ((alias_behavior & LIST_ALIASES_AND_TARGET_NAMES) && + fname->type == FONT_ENTRY_ALIAS) + { + names->length[names->nnames - 1] = + -names->length[names->nnames - 1]; + ret = AddFontNamesName(names, fname->u.alias.resolved, + strlen(fname->u.alias.resolved)); + if (ret != Successful) + goto bail; + } + + if (--max <= 0) + break; + } else if (res < 0) + break; + } + bail: ; + if (newmax) *newmax = max; + return ret; +} + +int +FontFileFindNamesInDir(FontTablePtr table, FontNamePtr pat, + int max, FontNamesPtr names) +{ + return FontFileFindNamesInScalableDir(table, pat, max, names, + (FontScalablePtr)0, + NORMAL_ALIAS_BEHAVIOR, (int *)0); +} + +Bool +FontFileMatchName(char *name, int length, FontNamePtr pat) +{ + /* Perform a fontfile-type name match on a single name */ + FontTableRec table; + FontEntryRec entries[1]; + + /* Dummy up a table */ + table.used = 1; + table.size = 1; + table.sorted = TRUE; + table.entries = entries; + entries[0].name.name = name; + entries[0].name.length = length; + entries[0].name.ndashes = FontFileCountDashes(name, length); + + return FontFileFindNameInDir(&table, pat) != (FontEntryPtr)0; +} + +/* + * Add a font file to a directory. This handles bitmap and + * scalable names both + */ + +Bool +FontFileAddFontFile (FontDirectoryPtr dir, char *fontName, char *fileName) +{ + FontEntryRec entry; + FontScalableRec vals, zeroVals; + FontRendererPtr renderer; + FontEntryPtr existing; + FontScalableExtraPtr extra; + FontEntryPtr bitmap = 0, scalable; + Bool isscale; + Bool scalable_xlfd; + + renderer = FontFileMatchRenderer (fileName); + if (!renderer) + return FALSE; + entry.name.length = strlen (fontName); + if (entry.name.length > MAXFONTNAMELEN) + entry.name.length = MAXFONTNAMELEN; + entry.name.name = fontName; + CopyISOLatin1Lowered (entry.name.name, fontName, entry.name.length); + entry.name.ndashes = FontFileCountDashes (entry.name.name, entry.name.length); + entry.name.name[entry.name.length] = '\0'; + /* + * Add a bitmap name if the incoming name isn't an XLFD name, or + * if it isn't a scalable name (i.e. non-zero scalable fields) + * + * If name of bitmapped font contains XLFD enhancements, do not add + * a scalable version of the name... this can lead to confusion and + * ambiguity between the font name and the field enhancements. + */ + isscale = entry.name.ndashes == 14 && + FontParseXLFDName(entry.name.name, + &vals, FONT_XLFD_REPLACE_NONE) && + (vals.values_supplied & PIXELSIZE_MASK) != PIXELSIZE_ARRAY && + (vals.values_supplied & POINTSIZE_MASK) != POINTSIZE_ARRAY && + !(vals.values_supplied & ENHANCEMENT_SPECIFY_MASK); +#define UNSCALED_ATTRIB "unscaled" + scalable_xlfd = (isscale && + (((vals.values_supplied & PIXELSIZE_MASK) == 0) || + ((vals.values_supplied & POINTSIZE_MASK) == 0))); + /* + * For scalable fonts without a scalable XFLD, check if the "unscaled" + * attribute is present. + */ + if (isscale && !scalable_xlfd && + dir->attributes && dir->attributes[0] == ':') { + char *ptr1 = dir->attributes + 1; + char *ptr2; + int length; + int uslength = strlen(UNSCALED_ATTRIB); + + do { + ptr2 = strchr(ptr1, ':'); + if (ptr2) + length = ptr2 - ptr1; + else + length = dir->attributes + strlen(dir->attributes) - ptr1; + if (length == uslength && !strncmp(ptr1, UNSCALED_ATTRIB, uslength)) + isscale = FALSE; + if (ptr2) + ptr1 = ptr2 + 1; + } while (ptr2); + } + if (!isscale || (vals.values_supplied & SIZE_SPECIFY_MASK)) + { + /* + * If the renderer doesn't support OpenBitmap, FontFileOpenFont + * will still do the right thing. + */ + entry.type = FONT_ENTRY_BITMAP; + entry.u.bitmap.renderer = renderer; + entry.u.bitmap.pFont = NullFont; + if (!(entry.u.bitmap.fileName = FontFileSaveString (fileName))) + return FALSE; + if (!(bitmap = FontFileAddEntry (&dir->nonScalable, &entry))) + { + free (entry.u.bitmap.fileName); + return FALSE; + } + } + /* + * Parse out scalable fields from XLFD names - a scalable name + * just gets inserted, a scaled name has more things to do. + */ + if (isscale) + { + if (vals.values_supplied & SIZE_SPECIFY_MASK) + { + bzero((char *)&zeroVals, sizeof(zeroVals)); + zeroVals.x = vals.x; + zeroVals.y = vals.y; + zeroVals.values_supplied = PIXELSIZE_SCALAR | POINTSIZE_SCALAR; + FontParseXLFDName (entry.name.name, &zeroVals, + FONT_XLFD_REPLACE_VALUE); + entry.name.length = strlen (entry.name.name); + existing = FontFileFindNameInDir (&dir->scalable, &entry.name); + if (existing) + { + if ((vals.values_supplied & POINTSIZE_MASK) == + POINTSIZE_SCALAR && + (int)(vals.point_matrix[3] * 10) == GetDefaultPointSize()) + { + existing->u.scalable.extra->defaults = vals; + + free (existing->u.scalable.fileName); + if (!(existing->u.scalable.fileName = FontFileSaveString (fileName))) + return FALSE; + } + if(bitmap) + { + FontFileCompleteXLFD(&vals, &vals); + FontFileAddScaledInstance (existing, &vals, NullFont, + bitmap->name.name); + return TRUE; + } + } + } + if (!(entry.u.scalable.fileName = FontFileSaveString (fileName))) + return FALSE; + extra = malloc (sizeof (FontScalableExtraRec)); + if (!extra) + { + free (entry.u.scalable.fileName); + return FALSE; + } + bzero((char *)&extra->defaults, sizeof(extra->defaults)); + if ((vals.values_supplied & POINTSIZE_MASK) == POINTSIZE_SCALAR && + (int)(vals.point_matrix[3] * 10) == GetDefaultPointSize()) + extra->defaults = vals; + else + { + FontResolutionPtr resolution; + int num; + int default_point_size = GetDefaultPointSize(); + + extra->defaults.point_matrix[0] = + extra->defaults.point_matrix[3] = + (double)default_point_size / 10.0; + extra->defaults.point_matrix[1] = + extra->defaults.point_matrix[2] = 0.0; + extra->defaults.values_supplied = + POINTSIZE_SCALAR | PIXELSIZE_UNDEFINED; + extra->defaults.width = -1; + if (vals.x <= 0 || vals.y <= 0) + { + resolution = GetClientResolutions (&num); + if (resolution && num > 0) + { + extra->defaults.x = resolution->x_resolution; + extra->defaults.y = resolution->y_resolution; + } + else + { + extra->defaults.x = 75; + extra->defaults.y = 75; + } + } + else + { + extra->defaults.x = vals.x; + extra->defaults.y = vals.y; + } + FontFileCompleteXLFD (&extra->defaults, &extra->defaults); + } + extra->numScaled = 0; + extra->sizeScaled = 0; + extra->scaled = 0; + extra->private = 0; + entry.type = FONT_ENTRY_SCALABLE; + entry.u.scalable.renderer = renderer; + entry.u.scalable.extra = extra; + if (!(scalable = FontFileAddEntry (&dir->scalable, &entry))) + { + free (extra); + free (entry.u.scalable.fileName); + return FALSE; + } + if (vals.values_supplied & SIZE_SPECIFY_MASK) + { + if(bitmap) + { + FontFileCompleteXLFD(&vals, &vals); + FontFileAddScaledInstance (scalable, &vals, NullFont, + bitmap->name.name); + } + } + } + return TRUE; +} + +Bool +FontFileAddFontAlias (FontDirectoryPtr dir, char *aliasName, char *fontName) +{ + FontEntryRec entry; + + if (strcmp(aliasName,fontName) == 0) { + /* Don't allow an alias to point to itself and create a loop */ + return FALSE; + } + entry.name.length = strlen (aliasName); + CopyISOLatin1Lowered (aliasName, aliasName, entry.name.length); + entry.name.name = aliasName; + entry.name.ndashes = FontFileCountDashes (entry.name.name, entry.name.length); + entry.type = FONT_ENTRY_ALIAS; + if (!(entry.u.alias.resolved = FontFileSaveString (fontName))) + return FALSE; + if (!FontFileAddEntry (&dir->nonScalable, &entry)) + { + free (entry.u.alias.resolved); + return FALSE; + } + return TRUE; +} diff --git a/src/fontfile/fontencc.c b/src/fontfile/fontencc.c new file mode 100755 index 0000000..7997785 --- /dev/null +++ b/src/fontfile/fontencc.c @@ -0,0 +1,76 @@ +/* +Copyright (c) 1998-2001 by Juliusz Chroboczek + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/* Binary compatibility code. */ + +/* This file includes code to make modules compiled for earlier + versions of the fontenc interfaces link with this one. It does + *not* provide source compatibility, as many of the data structures + now have different names. */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +extern void ErrorF(const char *f, ...); + +char * +font_encoding_from_xlfd(const char * name, int length) +{ + return FontEncFromXLFD(name, length); +} + +FontEncPtr +font_encoding_find(const char *encoding_name, const char *filename) +{ + return FontEncFind(encoding_name, filename); +} + +unsigned +font_encoding_recode(unsigned code, + FontEncPtr encoding, FontMapPtr mapping) +{ + if(encoding != mapping->encoding) { + ErrorF("Inconsistent mapping/encoding\n"); + return 0; + } + return FontEncRecode(code, mapping); +} + +char * +font_encoding_name(unsigned code, + FontEncPtr encoding, FontMapPtr mapping) +{ + if(encoding != mapping->encoding) { + ErrorF("Inconsistent mapping/encoding\n"); + return 0; + } + return FontEncName(code, mapping); +} + +char ** +identifyEncodingFile(const char *filename) +{ + return FontEncIdentify(filename); +} diff --git a/src/fontfile/fontfile.c b/src/fontfile/fontfile.c new file mode 100755 index 0000000..eb37a87 --- /dev/null +++ b/src/fontfile/fontfile.c @@ -0,0 +1,1136 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#ifdef WIN32 +#include +#endif + +static unsigned char +ISOLatin1ToLower(unsigned char source) +{ + if (source >= XK_A && source <= XK_Z) + return source + (XK_a - XK_A); + if (source >= XK_Agrave && source <= XK_Odiaeresis) + return source + (XK_agrave - XK_Agrave); + if (source >= XK_Ooblique && source <= XK_Thorn) + return source + (XK_oslash - XK_Ooblique); + return source; +} + +_X_HIDDEN void +CopyISOLatin1Lowered(char *dest, char *source, int length) +{ + int i; + for (i = 0; i < length; i++, source++, dest++) + *dest = ISOLatin1ToLower(*source); + *dest = '\0'; +} + +/* + * Map FPE functions to renderer functions + */ + +static int FontFileOpenBitmapNCF (FontPathElementPtr fpe, FontPtr *pFont, + int flags, FontEntryPtr entry, + fsBitmapFormat format, + fsBitmapFormatMask fmask, + FontPtr non_cachable_font); + +int +FontFileNameCheck (char *name) +{ +#ifndef NCD +#if defined(WIN32) + /* OS/2 uses D:/... as a path name for fonts, so accept this as a valid + * path if it starts with a letter and a colon. Same applies for WIN32 + */ + if (isalpha(*name) && name[1]==':') + return TRUE; +#endif + return *name == '/'; +#else + return ((strcmp(name, "built-ins") == 0) || (*name == '/')); +#endif +} + +int +FontFileInitFPE (FontPathElementPtr fpe) +{ + int status; + FontDirectoryPtr dir; + + status = FontFileReadDirectory (fpe->name, &dir); + if (status == Successful) + { + if (dir->nonScalable.used > 0) + if (!FontFileRegisterBitmapSource (fpe)) + { + FontFileFreeFPE (fpe); + return AllocError; + } + fpe->private = (pointer) dir; + } + return status; +} + +/* ARGSUSED */ +int +FontFileResetFPE (FontPathElementPtr fpe) +{ + FontDirectoryPtr dir; + + dir = (FontDirectoryPtr) fpe->private; + /* + * The reset must fail for bitmap fonts because they get cleared when + * the path is set. + */ + if (FontFileDirectoryChanged (dir)) + { + /* can't do it, so tell the caller to close and re-open */ + return FPEResetFailed; + } + else + { + if (dir->nonScalable.used > 0) + if (!FontFileRegisterBitmapSource (fpe)) + { + return FPEResetFailed; + } + return Successful; + } +} + +int +FontFileFreeFPE (FontPathElementPtr fpe) +{ + FontFileUnregisterBitmapSource (fpe); + FontFileFreeDir ((FontDirectoryPtr) fpe->private); + return Successful; +} + +static int +transfer_values_to_alias(char *entryname, int entrynamelength, + char *resolvedname, + char **aliasName, FontScalablePtr vals) +{ + static char aliasname[MAXFONTNAMELEN]; + int nameok = 1, len; + char lowerName[MAXFONTNAMELEN]; + + *aliasName = resolvedname; + if ((len = strlen(*aliasName)) <= MAXFONTNAMELEN && + (entrynamelength < MAXFONTNAMELEN) && + FontFileCountDashes (*aliasName, len) == 14) + { + FontScalableRec tmpVals; + FontScalableRec tmpVals2; + + tmpVals2 = *vals; + + /* If we're aliasing a scalable name, transfer values + from the name into the destination alias, multiplying + by matrices that appear in the alias. */ + + CopyISOLatin1Lowered (lowerName, entryname, + entrynamelength); + lowerName[entrynamelength] = '\0'; + + if (FontParseXLFDName(lowerName, &tmpVals, + FONT_XLFD_REPLACE_NONE) && + !tmpVals.values_supplied && + FontParseXLFDName(*aliasName, &tmpVals, + FONT_XLFD_REPLACE_NONE)) + { + double *matrix = 0, tempmatrix[4]; + + /* Use a matrix iff exactly one is defined */ + if ((tmpVals.values_supplied & PIXELSIZE_MASK) == + PIXELSIZE_ARRAY && + !(tmpVals.values_supplied & POINTSIZE_MASK)) + matrix = tmpVals.pixel_matrix; + else if ((tmpVals.values_supplied & POINTSIZE_MASK) == + POINTSIZE_ARRAY && + !(tmpVals.values_supplied & PIXELSIZE_MASK)) + matrix = tmpVals.point_matrix; + + /* If matrix given in the alias, compute new point + and/or pixel matrices */ + if (matrix) + { + /* Complete the XLFD name to avoid potential + gotchas */ + if (FontFileCompleteXLFD(&tmpVals2, &tmpVals2)) + { + tempmatrix[0] = + matrix[0] * tmpVals2.point_matrix[0] + + matrix[1] * tmpVals2.point_matrix[2]; + tempmatrix[1] = + matrix[0] * tmpVals2.point_matrix[1] + + matrix[1] * tmpVals2.point_matrix[3]; + tempmatrix[2] = + matrix[2] * tmpVals2.point_matrix[0] + + matrix[3] * tmpVals2.point_matrix[2]; + tempmatrix[3] = + matrix[2] * tmpVals2.point_matrix[1] + + matrix[3] * tmpVals2.point_matrix[3]; + tmpVals2.point_matrix[0] = tempmatrix[0]; + tmpVals2.point_matrix[1] = tempmatrix[1]; + tmpVals2.point_matrix[2] = tempmatrix[2]; + tmpVals2.point_matrix[3] = tempmatrix[3]; + + tempmatrix[0] = + matrix[0] * tmpVals2.pixel_matrix[0] + + matrix[1] * tmpVals2.pixel_matrix[2]; + tempmatrix[1] = + matrix[0] * tmpVals2.pixel_matrix[1] + + matrix[1] * tmpVals2.pixel_matrix[3]; + tempmatrix[2] = + matrix[2] * tmpVals2.pixel_matrix[0] + + matrix[3] * tmpVals2.pixel_matrix[2]; + tempmatrix[3] = + matrix[2] * tmpVals2.pixel_matrix[1] + + matrix[3] * tmpVals2.pixel_matrix[3]; + tmpVals2.pixel_matrix[0] = tempmatrix[0]; + tmpVals2.pixel_matrix[1] = tempmatrix[1]; + tmpVals2.pixel_matrix[2] = tempmatrix[2]; + tmpVals2.pixel_matrix[3] = tempmatrix[3]; + + tmpVals2.values_supplied = + (tmpVals2.values_supplied & + ~(PIXELSIZE_MASK | POINTSIZE_MASK)) | + PIXELSIZE_ARRAY | POINTSIZE_ARRAY; + } + else + nameok = 0; + } + + CopyISOLatin1Lowered (aliasname, *aliasName, len + 1); + if (nameok && FontParseXLFDName(aliasname, &tmpVals2, + FONT_XLFD_REPLACE_VALUE)) + /* Return a version of the aliasname that has + had the vals stuffed into it. To avoid + memory leak, this alias name lives in a + static buffer. The caller needs to be done + with this buffer before this procedure is + called again to avoid reentrancy problems. */ + *aliasName = aliasname; + } + } + return nameok; +} + +/* ARGSUSED */ +int +FontFileOpenFont (pointer client, FontPathElementPtr fpe, Mask flags, + char *name, int namelen, + fsBitmapFormat format, fsBitmapFormatMask fmask, + XID id, FontPtr *pFont, char **aliasName, + FontPtr non_cachable_font) +{ + FontDirectoryPtr dir; + char lowerName[MAXFONTNAMELEN]; + char fileName[MAXFONTFILENAMELEN*2 + 1]; + FontNameRec tmpName; + FontEntryPtr entry; + FontScalableRec vals; + FontScalableEntryPtr scalable; + FontScaledPtr scaled; + FontBitmapEntryPtr bitmap; + int ret; + Bool noSpecificSize; + int nranges; + fsRange *ranges; + + if (namelen >= MAXFONTNAMELEN) + return AllocError; + dir = (FontDirectoryPtr) fpe->private; + + /* Match non-scalable pattern */ + CopyISOLatin1Lowered (lowerName, name, namelen); + lowerName[namelen] = '\0'; + ranges = FontParseRanges(lowerName, &nranges); + tmpName.name = lowerName; + tmpName.length = namelen; + tmpName.ndashes = FontFileCountDashes (lowerName, namelen); + if (!FontParseXLFDName(lowerName, &vals, FONT_XLFD_REPLACE_NONE)) + bzero(&vals, sizeof(vals)); + if (!(entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName)) && + tmpName.ndashes == 14 && + FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO)) + { + tmpName.length = strlen(lowerName); + entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName); + } + + if (entry) + { + switch (entry->type) { + case FONT_ENTRY_BITMAP: + bitmap = &entry->u.bitmap; + if (bitmap->pFont) + { + *pFont = bitmap->pFont; + (*pFont)->fpe = fpe; + ret = Successful; + } + else + { + ret = FontFileOpenBitmapNCF (fpe, pFont, flags, entry, format, + fmask, non_cachable_font); + if (ret == Successful && *pFont) + (*pFont)->fpe = fpe; + } + break; + case FONT_ENTRY_ALIAS: + vals.nranges = nranges; + vals.ranges = ranges; + transfer_values_to_alias(entry->name.name, entry->name.length, + entry->u.alias.resolved, aliasName, &vals); + ret = FontNameAlias; + break; + default: + ret = BadFontName; + } + } + else + { + ret = BadFontName; + } + + if (ret != BadFontName) + { + if (ranges) free(ranges); + return ret; + } + + /* Match XLFD patterns */ + CopyISOLatin1Lowered (lowerName, name, namelen); + lowerName[namelen] = '\0'; + tmpName.name = lowerName; + tmpName.length = namelen; + tmpName.ndashes = FontFileCountDashes (lowerName, namelen); + if (!FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO) || + !(tmpName.length = strlen (lowerName), + entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName, + &vals))) { + CopyISOLatin1Lowered (lowerName, name, namelen); + lowerName[namelen] = '\0'; + tmpName.name = lowerName; + tmpName.length = namelen; + tmpName.ndashes = FontFileCountDashes (lowerName, namelen); + entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName, &vals); + if (entry) + { + strcpy(lowerName, entry->name.name); + tmpName.name = lowerName; + tmpName.length = entry->name.length; + tmpName.ndashes = entry->name.ndashes; + } + } + + if (entry) + { + noSpecificSize = FALSE; /* TRUE breaks XLFD enhancements */ + if (entry->type == FONT_ENTRY_SCALABLE && + FontFileCompleteXLFD (&vals, &entry->u.scalable.extra->defaults)) + { + scalable = &entry->u.scalable; + if ((vals.values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY || + (vals.values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY || + (vals.values_supplied & + ~SIZE_SPECIFY_MASK & ~CHARSUBSET_SPECIFIED)) + scaled = 0; + else + scaled = FontFileFindScaledInstance (entry, &vals, + noSpecificSize); + /* + * A scaled instance can occur one of two ways: + * + * Either the font has been scaled to this + * size already, in which case scaled->pFont + * will point at that font. + * + * Or a bitmap instance in this size exists, + * which is handled as if we got a pattern + * matching the bitmap font name. + */ + if (scaled) + { + if (scaled->pFont) + { + *pFont = scaled->pFont; + (*pFont)->fpe = fpe; + ret = Successful; + } + else if (scaled->bitmap) + { + entry = scaled->bitmap; + bitmap = &entry->u.bitmap; + if (bitmap->pFont) + { + *pFont = bitmap->pFont; + (*pFont)->fpe = fpe; + ret = Successful; + } + else + { + ret = FontFileOpenBitmapNCF (fpe, pFont, flags, entry, + format, fmask, + non_cachable_font); + if (ret == Successful && *pFont) + (*pFont)->fpe = fpe; + } + } + else /* "cannot" happen */ + { + ret = BadFontName; + } + } + else + { + ret = FontFileMatchBitmapSource (fpe, pFont, flags, entry, &tmpName, &vals, format, fmask, noSpecificSize); + if (ret != Successful) + { + char origName[MAXFONTNAMELEN]; + + CopyISOLatin1Lowered (origName, name, namelen); + origName[namelen] = '\0'; + + /* Pass the original XLFD name in the vals + structure; the rasterizer is free to examine it + for hidden meanings. This information will not + be saved in the scaled-instances table. */ + + vals.xlfdName = origName; + vals.ranges = ranges; + vals.nranges = nranges; + + if (strlen(dir->directory) + strlen(scalable->fileName) >= + sizeof(fileName)) { + ret = BadFontName; + } else { + strcpy (fileName, dir->directory); + strcat (fileName, scalable->fileName); + if (scalable->renderer->OpenScalable) { + ret = (*scalable->renderer->OpenScalable) (fpe, pFont, + flags, entry, fileName, &vals, format, fmask, + non_cachable_font); + } + else if (scalable->renderer->OpenBitmap) { + ret = (*scalable->renderer->OpenBitmap) (fpe, pFont, + flags, entry, fileName, format, fmask, + non_cachable_font); + } + } + + /* In case rasterizer does something bad because of + charset subsetting... */ + if (ret == Successful && + ((*pFont)->info.firstCol > (*pFont)->info.lastCol || + (*pFont)->info.firstRow > (*pFont)->info.lastRow)) + { + (*(*pFont)->unload_font)(*pFont); + ret = BadFontName; + } + /* Save the instance */ + if (ret == Successful) + { + if (FontFileAddScaledInstance (entry, &vals, + *pFont, (char *) 0)) + ranges = 0; + else + (*pFont)->fpePrivate = (pointer) 0; + (*pFont)->fpe = fpe; + } + } + } + } + } + else + ret = BadFontName; + + if (ranges) + free(ranges); + return ret; +} + +/* ARGSUSED */ +void +FontFileCloseFont (FontPathElementPtr fpe, FontPtr pFont) +{ + FontEntryPtr entry; + + if ((entry = (FontEntryPtr) pFont->fpePrivate)) { + switch (entry->type) { + case FONT_ENTRY_SCALABLE: + FontFileRemoveScaledInstance (entry, pFont); + break; + case FONT_ENTRY_BITMAP: + entry->u.bitmap.pFont = 0; + break; + default: + /* "cannot" happen */ + break; + } + pFont->fpePrivate = 0; + } + (*pFont->unload_font) (pFont); +} + +static int +FontFileOpenBitmapNCF (FontPathElementPtr fpe, FontPtr *pFont, + int flags, FontEntryPtr entry, + fsBitmapFormat format, fsBitmapFormatMask fmask, + FontPtr non_cachable_font) +{ + FontBitmapEntryPtr bitmap; + char fileName[MAXFONTFILENAMELEN*2+1]; + int ret; + FontDirectoryPtr dir; + + dir = (FontDirectoryPtr) fpe->private; + bitmap = &entry->u.bitmap; + if(!bitmap || !bitmap->renderer->OpenBitmap) + return BadFontName; + if (strlen(dir->directory) + strlen(bitmap->fileName) >= sizeof(fileName)) + return BadFontName; + strcpy (fileName, dir->directory); + strcat (fileName, bitmap->fileName); + ret = (*bitmap->renderer->OpenBitmap) + (fpe, pFont, flags, entry, fileName, format, fmask, + non_cachable_font); + if (ret == Successful) + { + bitmap->pFont = *pFont; + (*pFont)->fpePrivate = (pointer) entry; + } + return ret; +} + +int +FontFileOpenBitmap (FontPathElementPtr fpe, FontPtr *pFont, + int flags, FontEntryPtr entry, + fsBitmapFormat format, fsBitmapFormatMask fmask) +{ + return FontFileOpenBitmapNCF (fpe, pFont, flags, entry, format, fmask, + (FontPtr)0); +} + +static int +FontFileGetInfoBitmap (FontPathElementPtr fpe, FontInfoPtr pFontInfo, + FontEntryPtr entry) +{ + FontBitmapEntryPtr bitmap; + char fileName[MAXFONTFILENAMELEN*2+1]; + int ret; + FontDirectoryPtr dir; + + dir = (FontDirectoryPtr) fpe->private; + bitmap = &entry->u.bitmap; + if (!bitmap || !bitmap->renderer->GetInfoBitmap) + return BadFontName; + if (strlen(dir->directory) + strlen(bitmap->fileName) >= sizeof(fileName)) + return BadFontName; + strcpy (fileName, dir->directory); + strcat (fileName, bitmap->fileName); + ret = (*bitmap->renderer->GetInfoBitmap) (fpe, pFontInfo, entry, fileName); + return ret; +} + +static void +_FontFileAddScalableNames(FontNamesPtr names, FontNamesPtr scaleNames, + FontNamePtr nameptr, char *zeroChars, + FontScalablePtr vals, fsRange *ranges, + int nranges, int *max) +{ + int i; + FontScalableRec zeroVals, tmpVals; + for (i = 0; i < scaleNames->nnames; i++) + { + char nameChars[MAXFONTNAMELEN]; + if (!*max) + return; + FontParseXLFDName (scaleNames->names[i], &zeroVals, + FONT_XLFD_REPLACE_NONE); + tmpVals = *vals; + if (FontFileCompleteXLFD (&tmpVals, &zeroVals)) + { + --*max; + + strcpy (nameChars, scaleNames->names[i]); + if ((vals->values_supplied & PIXELSIZE_MASK) || + !(vals->values_supplied & PIXELSIZE_WILDCARD) || + vals->y == 0) + { + tmpVals.values_supplied = + (tmpVals.values_supplied & ~PIXELSIZE_MASK) | + (vals->values_supplied & PIXELSIZE_MASK); + tmpVals.pixel_matrix[0] = vals->pixel_matrix[0]; + tmpVals.pixel_matrix[1] = vals->pixel_matrix[1]; + tmpVals.pixel_matrix[2] = vals->pixel_matrix[2]; + tmpVals.pixel_matrix[3] = vals->pixel_matrix[3]; + } + if ((vals->values_supplied & POINTSIZE_MASK) || + !(vals->values_supplied & POINTSIZE_WILDCARD) || + vals->y == 0) + { + tmpVals.values_supplied = + (tmpVals.values_supplied & ~POINTSIZE_MASK) | + (vals->values_supplied & POINTSIZE_MASK); + tmpVals.point_matrix[0] = vals->point_matrix[0]; + tmpVals.point_matrix[1] = vals->point_matrix[1]; + tmpVals.point_matrix[2] = vals->point_matrix[2]; + tmpVals.point_matrix[3] = vals->point_matrix[3]; + } + if (vals->width <= 0) + tmpVals.width = 0; + if (vals->x == 0) + tmpVals.x = 0; + if (vals->y == 0) + tmpVals.y = 0; + tmpVals.ranges = ranges; + tmpVals.nranges = nranges; + FontParseXLFDName (nameChars, &tmpVals, + FONT_XLFD_REPLACE_VALUE); + /* If we're marking aliases with negative lengths, we + need to concoct a valid target name to follow it. + Otherwise we're done. */ + if (scaleNames->length[i] >= 0) + { + (void) AddFontNamesName (names, nameChars, + strlen (nameChars)); + /* If our original pattern matches the name from + the table and that name doesn't duplicate what + we just added, add the name from the table */ + if (strcmp(nameChars, scaleNames->names[i]) && + FontFileMatchName(scaleNames->names[i], + scaleNames->length[i], + nameptr) && + *max) + { + --*max; + (void) AddFontNamesName (names, scaleNames->names[i], + scaleNames->length[i]); + } + } + else + { + char *aliasName; + vals->ranges = ranges; + vals->nranges = nranges; + if (transfer_values_to_alias(zeroChars, + strlen(zeroChars), + scaleNames->names[++i], + &aliasName, vals)) + { + (void) AddFontNamesName (names, nameChars, + strlen (nameChars)); + names->length[names->nnames - 1] = + -names->length[names->nnames - 1]; + (void) AddFontNamesName (names, aliasName, + strlen (aliasName)); + /* If our original pattern matches the name from + the table and that name doesn't duplicate what + we just added, add the name from the table */ + if (strcmp(nameChars, scaleNames->names[i - 1]) && + FontFileMatchName(scaleNames->names[i - 1], + -scaleNames->length[i - 1], + nameptr) && + *max) + { + --*max; + (void) AddFontNamesName (names, + scaleNames->names[i - 1], + -scaleNames->length[i - 1]); + names->length[names->nnames - 1] = + -names->length[names->nnames - 1]; + (void) AddFontNamesName (names, aliasName, + strlen (aliasName)); + } + } + } + } + } +} + +/* ARGSUSED */ +static int +_FontFileListFonts (pointer client, FontPathElementPtr fpe, + char *pat, int len, int max, FontNamesPtr names, + int mark_aliases) +{ + FontDirectoryPtr dir; + char lowerChars[MAXFONTNAMELEN], zeroChars[MAXFONTNAMELEN]; + FontNameRec lowerName; + FontNameRec zeroName; + FontNamesPtr scaleNames; + FontScalableRec vals; + fsRange *ranges; + int nranges; + int result = BadFontName; + + if (len >= MAXFONTNAMELEN) + return AllocError; + dir = (FontDirectoryPtr) fpe->private; + CopyISOLatin1Lowered (lowerChars, pat, len); + lowerChars[len] = '\0'; + lowerName.name = lowerChars; + lowerName.length = len; + lowerName.ndashes = FontFileCountDashes (lowerChars, len); + + /* Match XLFD patterns */ + + strcpy (zeroChars, lowerChars); + if (lowerName.ndashes == 14 && + FontParseXLFDName (zeroChars, &vals, FONT_XLFD_REPLACE_ZERO)) + { + ranges = FontParseRanges(lowerChars, &nranges); + result = FontFileFindNamesInScalableDir (&dir->nonScalable, + &lowerName, max, names, + (FontScalablePtr)0, + (mark_aliases ? + LIST_ALIASES_AND_TARGET_NAMES : + NORMAL_ALIAS_BEHAVIOR) | + IGNORE_SCALABLE_ALIASES, + &max); + zeroName.name = zeroChars; + zeroName.length = strlen (zeroChars); + zeroName.ndashes = lowerName.ndashes; + + /* Look for scalable names and aliases, adding scaled instances of + them to the output */ + + /* Scalable names... */ + scaleNames = MakeFontNamesRecord (0); + if (!scaleNames) + { + if (ranges) free(ranges); + return AllocError; + } + FontFileFindNamesInScalableDir (&dir->scalable, &zeroName, max, + scaleNames, &vals, + mark_aliases ? + LIST_ALIASES_AND_TARGET_NAMES : + NORMAL_ALIAS_BEHAVIOR, (int *)0); + _FontFileAddScalableNames(names, scaleNames, &lowerName, + zeroChars, &vals, ranges, nranges, + &max); + FreeFontNames (scaleNames); + + /* Scalable aliases... */ + scaleNames = MakeFontNamesRecord (0); + if (!scaleNames) + { + if (ranges) free(ranges); + return AllocError; + } + FontFileFindNamesInScalableDir (&dir->nonScalable, &zeroName, + max, scaleNames, &vals, + mark_aliases ? + LIST_ALIASES_AND_TARGET_NAMES : + NORMAL_ALIAS_BEHAVIOR, (int *)0); + _FontFileAddScalableNames(names, scaleNames, &lowerName, + zeroChars, &vals, ranges, nranges, + &max); + FreeFontNames (scaleNames); + + if (ranges) free(ranges); + } + else + { + result = FontFileFindNamesInScalableDir (&dir->nonScalable, + &lowerName, max, names, + (FontScalablePtr)0, + mark_aliases ? + LIST_ALIASES_AND_TARGET_NAMES : + NORMAL_ALIAS_BEHAVIOR, + &max); + if (result == Successful) + result = FontFileFindNamesInScalableDir (&dir->scalable, + &lowerName, max, names, + (FontScalablePtr)0, + mark_aliases ? + LIST_ALIASES_AND_TARGET_NAMES : + NORMAL_ALIAS_BEHAVIOR, (int *)0); + } + return result; +} + +typedef struct _LFWIData { + FontNamesPtr names; + int current; +} LFWIDataRec, *LFWIDataPtr; + +int +FontFileListFonts (pointer client, FontPathElementPtr fpe, char *pat, + int len, int max, FontNamesPtr names) +{ + return _FontFileListFonts (client, fpe, pat, len, max, names, 0); +} + +int +FontFileStartListFonts(pointer client, FontPathElementPtr fpe, + char *pat, int len, int max, + pointer *privatep, int mark_aliases) +{ + LFWIDataPtr data; + int ret; + + data = malloc (sizeof *data); + if (!data) + return AllocError; + data->names = MakeFontNamesRecord (0); + if (!data->names) + { + free (data); + return AllocError; + } + ret = _FontFileListFonts (client, fpe, pat, len, + max, data->names, mark_aliases); + if (ret != Successful) + { + FreeFontNames (data->names); + free (data); + return ret; + } + data->current = 0; + *privatep = (pointer) data; + return Successful; +} + + +int +FontFileStartListFontsWithInfo(pointer client, FontPathElementPtr fpe, + char *pat, int len, int max, + pointer *privatep) +{ + return FontFileStartListFonts(client, fpe, pat, len, max, privatep, 0); +} + +/* ARGSUSED */ +static int +FontFileListOneFontWithInfo (pointer client, FontPathElementPtr fpe, + char **namep, int *namelenp, + FontInfoPtr *pFontInfo) +{ + FontDirectoryPtr dir; + char lowerName[MAXFONTNAMELEN]; + char fileName[MAXFONTFILENAMELEN*2 + 1]; + FontNameRec tmpName; + FontEntryPtr entry; + FontScalableRec vals; + FontScalableEntryPtr scalable; + FontScaledPtr scaled; + FontBitmapEntryPtr bitmap; + int ret; + Bool noSpecificSize; + int nranges; + fsRange *ranges; + + char *name = *namep; + int namelen = *namelenp; + + if (namelen >= MAXFONTNAMELEN) + return AllocError; + dir = (FontDirectoryPtr) fpe->private; + + /* Match non-scalable pattern */ + CopyISOLatin1Lowered (lowerName, name, namelen); + lowerName[namelen] = '\0'; + ranges = FontParseRanges(lowerName, &nranges); + tmpName.name = lowerName; + tmpName.length = namelen; + tmpName.ndashes = FontFileCountDashes (lowerName, namelen); + if (!FontParseXLFDName(lowerName, &vals, FONT_XLFD_REPLACE_NONE)) + bzero(&vals, sizeof(vals)); + if (!(entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName)) && + tmpName.ndashes == 14 && + FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO)) + { + tmpName.length = strlen(lowerName); + entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName); + } + + if (entry) + { + switch (entry->type) { + case FONT_ENTRY_BITMAP: + bitmap = &entry->u.bitmap; + if (bitmap->pFont) + { + *pFontInfo = &bitmap->pFont->info; + ret = Successful; + } + else + { + ret = FontFileGetInfoBitmap (fpe, *pFontInfo, entry); + } + break; + case FONT_ENTRY_ALIAS: + vals.nranges = nranges; + vals.ranges = ranges; + transfer_values_to_alias(entry->name.name, entry->name.length, + entry->u.alias.resolved, namep, &vals); + *namelenp = strlen (*namep); + ret = FontNameAlias; + break; + default: + ret = BadFontName; + } + } + else + { + ret = BadFontName; + } + + if (ret != BadFontName) + { + if (ranges) free(ranges); + return ret; + } + + /* Match XLFD patterns */ + CopyISOLatin1Lowered (lowerName, name, namelen); + lowerName[namelen] = '\0'; + tmpName.name = lowerName; + tmpName.length = namelen; + tmpName.ndashes = FontFileCountDashes (lowerName, namelen); + if (!FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO) || + !(tmpName.length = strlen (lowerName), + entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName, + &vals))) { + CopyISOLatin1Lowered (lowerName, name, namelen); + lowerName[namelen] = '\0'; + tmpName.name = lowerName; + tmpName.length = namelen; + tmpName.ndashes = FontFileCountDashes (lowerName, namelen); + entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName, &vals); + if (entry) + { + strcpy(lowerName, entry->name.name); + tmpName.name = lowerName; + tmpName.length = entry->name.length; + tmpName.ndashes = entry->name.ndashes; + } + } + + if (entry) + { + noSpecificSize = FALSE; /* TRUE breaks XLFD enhancements */ + if (entry && entry->type == FONT_ENTRY_SCALABLE && + FontFileCompleteXLFD (&vals, &entry->u.scalable.extra->defaults)) + { + scalable = &entry->u.scalable; + scaled = FontFileFindScaledInstance (entry, &vals, noSpecificSize); + /* + * A scaled instance can occur one of two ways: + * + * Either the font has been scaled to this + * size already, in which case scaled->pFont + * will point at that font. + * + * Or a bitmap instance in this size exists, + * which is handled as if we got a pattern + * matching the bitmap font name. + */ + if (scaled) + { + if (scaled->pFont) + { + *pFontInfo = &scaled->pFont->info; + ret = Successful; + } + else if (scaled->bitmap) + { + entry = scaled->bitmap; + bitmap = &entry->u.bitmap; + if (bitmap->pFont) + { + *pFontInfo = &bitmap->pFont->info; + ret = Successful; + } + else + { + ret = FontFileGetInfoBitmap (fpe, *pFontInfo, entry); + } + } + else /* "cannot" happen */ + { + ret = BadFontName; + } + } + else + { + { + char origName[MAXFONTNAMELEN]; + + CopyISOLatin1Lowered (origName, name, namelen); + origName[namelen] = '\0'; + vals.xlfdName = origName; + vals.ranges = ranges; + vals.nranges = nranges; + + /* Make a new scaled instance */ + if (strlen(dir->directory) + strlen(scalable->fileName) >= + sizeof(fileName)) { + ret = BadFontName; + } else { + strcpy (fileName, dir->directory); + strcat (fileName, scalable->fileName); + if (scalable->renderer->GetInfoScalable) + ret = (*scalable->renderer->GetInfoScalable) + (fpe, *pFontInfo, entry, &tmpName, fileName, + &vals); + else if (scalable->renderer->GetInfoBitmap) + ret = (*scalable->renderer->GetInfoBitmap) + (fpe, *pFontInfo, entry, fileName); + } + if (ranges) { + free(ranges); + ranges = NULL; + } + } + } + if (ret == Successful) return ret; + } + CopyISOLatin1Lowered (lowerName, name, namelen); + tmpName.length = namelen; + } + else + ret = BadFontName; + + if (ranges) + free(ranges); + return ret; +} + +int +FontFileListNextFontWithInfo(pointer client, FontPathElementPtr fpe, + char **namep, int *namelenp, + FontInfoPtr *pFontInfo, + int *numFonts, pointer private) +{ + LFWIDataPtr data = (LFWIDataPtr) private; + int ret; + char *name; + int namelen; + + if (data->current == data->names->nnames) + { + FreeFontNames (data->names); + free (data); + return BadFontName; + } + name = data->names->names[data->current]; + namelen = data->names->length[data->current]; + ret = FontFileListOneFontWithInfo (client, fpe, &name, &namelen, pFontInfo); + if (ret == BadFontName) + ret = AllocError; + *namep = name; + *namelenp = namelen; + ++data->current; + *numFonts = data->names->nnames - data->current; + return ret; +} + +int +FontFileStartListFontsAndAliases(pointer client, FontPathElementPtr fpe, + char *pat, int len, int max, + pointer *privatep) +{ + return FontFileStartListFonts(client, fpe, pat, len, max, privatep, 1); +} + +int +FontFileListNextFontOrAlias(pointer client, FontPathElementPtr fpe, + char **namep, int *namelenp, char **resolvedp, + int *resolvedlenp, pointer private) +{ + LFWIDataPtr data = (LFWIDataPtr) private; + int ret; + char *name; + int namelen; + + if (data->current == data->names->nnames) + { + FreeFontNames (data->names); + free (data); + return BadFontName; + } + name = data->names->names[data->current]; + namelen = data->names->length[data->current]; + + /* If this is a real font name... */ + if (namelen >= 0) + { + *namep = name; + *namelenp = namelen; + ret = Successful; + } + /* Else if an alias */ + else + { + /* Tell the caller that this is an alias... let him resolve it to + see if it's valid */ + *namep = name; + *namelenp = -namelen; + *resolvedp = data->names->names[++data->current]; + *resolvedlenp = data->names->length[data->current]; + ret = FontNameAlias; + } + + ++data->current; + return ret; +} + +void +FontFileRegisterLocalFpeFunctions (void) +{ + RegisterFPEFunctions(FontFileNameCheck, + FontFileInitFPE, + FontFileFreeFPE, + FontFileResetFPE, + FontFileOpenFont, + FontFileCloseFont, + FontFileListFonts, + FontFileStartListFontsWithInfo, + FontFileListNextFontWithInfo, + NULL, + NULL, + NULL, + FontFileStartListFontsAndAliases, + FontFileListNextFontOrAlias, + FontFileEmptyBitmapSource); +} diff --git a/src/fontfile/fontscale.c b/src/fontfile/fontscale.c new file mode 100755 index 0000000..55aca29 --- /dev/null +++ b/src/fontfile/fontscale.c @@ -0,0 +1,437 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +Bool +FontFileAddScaledInstance (FontEntryPtr entry, FontScalablePtr vals, + FontPtr pFont, char *bitmapName) +{ + FontScalableEntryPtr scalable; + FontScalableExtraPtr extra; + FontScaledPtr new; + int newsize; + + scalable = &entry->u.scalable; + extra = scalable->extra; + if (extra->numScaled == extra->sizeScaled) + { + newsize = extra->sizeScaled + 4; + new = realloc (extra->scaled, newsize * sizeof (FontScaledRec)); + if (!new) + return FALSE; + extra->sizeScaled = newsize; + extra->scaled = new; + } + new = &extra->scaled[extra->numScaled++]; + new->vals = *vals; + new->pFont = pFont; + new->bitmap = (FontEntryPtr) bitmapName; + if (pFont) + pFont->fpePrivate = (pointer) entry; + return TRUE; +} + +/* Must call this after the directory is sorted */ + +void +FontFileSwitchStringsToBitmapPointers (FontDirectoryPtr dir) +{ + int s; + int b; + int i; + FontEntryPtr scalable; + FontEntryPtr nonScalable; + FontScaledPtr scaled; + FontScalableExtraPtr extra; + + scalable = dir->scalable.entries; + nonScalable = dir->nonScalable.entries; + for (s = 0; s < dir->scalable.used; s++) + { + extra = scalable[s].u.scalable.extra; + scaled = extra->scaled; + for (i = 0; i < extra->numScaled; i++) + for (b = 0; b < dir->nonScalable.used; b++) + if (nonScalable[b].name.name == (char *) scaled[i].bitmap) + scaled[i].bitmap = &nonScalable[b]; + } +} + +void +FontFileRemoveScaledInstance (FontEntryPtr entry, FontPtr pFont) +{ + FontScalableEntryPtr scalable; + FontScalableExtraPtr extra; + int i; + + scalable = &entry->u.scalable; + extra = scalable->extra; + for (i = 0; i < extra->numScaled; i++) + { + if (extra->scaled[i].pFont == pFont) + { + if (extra->scaled[i].vals.ranges) + free (extra->scaled[i].vals.ranges); + extra->numScaled--; + for (; i < extra->numScaled; i++) + extra->scaled[i] = extra->scaled[i+1]; + } + } +} + +Bool +FontFileCompleteXLFD (FontScalablePtr vals, FontScalablePtr def) +{ + FontResolutionPtr res; + int num_res; + double sx, sy, temp_matrix[4]; + double pixel_setsize_adjustment = 1.0; + /* + * If two of the three vertical scale values are specified, compute the + * third. If all three are specified, make sure they are consistent + * (within a pixel) + * + * One purpose of this procedure is to complete XLFD names in a + * repeatable manner. That is, if the user partially specifies + * a name (say, pixelsize but not pointsize), the results generated + * here result in a fully specified name that will result in the + * same font. + */ + + res = GetClientResolutions(&num_res); + + if (!(vals->values_supplied & PIXELSIZE_MASK) || + !(vals->values_supplied & POINTSIZE_MASK)) + { + /* If resolution(s) unspecified and cannot be computed from + pixelsize and pointsize, get appropriate defaults. */ + + if (num_res) + { + if (vals->x <= 0) + vals->x = res->x_resolution; + if (vals->y <= 0) + vals->y = res->y_resolution; + } + + if (vals->x <= 0) + vals->x = def->x; + if (vals->y <= 0) + vals->y = def->y; + } + else + { + /* If needed, compute resolution values from the pixel and + pointsize information we were given. This problem is + overdetermined (four equations, two unknowns), but we don't + check for inconsistencies here. If they exist, they will + show up in later tests for the point and pixel sizes. */ + + if (vals->y <= 0) + { + double x = hypot(vals->pixel_matrix[1], vals->pixel_matrix[3]); + double y = hypot(vals->point_matrix[1], vals->point_matrix[3]); + if (y < EPS) return FALSE; + vals->y = (int)(x * 72.27 / y + .5); + } + if (vals->x <= 0) + { + /* If the pixelsize was given as an array, or as a scalar that + has been normalized for the pixel shape, we have enough + information to compute a separate horizontal resolution */ + + if ((vals->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY || + (vals->values_supplied & PIXELSIZE_MASK) == + PIXELSIZE_SCALAR_NORMALIZED) + { + double x = hypot(vals->pixel_matrix[0], vals->pixel_matrix[2]); + double y = hypot(vals->point_matrix[0], vals->point_matrix[2]); + if (y < EPS) return FALSE; + vals->x = (int)(x * 72.27 / y + .5); + } + else + { + /* Not enough information in the pixelsize array. Just + assume the pixels are square. */ + vals->x = vals->y; + } + } + } + + if (vals->x <= 0 || vals->y <= 0) return FALSE; + + /* If neither pixelsize nor pointsize is defined, take the pointsize + from the defaults structure we've been passed. */ + if (!(vals->values_supplied & PIXELSIZE_MASK) && + !(vals->values_supplied & POINTSIZE_MASK)) + { + if (num_res) + { + vals->point_matrix[0] = + vals->point_matrix[3] = (double)res->point_size / 10.0; + vals->point_matrix[1] = + vals->point_matrix[2] = 0; + vals->values_supplied = (vals->values_supplied & ~POINTSIZE_MASK) | + POINTSIZE_SCALAR; + } + else if (def->values_supplied & POINTSIZE_MASK) + { + vals->point_matrix[0] = def->point_matrix[0]; + vals->point_matrix[1] = def->point_matrix[1]; + vals->point_matrix[2] = def->point_matrix[2]; + vals->point_matrix[3] = def->point_matrix[3]; + vals->values_supplied = (vals->values_supplied & ~POINTSIZE_MASK) | + (def->values_supplied & POINTSIZE_MASK); + } + else return FALSE; + } + + /* At this point, at least two of the three vertical scale values + should be specified. Our job now is to compute the missing ones + and check for agreement between overspecified values */ + + /* If pixelsize was specified by a scalar, we need to fix the matrix + now that we know the resolutions. */ + if ((vals->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_SCALAR) + { + /* pixel_setsize_adjustment used below to modify permissible + error in pixel/pointsize matching, since multiplying a + number rounded to integer changes the amount of the error + caused by the rounding */ + + pixel_setsize_adjustment = (double)vals->x / (double)vals->y; + vals->pixel_matrix[0] *= pixel_setsize_adjustment; + vals->values_supplied = (vals->values_supplied & ~PIXELSIZE_MASK) | + PIXELSIZE_SCALAR_NORMALIZED; + } + + sx = (double)vals->x / 72.27; + sy = (double)vals->y / 72.27; + + /* If a pointsize was specified, make sure pixelsize is consistent + to within 1 pixel, then replace pixelsize with a consistent + floating-point value. */ + + if (vals->values_supplied & POINTSIZE_MASK) + { + recompute_pixelsize: ; + temp_matrix[0] = vals->point_matrix[0] * sx; + temp_matrix[1] = vals->point_matrix[1] * sy; + temp_matrix[2] = vals->point_matrix[2] * sx; + temp_matrix[3] = vals->point_matrix[3] * sy; + if (vals->values_supplied & PIXELSIZE_MASK) + { + if (fabs(vals->pixel_matrix[0] - temp_matrix[0]) > + pixel_setsize_adjustment || + fabs(vals->pixel_matrix[1] - temp_matrix[1]) > 1 || + fabs(vals->pixel_matrix[2] - temp_matrix[2]) > 1 || + fabs(vals->pixel_matrix[3] - temp_matrix[3]) > 1) + return FALSE; + } + if ((vals->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY && + (vals->values_supplied & POINTSIZE_MASK) == POINTSIZE_SCALAR) + { + /* In the special case that pixelsize came as an array and + pointsize as a scalar, recompute the pointsize matrix + from the pixelsize matrix. */ + goto recompute_pointsize; + } + + /* Refresh pixel matrix with precise values computed from + pointsize and resolution. */ + vals->pixel_matrix[0] = temp_matrix[0]; + vals->pixel_matrix[1] = temp_matrix[1]; + vals->pixel_matrix[2] = temp_matrix[2]; + vals->pixel_matrix[3] = temp_matrix[3]; + + /* Set values_supplied for pixel to match that for point */ + vals->values_supplied = + (vals->values_supplied & ~PIXELSIZE_MASK) | + (((vals->values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY) ? + PIXELSIZE_ARRAY : PIXELSIZE_SCALAR_NORMALIZED); + } + else + { + /* Pointsize unspecified... compute from pixel size and + resolutions */ + recompute_pointsize: ; + if (fabs(sx) < EPS || fabs(sy) < EPS) return FALSE; + vals->point_matrix[0] = vals->pixel_matrix[0] / sx; + vals->point_matrix[1] = vals->pixel_matrix[1] / sy; + vals->point_matrix[2] = vals->pixel_matrix[2] / sx; + vals->point_matrix[3] = vals->pixel_matrix[3] / sy; + + /* Set values_supplied for pixel to match that for point */ + vals->values_supplied = + (vals->values_supplied & ~POINTSIZE_MASK) | + (((vals->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY) ? + POINTSIZE_ARRAY : POINTSIZE_SCALAR); + + /* If we computed scalar pointsize from scalar pixelsize, round + pointsize to decipoints and recompute pixelsize so we end up + with a repeatable name */ + if ((vals->values_supplied & POINTSIZE_MASK) == POINTSIZE_SCALAR) + { + /* Off-diagonal elements should be zero since no matrix was + specified. */ + vals->point_matrix[0] = + (double)(int)(vals->point_matrix[0] * 10.0 + .5) / 10.0; + vals->point_matrix[3] = + (double)(int)(vals->point_matrix[3] * 10.0 + .5) / 10.0; + goto recompute_pixelsize; + } + } + + /* We've succeeded. Round everything to a few decimal places + for repeatability. */ + + vals->pixel_matrix[0] = xlfd_round_double(vals->pixel_matrix[0]); + vals->pixel_matrix[1] = xlfd_round_double(vals->pixel_matrix[1]); + vals->pixel_matrix[2] = xlfd_round_double(vals->pixel_matrix[2]); + vals->pixel_matrix[3] = xlfd_round_double(vals->pixel_matrix[3]); + vals->point_matrix[0] = xlfd_round_double(vals->point_matrix[0]); + vals->point_matrix[1] = xlfd_round_double(vals->point_matrix[1]); + vals->point_matrix[2] = xlfd_round_double(vals->point_matrix[2]); + vals->point_matrix[3] = xlfd_round_double(vals->point_matrix[3]); + + /* Fill in the deprecated fields for the benefit of rasterizers + that do not handle the matrices. */ + vals->point = vals->point_matrix[3] * 10; + vals->pixel = vals->pixel_matrix[3]; + + return TRUE; +} + +static Bool +MatchScalable (FontScalablePtr a, FontScalablePtr b) +{ + int i; + + /* Some asymmetry here: we assume that the first argument (a) is + the table entry and the second (b) the item we're trying to match + (the key). We'll consider the fonts matched if the relevant + metrics match *and* if a) the table entry doesn't have charset + subsetting or b) the table entry has identical charset subsetting + to that in the key. We could add logic to check if the table + entry has a superset of the charset required by the key, but + we'll resist the urge for now. */ + +#define EQUAL(a,b) ((a)[0] == (b)[0] && \ + (a)[1] == (b)[1] && \ + (a)[2] == (b)[2] && \ + (a)[3] == (b)[3]) + + if (!(a->x == b->x && + a->y == b->y && + (a->width == b->width || a->width == 0 || b->width == 0 || b->width == -1) && + (!(b->values_supplied & PIXELSIZE_MASK) || + ((a->values_supplied & PIXELSIZE_MASK) == + (b->values_supplied & PIXELSIZE_MASK) && + EQUAL(a->pixel_matrix, b->pixel_matrix))) && + (!(b->values_supplied & POINTSIZE_MASK) || + ((a->values_supplied & POINTSIZE_MASK) == + (b->values_supplied & POINTSIZE_MASK) && + EQUAL(a->point_matrix, b->point_matrix))) && + (a->nranges == 0 || a->nranges == b->nranges))) + return FALSE; + + for (i = 0; i < a->nranges; i++) + if (a->ranges[i].min_char_low != b->ranges[i].min_char_low || + a->ranges[i].min_char_high != b->ranges[i].min_char_high || + a->ranges[i].max_char_low != b->ranges[i].max_char_low || + a->ranges[i].max_char_high != b->ranges[i].max_char_high) + return FALSE; + + return TRUE; +} + +FontScaledPtr +FontFileFindScaledInstance (FontEntryPtr entry, FontScalablePtr vals, + int noSpecificSize) +{ + FontScalableEntryPtr scalable; + FontScalableExtraPtr extra; + FontScalablePtr mvals; + int dist, i; + int mini; + double mindist; + register double temp, sum=0.0; + +#define NORMDIFF(a, b) ( \ + temp = (a)[0] - (b)[0], \ + sum = temp * temp, \ + temp = (a)[1] - (b)[1], \ + sum += temp * temp, \ + temp = (a)[2] - (b)[2], \ + sum += temp * temp, \ + temp = (a)[3] - (b)[3], \ + sum + temp * temp ) + + scalable = &entry->u.scalable; + extra = scalable->extra; + if (noSpecificSize && extra->numScaled) + { + mini = 0; + mindist = NORMDIFF(extra->scaled[0].vals.point_matrix, + vals->point_matrix); + for (i = 1; i < extra->numScaled; i++) + { + if (extra->scaled[i].pFont && + !extra->scaled[i].pFont->info.cachable) continue; + mvals = &extra->scaled[i].vals; + dist = NORMDIFF(mvals->point_matrix, vals->point_matrix); + if (dist < mindist) + { + mindist = dist; + mini = i; + } + } + if (extra->scaled[mini].pFont && + !extra->scaled[mini].pFont->info.cachable) return 0; + return &extra->scaled[mini]; + } + else + { + /* See if we've scaled to this value yet */ + for (i = 0; i < extra->numScaled; i++) + { + if (extra->scaled[i].pFont && + !extra->scaled[i].pFont->info.cachable) continue; + if (MatchScalable (&extra->scaled[i].vals, vals)) + return &extra->scaled[i]; + } + } + return 0; +} diff --git a/src/fontfile/gunzip.c b/src/fontfile/gunzip.c new file mode 100755 index 0000000..9fa3eed --- /dev/null +++ b/src/fontfile/gunzip.c @@ -0,0 +1,225 @@ +/* lib/font/fontfile/gunzip.c + written by Mark Eichin September 1996. + intended for inclusion in X11 public releases. */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include + +typedef struct _xzip_buf { + z_stream z; + int zstat; + BufChar b[BUFFILESIZE]; + BufChar b_in[BUFFILESIZE]; + BufFilePtr f; +} xzip_buf; + +static int BufZipFileClose ( BufFilePtr f, int flag ); +static int BufZipFileFill ( BufFilePtr f ); +static int BufZipFileSkip ( BufFilePtr f, int c ); +static int BufCheckZipHeader ( BufFilePtr f ); + +BufFilePtr +BufFilePushZIP (BufFilePtr f) +{ + xzip_buf *x; + + x = malloc (sizeof (xzip_buf)); + if (!x) return 0; + /* these are just for raw calloc/free */ + x->z.zalloc = Z_NULL; + x->z.zfree = Z_NULL; + x->z.opaque = Z_NULL; + x->f = f; + + /* force inflateInit to allocate it's own history buffer */ + x->z.next_in = Z_NULL; + x->z.next_out = Z_NULL; + x->z.avail_in = x->z.avail_out = 0; + + /* using negative windowBits sets "nowrap" mode, which turns off + zlib header checking [undocumented, for gzip compatibility only?] */ + x->zstat = inflateInit2(&(x->z), -MAX_WBITS); + if (x->zstat != Z_OK) { + free(x); + return 0; + } + + /* now that the history buffer is allocated, we provide the data buffer */ + x->z.next_out = x->b; + x->z.avail_out = BUFFILESIZE; + x->z.next_out = x->b_in; + x->z.avail_in = 0; + + if (BufCheckZipHeader(x->f)) { + free(x); + return 0; + } + + return BufFileCreate((char *)x, + BufZipFileFill, + 0, + BufZipFileSkip, + BufZipFileClose); +} + +static int +BufZipFileClose(BufFilePtr f, int flag) +{ + xzip_buf *x = (xzip_buf *)f->private; + inflateEnd (&(x->z)); + BufFileClose (x->f, flag); + free (x); + return 1; +} + +/* here's the real work. + -- we need to put stuff in f.buffer, update f.left and f.bufp, + then return the first byte (or BUFFILEEOF). + -- to do this, we need to get stuff into avail_in, and next_in, + and call inflate appropriately. + -- we may also need to add CRC maintenance - if inflate tells us + Z_STREAM_END, we then have 4bytes CRC and 4bytes length... + gzio.c:gzread shows most of the mechanism. + */ +static int +BufZipFileFill (BufFilePtr f) +{ + xzip_buf *x = (xzip_buf *)f->private; + + /* we only get called when left == 0... */ + /* but just in case, deal */ + if (f->left >= 0) { + f->left--; + return *(f->bufp++); + } + /* did we run out last time? */ + switch (x->zstat) { + case Z_OK: + break; + case Z_STREAM_END: + case Z_DATA_ERROR: + case Z_ERRNO: + f->left = 0; + return BUFFILEEOF; + default: + return BUFFILEEOF; + } + /* now we work to consume what we can */ + /* let zlib know what we can handle */ + x->z.next_out = x->b; + x->z.avail_out = BUFFILESIZE; + + /* and try to consume all of it */ + while (x->z.avail_out > 0) { + /* if we don't have anything to work from... */ + if (x->z.avail_in == 0) { + /* ... fill the z buf from underlying file */ + int i, c; + for (i = 0; i < sizeof(x->b_in); i++) { + c = BufFileGet(x->f); + if (c == BUFFILEEOF) break; + x->b_in[i] = c; + } + x->z.avail_in += i; + x->z.next_in = x->b_in; + } + /* so now we have some output space and some input data */ + x->zstat = inflate(&(x->z), Z_NO_FLUSH); + /* the inflation output happens in the f buffer directly... */ + if (x->zstat == Z_STREAM_END) { + /* deal with EOF, crc */ + break; + } + if (x->zstat != Z_OK) { + break; + } + } + f->bufp = x->b; + f->left = BUFFILESIZE - x->z.avail_out; + + if (f->left >= 0) { + f->left--; + return *(f->bufp++); + } else { + return BUFFILEEOF; + } +} + +/* there should be a BufCommonSkip... */ +static int +BufZipFileSkip (BufFilePtr f, int c) +{ + /* BufFileRawSkip returns the count unchanged. + BufCompressedSkip returns 0. + That means it probably never gets called... */ + int retval = c; + while(c--) { + int get = BufFileGet(f); + if (get == BUFFILEEOF) return get; + } + return retval; +} + +/* now we need to duplicate check_header */ +/* contents: + 0x1f, 0x8b -- magic number + 1 byte -- method (Z_DEFLATED) + 1 byte -- flags (mask with RESERVED -> fail) + 4 byte -- time (discard) + 1 byte -- xflags (discard) + 1 byte -- "os" code (discard) + [if flags & EXTRA_FIELD: + 2 bytes -- LSBfirst length n + n bytes -- extra data (discard)] + [if flags & ORIG_NAME: + n bytes -- null terminated name (discard)] + [if flags & COMMENT: + n bytes -- null terminated comment (discard)] + [if flags & HEAD_CRC: + 2 bytes -- crc of headers? (discard)] + */ + +/* gzip flag byte -- from gzio.c */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +#define GET(f) do {c = BufFileGet(f); if (c == BUFFILEEOF) return c;} while(0) +static int +BufCheckZipHeader(BufFilePtr f) +{ + int c, flags; + GET(f); if (c != 0x1f) return 1; /* magic 1 */ + GET(f); if (c != 0x8b) return 2; /* magic 2 */ + GET(f); if (c != Z_DEFLATED) return 3; /* method */ + GET(f); if (c & RESERVED) return 4; /* reserved flags */ + flags = c; + GET(f); GET(f); GET(f); GET(f); /* time */ + GET(f); /* xflags */ + GET(f); /* os code */ + if (flags & EXTRA_FIELD) { + int len; + GET(f); len = c; + GET(f); len += (c<<8); + while (len-- >= 0) { + GET(f); + } + } + if (flags & ORIG_NAME) { + do { GET(f); } while (c != 0); + } + if (flags & COMMENT) { + do { GET(f); } while (c != 0); + } + if (flags & HEAD_CRC) { + GET(f); GET(f); /* header crc */ + } + return 0; +} diff --git a/src/fontfile/register.c b/src/fontfile/register.c new file mode 100644 index 0000000..1a63cb3 --- /dev/null +++ b/src/fontfile/register.c @@ -0,0 +1,62 @@ +/* + +Copyright 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#else +#define XFONT_BITMAP 1 +#endif + +#include +#include +#include + +/* + * Translate monolithic build symbols to modular build symbols. + * I chose to make the modular symbols 'canonical' because they + * are prefixed with XFONT_, neatly avoiding name collisions + * with other packages. + */ + +#ifdef BUILD_FREETYPE +# define XFONT_FREETYPE 1 +#endif + +void +FontFileRegisterFpeFunctions(void) +{ +#ifdef XFONT_BITMAP + /* bitmap is always builtin to libXfont now */ + BitmapRegisterFontFileFunctions (); +#endif +#ifdef XFONT_FREETYPE + FreeTypeRegisterFontFileFunctions(); +#endif + + FontFileRegisterLocalFpeFunctions (); + CatalogueRegisterLocalFpeFunctions (); +} + diff --git a/src/fontfile/renderers.c b/src/fontfile/renderers.c new file mode 100755 index 0000000..a9e4bef --- /dev/null +++ b/src/fontfile/renderers.c @@ -0,0 +1,114 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +extern void ErrorF(const char *f, ...); + +static FontRenderersRec renderers; + +/* + * XXX Maybe should allow unregistering renders. For now, just clear the + * list at each new generation. + */ +extern unsigned long serverGeneration; +static unsigned long rendererGeneration = 0; + +Bool +FontFileRegisterRenderer (FontRendererPtr renderer) +{ + return FontFilePriorityRegisterRenderer(renderer, 0); +} + +Bool +FontFilePriorityRegisterRenderer (FontRendererPtr renderer, int priority) +{ + int i; + struct _FontRenderersElement *new; + + if (rendererGeneration != serverGeneration) { + rendererGeneration = serverGeneration; + renderers.number = 0; + if (renderers.renderers) + free(renderers.renderers); + renderers.renderers = NULL; + } + + for (i = 0; i < renderers.number; i++) { + if (!strcasecmp (renderers.renderers[i].renderer->fileSuffix, + renderer->fileSuffix)) { + if(renderers.renderers[i].priority >= priority) { + if(renderers.renderers[i].priority == priority) { + if (rendererGeneration == 1) + ErrorF("Warning: font renderer for \"%s\" " + "already registered at priority %d\n", + renderer->fileSuffix, priority); + } + return TRUE; + } else { + break; + } + } + } + + if(i >= renderers.number) { + new = realloc (renderers.renderers, sizeof(*new) * (i + 1)); + if (!new) + return FALSE; + renderers.renderers = new; + renderers.number = i + 1; + } + renderer->number = i; + renderers.renderers[i].renderer = renderer; + renderers.renderers[i].priority = priority; + return TRUE; +} + +FontRendererPtr +FontFileMatchRenderer (char *fileName) +{ + int i; + int fileLen; + FontRendererPtr r; + + fileLen = strlen (fileName); + for (i = 0; i < renderers.number; i++) + { + r = renderers.renderers[i].renderer; + if (fileLen >= r->fileSuffixLen && + !strcasecmp (fileName + fileLen - r->fileSuffixLen, r->fileSuffix)) + { + return r; + } + } + return 0; +} diff --git a/src/stubs/Makefile.am b/src/stubs/Makefile.am new file mode 100644 index 0000000..4d60c2a --- /dev/null +++ b/src/stubs/Makefile.am @@ -0,0 +1,25 @@ +INCLUDES = \ + -I${top_srcdir}/include + +AM_CFLAGS = $(XFONT_CFLAGS) $(OS_CFLAGS) $(CWARNFLAGS) + +noinst_LTLIBRARIES = libstubs.la + +libstubs_la_SOURCES = \ + cauthgen.c \ + csignal.c \ + delfntcid.c \ + errorf.c \ + fatalerror.c \ + findoldfnt.c \ + getcres.c \ + getdefptsize.c \ + getnewfntcid.c \ + gettime.c \ + initfshdl.c \ + regfpefunc.c \ + rmfshdl.c \ + servclient.c \ + setfntauth.c \ + stfntcfnt.c \ + stubs.h diff --git a/src/stubs/cauthgen.c b/src/stubs/cauthgen.c new file mode 100644 index 0000000..026c52d --- /dev/null +++ b/src/stubs/cauthgen.c @@ -0,0 +1,14 @@ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "stubs.h" + +#ifdef __SUNPRO_C +#pragma weak client_auth_generation +#endif + +weak int +client_auth_generation(ClientPtr client) +{ + return 0; +} diff --git a/src/stubs/csignal.c b/src/stubs/csignal.c new file mode 100644 index 0000000..e6fdeae --- /dev/null +++ b/src/stubs/csignal.c @@ -0,0 +1,14 @@ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "stubs.h" + +#ifdef __SUNPRO_C +#pragma weak ClientSignal +#endif + +weak Bool +ClientSignal(ClientPtr client) +{ + return True; +} diff --git a/src/stubs/delfntcid.c b/src/stubs/delfntcid.c new file mode 100644 index 0000000..ca71328 --- /dev/null +++ b/src/stubs/delfntcid.c @@ -0,0 +1,13 @@ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "stubs.h" + +#ifdef __SUNPRO_C +#pragma weak DeleteFontClientID +#endif + +weak void +DeleteFontClientID(Font id) +{ +} diff --git a/src/stubs/errorf.c b/src/stubs/errorf.c new file mode 100644 index 0000000..fd32965 --- /dev/null +++ b/src/stubs/errorf.c @@ -0,0 +1,13 @@ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "stubs.h" + +#ifdef __SUNPRO_C +#pragma weak ErrorF +#endif + +weak void +ErrorF(const char *f, ...) +{ +} diff --git a/src/stubs/fatalerror.c b/src/stubs/fatalerror.c new file mode 100644 index 0000000..1549ad3 --- /dev/null +++ b/src/stubs/fatalerror.c @@ -0,0 +1,13 @@ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "stubs.h" + +#ifdef __SUNPRO_C +#pragma weak FatalError +#endif + +weak void +FatalError(const char *f, ...) +{ +} diff --git a/src/stubs/findoldfnt.c b/src/stubs/findoldfnt.c new file mode 100644 index 0000000..7a00084 --- /dev/null +++ b/src/stubs/findoldfnt.c @@ -0,0 +1,14 @@ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "stubs.h" + +#ifdef __SUNPRO_C +#pragma weak find_old_font +#endif + +weak FontPtr +find_old_font(FSID id) +{ + return (FontPtr)NULL; +} diff --git a/src/stubs/getcres.c b/src/stubs/getcres.c new file mode 100644 index 0000000..0b98f46 --- /dev/null +++ b/src/stubs/getcres.c @@ -0,0 +1,14 @@ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "stubs.h" + +#ifdef __SUNPRO_C +#pragma weak GetClientResolutions +#endif + +weak FontResolutionPtr +GetClientResolutions(int *num) +{ + return (FontResolutionPtr) 0; +} diff --git a/src/stubs/getdefptsize.c b/src/stubs/getdefptsize.c new file mode 100644 index 0000000..0b9e409 --- /dev/null +++ b/src/stubs/getdefptsize.c @@ -0,0 +1,14 @@ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "stubs.h" + +#ifdef __SUNPRO_C +#pragma weak GetDefaultPointSize +#endif + +weak int +GetDefaultPointSize(void) +{ + return 0; +} diff --git a/src/stubs/getnewfntcid.c b/src/stubs/getnewfntcid.c new file mode 100644 index 0000000..e2fe8bb --- /dev/null +++ b/src/stubs/getnewfntcid.c @@ -0,0 +1,14 @@ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "stubs.h" + +#ifdef __SUNPRO_C +#pragma weak GetNewFontClientID +#endif + +weak Font +GetNewFontClientID(void) +{ + return (Font)0; +} diff --git a/src/stubs/gettime.c b/src/stubs/gettime.c new file mode 100644 index 0000000..7b2d3b3 --- /dev/null +++ b/src/stubs/gettime.c @@ -0,0 +1,14 @@ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "stubs.h" + +#ifdef __SUNPRO_C +#pragma weak GetTimeInMillis +#endif + +weak unsigned long +GetTimeInMillis (void) +{ + return 0; +} diff --git a/src/stubs/initfshdl.c b/src/stubs/initfshdl.c new file mode 100644 index 0000000..a14daff --- /dev/null +++ b/src/stubs/initfshdl.c @@ -0,0 +1,15 @@ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "stubs.h" + +#ifdef __SUNPRO_C +#pragma weak init_fs_handlers +#endif + +weak int +init_fs_handlers(FontPathElementPtr fpe, + BlockHandlerProcPtr block_handler) +{ + return Successful; +} diff --git a/src/stubs/regfpefunc.c b/src/stubs/regfpefunc.c new file mode 100644 index 0000000..a79b4bf --- /dev/null +++ b/src/stubs/regfpefunc.c @@ -0,0 +1,28 @@ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "stubs.h" + +#ifdef __SUNPRO_C +#pragma weak RegisterFPEFunctions +#endif + +weak int +RegisterFPEFunctions(NameCheckFunc name_func, + InitFpeFunc init_func, + FreeFpeFunc free_func, + ResetFpeFunc reset_func, + OpenFontFunc open_func, + CloseFontFunc close_func, + ListFontsFunc list_func, + StartLfwiFunc start_lfwi_func, + NextLfwiFunc next_lfwi_func, + WakeupFpeFunc wakeup_func, + ClientDiedFunc client_died, + LoadGlyphsFunc load_glyphs, + StartLaFunc start_list_alias_func, + NextLaFunc next_list_alias_func, + SetPathFunc set_path_func) +{ + return 0; +} diff --git a/src/stubs/rmfshdl.c b/src/stubs/rmfshdl.c new file mode 100644 index 0000000..d0bdd3d --- /dev/null +++ b/src/stubs/rmfshdl.c @@ -0,0 +1,15 @@ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "stubs.h" + +#ifdef __SUNPRO_C +#pragma weak remove_fs_handlers +#endif + +weak void +remove_fs_handlers(FontPathElementPtr fpe, + BlockHandlerProcPtr blockHandler, + Bool all) +{ +} diff --git a/src/stubs/servclient.c b/src/stubs/servclient.c new file mode 100644 index 0000000..9b6cebb --- /dev/null +++ b/src/stubs/servclient.c @@ -0,0 +1,10 @@ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "stubs.h" + +#ifdef __SUNPRO_C +#pragma weak serverClient +#endif + +weak void *serverClient = 0; diff --git a/src/stubs/setfntauth.c b/src/stubs/setfntauth.c new file mode 100644 index 0000000..0c7eccc --- /dev/null +++ b/src/stubs/setfntauth.c @@ -0,0 +1,14 @@ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "stubs.h" + +#ifdef __SUNPRO_C +#pragma weak set_font_authorizations +#endif + +weak int +set_font_authorizations(char **authorizations, int *authlen, ClientPtr client) +{ + return 0; +} diff --git a/src/stubs/stfntcfnt.c b/src/stubs/stfntcfnt.c new file mode 100644 index 0000000..5fc1745 --- /dev/null +++ b/src/stubs/stfntcfnt.c @@ -0,0 +1,14 @@ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "stubs.h" + +#ifdef __SUNPRO_C +#pragma weak StoreFontClientFont +#endif + +weak int +StoreFontClientFont(FontPtr pfont, Font id) +{ + return 0; +} diff --git a/src/stubs/stubs.h b/src/stubs/stubs.h new file mode 100755 index 0000000..7f0eef2 --- /dev/null +++ b/src/stubs/stubs.h @@ -0,0 +1,41 @@ +#include +#include +#include + +#ifndef True +#define True (-1) +#endif +#ifndef False +#define False (0) +#endif + +/* this probably works for Mach-O too, but probably not for PE */ +#if (defined(__APPLE__) || defined(__ELF__)) && defined(__GNUC__) && (__GNUC__ >= 3) +#define weak __attribute__((weak)) +#else +#define weak +#ifndef __SUNPRO_C /* Sun compilers use #pragma weak in .c files instead */ +#define NO_WEAK_SYMBOLS +#endif +#endif + +/* This is really just a hack for now... __APPLE__ really should be using + * the weak symbols route above, but it's causing an as-yet unresolved issue, + * so we're instead building with flat_namespace. + */ +#ifdef __APPLE__ +#undef weak +#define weak +#endif + +extern FontPtr find_old_font ( FSID id ); +extern int set_font_authorizations ( char **authorizations, + int *authlen, + ClientPtr client ); + +extern unsigned long GetTimeInMillis (void); + +extern void ErrorF(const char *format, ...); +extern void FatalError(const char *format, ...); + +/* end of file */ diff --git a/src/util/Makefile.am b/src/util/Makefile.am new file mode 100644 index 0000000..055fc9d --- /dev/null +++ b/src/util/Makefile.am @@ -0,0 +1,19 @@ +INCLUDES = \ + -I${top_srcdir}/include \ + -I$(top_srcdir)/src/stubs + +AM_CFLAGS = $(XFONT_CFLAGS) $(OS_CFLAGS) $(CWARNFLAGS) + +noinst_LTLIBRARIES = libutil.la + +libutil_la_SOURCES = \ + atom.c \ + fontaccel.c \ + fontnames.c \ + fontutil.c \ + fontxlfd.c \ + format.c \ + miscutil.c \ + patcache.c \ + private.c \ + utilbitmap.c diff --git a/src/util/atom.c b/src/util/atom.c new file mode 100755 index 0000000..f15e3d8 --- /dev/null +++ b/src/util/atom.c @@ -0,0 +1,242 @@ +/* + +Copyright 1990, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +/* lame atom replacement routines for font applications */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include "stubs.h" + +typedef struct _AtomList { + char *name; + int len; + int hash; + Atom atom; +} AtomListRec, *AtomListPtr; + +static AtomListPtr *hashTable; + +static int hashSize, hashUsed; +static int hashMask; +static int rehash; + +static AtomListPtr *reverseMap; +static int reverseMapSize; +static Atom lastAtom; + +static int +Hash(char *string, int len) +{ + int h; + + h = 0; + while (len--) + h = (h << 3) ^ *string++; + if (h < 0) + return -h; + return h; +} + +static int +ResizeHashTable (void) +{ + int newHashSize; + int newHashMask; + AtomListPtr *newHashTable; + int i; + int h; + int newRehash; + int r; + + if (hashSize == 0) + newHashSize = 1024; + else + newHashSize = hashSize * 2; + newHashTable = calloc (newHashSize, sizeof (AtomListPtr)); + if (!newHashTable) { + fprintf(stderr, "ResizeHashTable(): Error: Couldn't allocate" + " newHashTable (%ld)\n", + newHashSize * (unsigned long)sizeof (AtomListPtr)); + return FALSE; + } + newHashMask = newHashSize - 1; + newRehash = (newHashMask - 2); + for (i = 0; i < hashSize; i++) + { + if (hashTable[i]) + { + h = (hashTable[i]->hash) & newHashMask; + if (newHashTable[h]) + { + r = hashTable[i]->hash % newRehash | 1; + do { + h += r; + if (h >= newHashSize) + h -= newHashSize; + } while (newHashTable[h]); + } + newHashTable[h] = hashTable[i]; + } + } + free (hashTable); + hashTable = newHashTable; + hashSize = newHashSize; + hashMask = newHashMask; + rehash = newRehash; + return TRUE; +} + +static int +ResizeReverseMap (void) +{ + int ret = TRUE; + if (reverseMapSize == 0) + reverseMapSize = 1000; + else + reverseMapSize *= 2; + reverseMap = realloc (reverseMap, reverseMapSize * sizeof (AtomListPtr)); + if (!reverseMap) { + fprintf(stderr, "ResizeReverseMap(): Error: Couldn't reallocate" + " reverseMap (%ld)\n", + reverseMapSize * (unsigned long)sizeof(AtomListPtr)); + ret = FALSE; + } + return ret; +} + +static int +NameEqual (const char *a, const char *b, int l) +{ + while (l--) + if (*a++ != *b++) + return FALSE; + return TRUE; +} + +#ifdef __SUNPRO_C +#pragma weak MakeAtom +#endif + +weak Atom +MakeAtom(char *string, unsigned len, int makeit) +{ + AtomListPtr a; + int hash; + int h = 0; + int r; + + hash = Hash (string, len); + if (hashTable) + { + h = hash & hashMask; + if (hashTable[h]) + { + if (hashTable[h]->hash == hash && hashTable[h]->len == len && + NameEqual (hashTable[h]->name, string, len)) + { + return hashTable[h]->atom; + } + r = (hash % rehash) | 1; + for (;;) + { + h += r; + if (h >= hashSize) + h -= hashSize; + if (!hashTable[h]) + break; + if (hashTable[h]->hash == hash && hashTable[h]->len == len && + NameEqual (hashTable[h]->name, string, len)) + { + return hashTable[h]->atom; + } + } + } + } + if (!makeit) + return None; + a = malloc (sizeof (AtomListRec) + len + 1); + if (a == NULL) { + fprintf(stderr, "MakeAtom(): Error: Couldn't allocate AtomListRec" + " (%ld)\n", (unsigned long)sizeof (AtomListRec) + len + 1); + return None; + } + a->name = (char *) (a + 1); + a->len = len; + strncpy (a->name, string, len); + a->name[len] = '\0'; + a->atom = ++lastAtom; + a->hash = hash; + if (hashUsed >= hashSize / 2) + { + ResizeHashTable (); + h = hash & hashMask; + if (hashTable[h]) + { + r = (hash % rehash) | 1; + do { + h += r; + if (h >= hashSize) + h -= hashSize; + } while (hashTable[h]); + } + } + hashTable[h] = a; + hashUsed++; + if (reverseMapSize <= a->atom) { + if (!ResizeReverseMap()) + return None; + } + reverseMap[a->atom] = a; + return a->atom; +} + +#ifdef __SUNPRO_C +#pragma weak ValidAtom +#endif + +weak int +ValidAtom(Atom atom) +{ + return (atom != None) && (atom <= lastAtom); +} + +#ifdef __SUNPRO_C +#pragma weak NameForAtom +#endif + +weak char * +NameForAtom(Atom atom) +{ + if (atom != None && atom <= lastAtom) + return reverseMap[atom]->name; + return NULL; +} diff --git a/src/util/fontaccel.c b/src/util/fontaccel.c new file mode 100755 index 0000000..c5915db --- /dev/null +++ b/src/util/fontaccel.c @@ -0,0 +1,104 @@ +/* + +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include + +void +FontComputeInfoAccelerators(FontInfoPtr pFontInfo) +{ + pFontInfo->noOverlap = FALSE; + if (pFontInfo->maxOverlap <= pFontInfo->minbounds.leftSideBearing) + pFontInfo->noOverlap = TRUE; + + if ((pFontInfo->minbounds.ascent == pFontInfo->maxbounds.ascent) && + (pFontInfo->minbounds.descent == pFontInfo->maxbounds.descent) && + (pFontInfo->minbounds.leftSideBearing == + pFontInfo->maxbounds.leftSideBearing) && + (pFontInfo->minbounds.rightSideBearing == + pFontInfo->maxbounds.rightSideBearing) && + (pFontInfo->minbounds.characterWidth == + pFontInfo->maxbounds.characterWidth) && + (pFontInfo->minbounds.attributes == pFontInfo->maxbounds.attributes)) { + pFontInfo->constantMetrics = TRUE; + if ((pFontInfo->maxbounds.leftSideBearing == 0) && + (pFontInfo->maxbounds.rightSideBearing == + pFontInfo->maxbounds.characterWidth) && + (pFontInfo->maxbounds.ascent == pFontInfo->fontAscent) && + (pFontInfo->maxbounds.descent == pFontInfo->fontDescent)) + pFontInfo->terminalFont = TRUE; + else + pFontInfo->terminalFont = FALSE; + } else { + pFontInfo->constantMetrics = FALSE; + pFontInfo->terminalFont = FALSE; + } + if (pFontInfo->minbounds.characterWidth == pFontInfo->maxbounds.characterWidth) + pFontInfo->constantWidth = TRUE; + else + pFontInfo->constantWidth = FALSE; + + if ((pFontInfo->minbounds.leftSideBearing >= 0) && + (pFontInfo->maxOverlap <= 0) && + (pFontInfo->minbounds.ascent >= -pFontInfo->fontDescent) && + (pFontInfo->maxbounds.ascent <= pFontInfo->fontAscent) && + (-pFontInfo->minbounds.descent <= pFontInfo->fontAscent) && + (pFontInfo->maxbounds.descent <= pFontInfo->fontDescent)) + pFontInfo->inkInside = TRUE; + else + pFontInfo->inkInside = FALSE; +} + +int +FontCouldBeTerminal(FontInfoPtr pFontInfo) +{ + if ((pFontInfo->minbounds.leftSideBearing >= 0) && + (pFontInfo->maxbounds.rightSideBearing <= pFontInfo->maxbounds.characterWidth) && + (pFontInfo->minbounds.characterWidth == pFontInfo->maxbounds.characterWidth) && + (pFontInfo->maxbounds.ascent <= pFontInfo->fontAscent) && + (pFontInfo->maxbounds.descent <= pFontInfo->fontDescent) && + (pFontInfo->maxbounds.leftSideBearing != 0 || + pFontInfo->minbounds.rightSideBearing != pFontInfo->minbounds.characterWidth || + pFontInfo->minbounds.ascent != pFontInfo->fontAscent || + pFontInfo->minbounds.descent != pFontInfo->fontDescent)) { + /* blow off font with nothing but a SPACE */ + if (pFontInfo->maxbounds.ascent == 0 && + pFontInfo->maxbounds.descent == 0) + return FALSE; + return TRUE; + } + return FALSE; +} diff --git a/src/util/fontnames.c b/src/util/fontnames.c new file mode 100755 index 0000000..ceafce5 --- /dev/null +++ b/src/util/fontnames.c @@ -0,0 +1,119 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +void +FreeFontNames(FontNamesPtr pFN) +{ + int i; + + if (!pFN) + return; + for (i = 0; i < pFN->nnames; i++) { + free(pFN->names[i]); + } + free(pFN->names); + free(pFN->length); + free(pFN); +} + +FontNamesPtr +MakeFontNamesRecord(unsigned int size) +{ + FontNamesPtr pFN; + + pFN = malloc(sizeof(FontNamesRec)); + if (pFN) { + pFN->nnames = 0; + pFN->size = size; + if (size) + { + pFN->length = malloc(size * sizeof(int)); + pFN->names = malloc(size * sizeof(char *)); + if (!pFN->length || !pFN->names) { + free(pFN->length); + free(pFN->names); + free(pFN); + pFN = (FontNamesPtr) 0; + } + } + else + { + pFN->length = 0; + pFN->names = 0; + } + } + return pFN; +} + +int +AddFontNamesName(FontNamesPtr names, char *name, int length) +{ + int index = names->nnames; + char *nelt; + + nelt = malloc(length + 1); + if (!nelt) + return AllocError; + if (index >= names->size) { + int size = names->size << 1; + int *nlength; + char **nnames; + + if (size == 0) + size = 8; + nlength = realloc(names->length, size * sizeof(int)); + nnames = realloc(names->names, size * sizeof(char *)); + if (nlength && nnames) { + names->size = size; + names->length = nlength; + names->names = nnames; + } else { + free(nelt); + free(nlength); + free(nnames); + return AllocError; + } + } + names->length[index] = length; + names->names[index] = nelt; + strncpy(nelt, name, length); + nelt[length] = '\0'; + names->nnames++; + return Successful; +} diff --git a/src/util/fontutil.c b/src/util/fontutil.c new file mode 100755 index 0000000..22f6119 --- /dev/null +++ b/src/util/fontutil.c @@ -0,0 +1,410 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +/* Define global here... doesn't hurt the servers, and avoids + unresolved references in font clients. */ + +static int defaultGlyphCachingMode = DEFAULT_GLYPH_CACHING_MODE; +int glyphCachingMode = DEFAULT_GLYPH_CACHING_MODE; + +void +GetGlyphs(FontPtr font, + unsigned long count, + unsigned char *chars, + FontEncoding fontEncoding, + unsigned long *glyphcount, /* RETURN */ + CharInfoPtr *glyphs) /* RETURN */ +{ + (*font->get_glyphs) (font, count, chars, fontEncoding, glyphcount, glyphs); +} + +#define MIN(a,b) ((a)<(b)?(a):(b)) +#define MAX(a,b) ((a)>(b)?(a):(b)) + +void +QueryGlyphExtents(FontPtr pFont, + CharInfoPtr *charinfo, + unsigned long count, + ExtentInfoRec *info) +{ + register unsigned long i; + xCharInfo *pCI; + + info->drawDirection = pFont->info.drawDirection; + + info->fontAscent = pFont->info.fontAscent; + info->fontDescent = pFont->info.fontDescent; + + if (count != 0) { + + pCI = &((*charinfo)->metrics); charinfo++; + /* ignore nonexisting characters when calculating text extents */ + if ( !((pCI->characterWidth == 0) + && (pCI->rightSideBearing == 0) + && (pCI->leftSideBearing == 0) + && (pCI->ascent == 0) + && (pCI->descent == 0)) ) { + info->overallAscent = pCI->ascent; + info->overallDescent = pCI->descent; + info->overallLeft = pCI->leftSideBearing; + info->overallRight = pCI->rightSideBearing; + info->overallWidth = pCI->characterWidth; + } + + if (pFont->info.constantMetrics && pFont->info.noOverlap) { + info->overallWidth *= count; + info->overallRight += (info->overallWidth - + pCI->characterWidth); + } else { + for (i = 1; i < count; i++) { + pCI = &((*charinfo)->metrics); charinfo++; + /* ignore nonexisting characters when calculating extents */ + if ( !((pCI->characterWidth == 0) + && (pCI->rightSideBearing == 0) + && (pCI->leftSideBearing == 0) + && (pCI->ascent == 0) + && (pCI->descent == 0)) ) { + info->overallAscent = MAX( + info->overallAscent, + pCI->ascent); + info->overallDescent = MAX( + info->overallDescent, + pCI->descent); + info->overallLeft = MIN( + info->overallLeft, + info->overallWidth + pCI->leftSideBearing); + info->overallRight = MAX( + info->overallRight, + info->overallWidth + pCI->rightSideBearing); + /* + * yes, this order is correct; overallWidth IS incremented + * last + */ + info->overallWidth += pCI->characterWidth; + } + } + } + } else { + info->overallAscent = 0; + info->overallDescent = 0; + info->overallWidth = 0; + info->overallLeft = 0; + info->overallRight = 0; + } +} + +Bool +QueryTextExtents(FontPtr pFont, + unsigned long count, + unsigned char *chars, + ExtentInfoRec *info) +{ + xCharInfo **charinfo; + unsigned long n; + FontEncoding encoding; + int cm; + int i; + unsigned long t; + xCharInfo *defaultChar = 0; + unsigned char defc[2]; + int firstReal; + + charinfo = malloc(count * sizeof(xCharInfo *)); + if (!charinfo) + return FALSE; + encoding = TwoD16Bit; + if (pFont->info.lastRow == 0) + encoding = Linear16Bit; + (*pFont->get_metrics) (pFont, count, chars, encoding, &n, charinfo); + + /* Do default character substitution as get_metrics doesn't */ + +#define IsNonExistentChar(ci) (!(ci) || \ + ((ci)->ascent == 0 && \ + (ci)->descent == 0 && \ + (ci)->leftSideBearing == 0 && \ + (ci)->rightSideBearing == 0 && \ + (ci)->characterWidth == 0)) + + firstReal = n; + defc[0] = pFont->info.defaultCh >> 8; + defc[1] = pFont->info.defaultCh; + (*pFont->get_metrics) (pFont, 1, defc, encoding, &t, &defaultChar); + if ((IsNonExistentChar (defaultChar))) + defaultChar = 0; + for (i = 0; i < n; i++) + { + if ((IsNonExistentChar (charinfo[i]))) + { + if (!defaultChar) + continue; + charinfo[i] = defaultChar; + } + if (firstReal == n) + firstReal = i; + } + cm = pFont->info.constantMetrics; + pFont->info.constantMetrics = FALSE; + QueryGlyphExtents(pFont, (CharInfoPtr*) charinfo + firstReal, + n - firstReal, info); + pFont->info.constantMetrics = cm; + free(charinfo); + return TRUE; +} + +Bool +ParseGlyphCachingMode(char *str) +{ + if (!strcmp(str, "none")) defaultGlyphCachingMode = CACHING_OFF; + else if (!strcmp(str, "all")) defaultGlyphCachingMode = CACHE_ALL_GLYPHS; + else if (!strcmp(str, "16")) defaultGlyphCachingMode = CACHE_16_BIT_GLYPHS; + else return FALSE; + return TRUE; +} + +void +InitGlyphCaching(void) +{ + /* Set glyphCachingMode to the mode the server hopes to + support. DDX drivers that do not support the requested level + of glyph caching can call SetGlyphCachingMode to lower the + level of support. + */ + + glyphCachingMode = defaultGlyphCachingMode; +} + +/* ddxen can call SetGlyphCachingMode to inform us of what level of glyph + * caching they can support. + */ +void +SetGlyphCachingMode(int newmode) +{ + if ( (glyphCachingMode > newmode) && (newmode >= 0) ) + glyphCachingMode = newmode; +} + +#define range_alloc_granularity 16 +#define mincharp(p) ((p)->min_char_low + ((p)->min_char_high << 8)) +#define maxcharp(p) ((p)->max_char_low + ((p)->max_char_high << 8)) + +/* add_range(): Add range to a list of ranges, with coalescence */ +int +add_range(fsRange *newrange, + int *nranges, + fsRange **range, + Bool charset_subset) +{ + int first, last, middle; + unsigned long keymin, keymax; + unsigned long ptrmin = 0, ptrmax = 0; + fsRange *ptr = NULL, *ptr1, *ptr2, *endptr; + + /* There are two different ways to treat ranges: + + 1) Charset subsetting (support of the HP XLFD enhancements), in + which a range of 0x1234,0x3456 means all numbers between + 0x1234 and 0x3456, and in which min and max might be swapped. + + 2) Row/column ranges, in which a range of 0x1234,0x3456 means the + ranges 0x1234-0x1256, 0x1334-0x1356, ... , 0x3434-0x3456. + This is for support of glyph caching. + + The choice of treatment is selected with the "charset_subset" + flag */ + + /* If newrange covers multiple rows; break up the rows */ + if (!charset_subset && newrange->min_char_high != newrange->max_char_high) + { + int i, err = 0; + fsRange temprange; + for (i = newrange->min_char_high; + i <= newrange->max_char_high; + i++) + { + temprange.min_char_low = newrange->min_char_low; + temprange.max_char_low = newrange->max_char_low; + temprange.min_char_high = temprange.max_char_high = i; + err = add_range(&temprange, nranges, range, charset_subset); + if (err != Successful) break; + } + return err; + } + + keymin = mincharp(newrange); + keymax = maxcharp(newrange); + + if (charset_subset && keymin > keymax) + { + unsigned long temp = keymin; + keymin = keymax; + keymax = temp; + } + + /* add_range() maintains a sorted list; this makes possible coalescence + and binary searches */ + + /* Binary search for a range with which the new range can merge */ + + first = middle = 0; + last = *nranges - 1; + while (last >= first) + { + middle = (first + last) / 2; + ptr = (*range) + middle; + ptrmin = mincharp(ptr); + ptrmax = maxcharp(ptr); + + if (ptrmin > 0 && keymax < ptrmin - 1) last = middle - 1; + else if (keymin > ptrmax + 1) first = middle + 1; + else if (!charset_subset) + { + /* We might have a range with which to merge... IF the + result doesn't cross rows */ + if (newrange->min_char_high != ptr->min_char_high) + last = first - 1; /* Force adding a new range */ + break; + } + else break; /* We have at least one range with which we can merge */ + } + + if (last < first) + { + /* Search failed; we need to add a new range to the list. */ + + /* Grow the list if necessary */ + if (*nranges == 0 || *range == (fsRange *)0) + { + *range = malloc(range_alloc_granularity * SIZEOF(fsRange)); + *nranges = 0; + } + else if (!(*nranges % range_alloc_granularity)) + { + *range = realloc(*range, (*nranges + range_alloc_granularity) * + SIZEOF(fsRange)); + } + + /* If alloc failed, just return a null list */ + if (*range == (fsRange *)0) + { + *nranges = 0; + return AllocError; + } + + /* Should new entry go *at* or *after* ptr? */ + ptr = (*range) + middle; + if (middle < *nranges && keymin > ptrmin) ptr++; /* after */ + + /* Open up a space for our new range */ + memmove((char *)(ptr + 1), + (char *)ptr, + (char *)(*range + *nranges) - (char *)ptr); + + /* Insert the new range */ + ptr->min_char_low = keymin & 0xff; + ptr->min_char_high = keymin >> 8; + ptr->max_char_low = keymax & 0xff; + ptr->max_char_high = keymax >> 8; + + /* Update range count */ + (*nranges)++; + + /* Done */ + return Successful; + } + + /* Join our new range to that pointed to by "ptr" */ + if (keymin < ptrmin) + { + ptr->min_char_low = keymin & 0xff; + ptr->min_char_high = keymin >> 8; + } + if (keymax > ptrmax) + { + ptr->max_char_low = keymax & 0xff; + ptr->max_char_high = keymax >> 8; + } + + ptrmin = mincharp(ptr); + ptrmax = maxcharp(ptr); + + endptr = *range + *nranges; + + for (ptr1 = ptr; ptr1 >= *range; ptr1--) + { + if (ptrmin <= maxcharp(ptr1) + 1) + { + if (!charset_subset && ptr->min_char_high != ptr1->min_char_high) + break; + if (ptrmin >= mincharp(ptr1)) + ptrmin = mincharp(ptr1); + } + else break; + } + for (ptr2 = ptr; ptr2 < endptr; ptr2++) + { + if ((ptr2->min_char_low == 0 && ptr2->min_char_high == 0) || + ptrmax >= mincharp(ptr2) - 1) + { + if (!charset_subset && ptr->min_char_high != ptr2->min_char_high) + break; + if (ptrmax <= maxcharp(ptr2)) + ptrmax = maxcharp(ptr2); + } + else break; + } + + /* We need to coalesce ranges between ptr1 and ptr2 exclusive */ + ptr1++; + ptr2--; + if (ptr1 != ptr2) + { + memmove(ptr1, ptr2, (char *)endptr - (char *)ptr2); + *nranges -= (ptr2 - ptr1); + } + + /* Write the new range into the range list */ + ptr1->min_char_low = ptrmin & 0xff; + ptr1->min_char_high = ptrmin >> 8; + ptr1->max_char_low = ptrmax & 0xff; + ptr1->max_char_high = ptrmax >> 8; + + return Successful; +} diff --git a/src/util/fontxlfd.c b/src/util/fontxlfd.c new file mode 100755 index 0000000..8124037 --- /dev/null +++ b/src/util/fontxlfd.c @@ -0,0 +1,632 @@ +/* + +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#if defined(sony) && !defined(SYSTYPE_SYSV) && !defined(_SYSTYPE_SYSV) +#define NO_LOCALE +#endif +#ifndef NO_LOCALE +#include +#endif +#include +#include /* for sprintf() */ + +static char * +GetInt(char *ptr, int *val) +{ + if (*ptr == '*') { + *val = -1; + ptr++; + } else + for (*val = 0; *ptr >= '0' && *ptr <= '9';) + *val = *val * 10 + *ptr++ - '0'; + if (*ptr == '-') + return ptr; + return (char *) 0; +} + +#define minchar(p) ((p).min_char_low + ((p).min_char_high << 8)) +#define maxchar(p) ((p).max_char_low + ((p).max_char_high << 8)) + + +#ifndef NO_LOCALE +static struct lconv *locale = 0; +#endif +static char *radix = ".", *plus = "+", *minus = "-"; + +static char * +readreal(char *ptr, double *result) +{ + char buffer[80], *p1, *p2; + +#ifndef NO_LOCALE + /* Figure out what symbols apply in this locale */ + + if (!locale) + { + locale = localeconv(); + if (locale->decimal_point && *locale->decimal_point) + radix = locale->decimal_point; + if (locale->positive_sign && *locale->positive_sign) + plus = locale->positive_sign; + if (locale->negative_sign && *locale->negative_sign) + minus = locale->negative_sign; + } +#endif + /* Copy the first 80 chars of ptr into our local buffer, changing + symbols as needed. */ + for (p1 = ptr, p2 = buffer; + *p1 && (p2 - buffer) < sizeof(buffer) - 1; + p1++, p2++) + { + switch(*p1) + { + case '~': *p2 = *minus; break; + case '+': *p2 = *plus; break; + case '.': *p2 = *radix; break; + default: *p2 = *p1; + } + } + *p2 = 0; + + /* Now we have something that strtod() can interpret... do it. */ + *result = strtod(buffer, &p1); + /* Return NULL if failure, pointer past number if success */ + return (p1 == buffer) ? (char *)0 : (ptr + (p1 - buffer)); +} + +static char * +xlfd_double_to_text(double value, char *buffer, int space_required) +{ + char formatbuf[40]; + register char *p1; + int ndigits, exponent; + +#ifndef NO_LOCALE + if (!locale) + { + locale = localeconv(); + if (locale->decimal_point && *locale->decimal_point) + radix = locale->decimal_point; + if (locale->positive_sign && *locale->positive_sign) + plus = locale->positive_sign; + if (locale->negative_sign && *locale->negative_sign) + minus = locale->negative_sign; + } +#endif + /* Compute a format to use to render the number */ + sprintf(formatbuf, "%%.%dle", XLFD_NDIGITS); + + if (space_required) + *buffer++ = ' '; + + /* Render the number using printf's idea of formatting */ + sprintf(buffer, formatbuf, value); + + /* Find and read the exponent value */ + for (p1 = buffer + strlen(buffer); + *p1-- != 'e' && p1[1] != 'E';); + exponent = atoi(p1 + 2); + if (value == 0.0) exponent = 0; + + /* Figure out how many digits are significant */ + while (p1 >= buffer && (!isdigit(*p1) || *p1 == '0')) p1--; + ndigits = 0; + while (p1 >= buffer) if (isdigit(*p1--)) ndigits++; + + /* Figure out notation to use */ + if (exponent >= XLFD_NDIGITS || ndigits - exponent > XLFD_NDIGITS + 1) + { + /* Scientific */ + sprintf(formatbuf, "%%.%dle", ndigits - 1); + sprintf(buffer, formatbuf, value); + } + else + { + /* Fixed */ + ndigits -= exponent + 1; + if (ndigits < 0) ndigits = 0; + sprintf(formatbuf, "%%.%dlf", ndigits); + sprintf(buffer, formatbuf, value); + if (exponent < 0) + { + p1 = buffer; + while (*p1 && *p1 != '0') p1++; + while (*p1++) p1[-1] = *p1; + } + } + + /* Last step, convert the locale-specific sign and radix characters + to our own. */ + for (p1 = buffer; *p1; p1++) + { + if (*p1 == *minus) *p1 = '~'; + else if (*p1 == *plus) *p1 = '+'; + else if (*p1 == *radix) *p1 = '.'; + } + + return buffer - space_required; +} + +double +xlfd_round_double(double x) +{ + /* Utility for XLFD users to round numbers to XLFD_NDIGITS + significant digits. How do you round to n significant digits on + a binary machine? */ + +#if defined(i386) || defined(__i386__) || \ + defined(ia64) || defined(__ia64__) || \ + defined(__alpha__) || defined(__alpha) || \ + defined(__hppa__) || \ + defined(__amd64__) || defined(__amd64) || \ + defined(sgi) +#include + +/* if we have IEEE 754 fp, we can round to binary digits... */ + +#if (FLT_RADIX == 2) && (DBL_DIG == 15) && (DBL_MANT_DIG == 53) + +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 +#endif +#ifndef M_LN10 +#define M_LN10 2.30258509299404568402 +#endif + +/* convert # of decimal digits to # of binary digits */ +#define XLFD_NDIGITS_2 ((int)(XLFD_NDIGITS * M_LN10 / M_LN2 + 0.5)) + + union conv_d { + double d; + unsigned char b[8]; + } d; + int i,j,k,d_exp; + + if (x == 0) + return x; + + /* do minor sanity check for IEEE 754 fp and correct byte order */ + d.d = 1.0; + if (sizeof(double) == 8 && d.b[7] == 0x3f && d.b[6] == 0xf0) { + + /* + * this code will round IEEE 754 double to XLFD_NDIGITS_2 binary digits + */ + + d.d = x; + d_exp = (d.b[7] << 4) | (d.b[6] >> 4); + + i = (DBL_MANT_DIG-XLFD_NDIGITS_2) >> 3; + j = 1 << ((DBL_MANT_DIG-XLFD_NDIGITS_2) & 0x07); + for (; i<7; i++) { + k = d.b[i] + j; + d.b[i] = k; + if (k & 0x100) j = 1; + else break; + } + if ((i==7) && ((d.b[6] & 0xf0) != ((d_exp<<4) & 0xf0))) { + /* mantissa overflow: increment exponent */ + d_exp = (d_exp & 0x800 ) | ((d_exp & 0x7ff) + 1); + d.b[7] = d_exp >> 4; + d.b[6] = (d.b[6] & 0x0f) | (d_exp << 4); + } + + i = (DBL_MANT_DIG-XLFD_NDIGITS_2) >> 3; + j = 1 << ((DBL_MANT_DIG-XLFD_NDIGITS_2) & 0x07); + d.b[i] &= ~(j-1); + for (;--i>=0;) d.b[i] = 0; + + return d.d; + } + else +#endif +#endif /* i386 || __i386__ */ + { + /* + * If not IEEE 754: Let printf() do it for you. + */ + + char formatbuf[40], buffer[40]; + + sprintf(formatbuf, "%%.%dlg", XLFD_NDIGITS); + sprintf(buffer, formatbuf, x); + return atof(buffer); + } +} + +static char * +GetMatrix(char *ptr, FontScalablePtr vals, int which) +{ + double *matrix; + + if (which == PIXELSIZE_MASK) + matrix = vals->pixel_matrix; + else if (which == POINTSIZE_MASK) + matrix = vals->point_matrix; + else return (char *)0; + + while (isspace(*ptr)) ptr++; + if (*ptr == '[') + { + /* This is a matrix containing real numbers. It would be nice + to use strtod() or sscanf() to read the numbers, but those + don't handle '~' for minus and we cannot force them to use a + "." for the radix. We'll have to do the hard work ourselves + (in readreal()). */ + + if ((ptr = readreal(++ptr, matrix + 0)) && + (ptr = readreal(ptr, matrix + 1)) && + (ptr = readreal(ptr, matrix + 2)) && + (ptr = readreal(ptr, matrix + 3))) + { + while (isspace(*ptr)) ptr++; + if (*ptr != ']') + ptr = (char *)0; + else + { + ptr++; + while (isspace(*ptr)) ptr++; + if (*ptr == '-') + { + if (which == POINTSIZE_MASK) + vals->values_supplied |= POINTSIZE_ARRAY; + else + vals->values_supplied |= PIXELSIZE_ARRAY; + } + else ptr = (char *)0; + } + } + } + else + { + int value; + if ((ptr = GetInt(ptr, &value))) + { + vals->values_supplied &= ~which; + if (value > 0) + { + matrix[3] = (double)value; + if (which == POINTSIZE_MASK) + { + matrix[3] /= 10.0; + vals->values_supplied |= POINTSIZE_SCALAR; + } + else + vals->values_supplied |= PIXELSIZE_SCALAR; + /* If we're concocting the pixelsize array from a scalar, + we will need to normalize element 0 for the pixel shape. + This is done in FontFileCompleteXLFD(). */ + matrix[0] = matrix[3]; + matrix[1] = matrix[2] = 0.0; + } + else if (value < 0) + { + if (which == POINTSIZE_MASK) + vals->values_supplied |= POINTSIZE_WILDCARD; + else + vals->values_supplied |= PIXELSIZE_WILDCARD; + } + } + } + return ptr; +} + + +static void +append_ranges(char *fname, int nranges, fsRange *ranges) +{ + if (nranges) + { + int i; + + strcat(fname, "["); + for (i = 0; i < nranges && strlen(fname) < 1010; i++) + { + if (i) strcat(fname, " "); + sprintf(fname + strlen(fname), "%d", + minchar(ranges[i])); + if (ranges[i].min_char_low == + ranges[i].max_char_low && + ranges[i].min_char_high == + ranges[i].max_char_high) continue; + sprintf(fname + strlen(fname), "_%d", + maxchar(ranges[i])); + } + strcat(fname, "]"); + } +} + +Bool +FontParseXLFDName(char *fname, FontScalablePtr vals, int subst) +{ + register char *ptr; + register char *ptr1, + *ptr2, + *ptr3, + *ptr4; + register char *ptr5; + FontScalableRec tmpvals; + char replaceChar = '0'; + char tmpBuf[1024]; + int spacingLen; + int l; + char *p; + + bzero(&tmpvals, sizeof(tmpvals)); + if (subst != FONT_XLFD_REPLACE_VALUE) + *vals = tmpvals; + + if (!(*(ptr = fname) == '-' || (*ptr++ == '*' && *ptr == '-')) || /* fndry */ + !(ptr = strchr(ptr + 1, '-')) || /* family_name */ + !(ptr1 = ptr = strchr(ptr + 1, '-')) || /* weight_name */ + !(ptr = strchr(ptr + 1, '-')) || /* slant */ + !(ptr = strchr(ptr + 1, '-')) || /* setwidth_name */ + !(ptr = strchr(ptr + 1, '-')) || /* add_style_name */ + !(ptr = strchr(ptr + 1, '-')) || /* pixel_size */ + !(ptr = GetMatrix(ptr + 1, &tmpvals, PIXELSIZE_MASK)) || + !(ptr2 = ptr = GetMatrix(ptr + 1, &tmpvals, POINTSIZE_MASK)) || + !(ptr = GetInt(ptr + 1, &tmpvals.x)) || /* resolution_x */ + !(ptr3 = ptr = GetInt(ptr + 1, &tmpvals.y)) || /* resolution_y */ + !(ptr4 = ptr = strchr(ptr + 1, '-')) || /* spacing */ + !(ptr5 = ptr = GetInt(ptr + 1, &tmpvals.width)) || /* average_width */ + !(ptr = strchr(ptr + 1, '-')) || /* charset_registry */ + strchr(ptr + 1, '-'))/* charset_encoding */ + return FALSE; + + /* Lop off HP charset subsetting enhancement. Interpreting this + field requires allocating some space in which to return the + results. So, to prevent memory leaks, this procedure will simply + lop off and ignore charset subsetting, and initialize the + relevant vals fields to zero. It's up to the caller to make its + own call to FontParseRanges() if it's interested in the charset + subsetting. */ + + if (subst != FONT_XLFD_REPLACE_NONE && + (p = strchr(strrchr(fname, '-'), '['))) + { + tmpvals.values_supplied |= CHARSUBSET_SPECIFIED; + *p = '\0'; + } + + /* Fill in deprecated fields for the benefit of rasterizers that care + about them. */ + tmpvals.pixel = (tmpvals.pixel_matrix[3] >= 0) ? + (int)(tmpvals.pixel_matrix[3] + .5) : + (int)(tmpvals.pixel_matrix[3] - .5); + tmpvals.point = (tmpvals.point_matrix[3] >= 0) ? + (int)(tmpvals.point_matrix[3] * 10 + .5) : + (int)(tmpvals.point_matrix[3] * 10 - .5); + + spacingLen = ptr4 - ptr3 + 1; + + switch (subst) { + case FONT_XLFD_REPLACE_NONE: + *vals = tmpvals; + break; + case FONT_XLFD_REPLACE_STAR: + replaceChar = '*'; + case FONT_XLFD_REPLACE_ZERO: + strcpy(tmpBuf, ptr2); + ptr5 = tmpBuf + (ptr5 - ptr2); + ptr3 = tmpBuf + (ptr3 - ptr2); + ptr2 = tmpBuf; + ptr = ptr1 + 1; + + ptr = strchr(ptr, '-') + 1; /* skip weight */ + ptr = strchr(ptr, '-') + 1; /* skip slant */ + ptr = strchr(ptr, '-') + 1; /* skip setwidth_name */ + ptr = strchr(ptr, '-') + 1; /* skip add_style_name */ + + if ((ptr - fname) + spacingLen + strlen(ptr5) + 10 >= (unsigned)1024) + return FALSE; + *ptr++ = replaceChar; + *ptr++ = '-'; + *ptr++ = replaceChar; + *ptr++ = '-'; + *ptr++ = '*'; + *ptr++ = '-'; + *ptr++ = '*'; + if (spacingLen > 2) + { + memmove(ptr, ptr3, spacingLen); + ptr += spacingLen; + } + else + { + *ptr++ = '-'; + *ptr++ = '*'; + *ptr++ = '-'; + } + *ptr++ = replaceChar; + strcpy(ptr, ptr5); + *vals = tmpvals; + break; + case FONT_XLFD_REPLACE_VALUE: + if (vals->values_supplied & PIXELSIZE_MASK) + { + tmpvals.values_supplied = + (tmpvals.values_supplied & ~PIXELSIZE_MASK) | + (vals->values_supplied & PIXELSIZE_MASK); + tmpvals.pixel_matrix[0] = vals->pixel_matrix[0]; + tmpvals.pixel_matrix[1] = vals->pixel_matrix[1]; + tmpvals.pixel_matrix[2] = vals->pixel_matrix[2]; + tmpvals.pixel_matrix[3] = vals->pixel_matrix[3]; + } + if (vals->values_supplied & POINTSIZE_MASK) + { + tmpvals.values_supplied = + (tmpvals.values_supplied & ~POINTSIZE_MASK) | + (vals->values_supplied & POINTSIZE_MASK); + tmpvals.point_matrix[0] = vals->point_matrix[0]; + tmpvals.point_matrix[1] = vals->point_matrix[1]; + tmpvals.point_matrix[2] = vals->point_matrix[2]; + tmpvals.point_matrix[3] = vals->point_matrix[3]; + } + if (vals->x >= 0) + tmpvals.x = vals->x; + if (vals->y >= 0) + tmpvals.y = vals->y; + if (vals->width >= 0) + tmpvals.width = vals->width; + else if (vals->width < -1) /* overload: -1 means wildcard */ + tmpvals.width = -vals->width; + + + p = ptr1 + 1; /* weight field */ + l = strchr(p, '-') - p; + sprintf(tmpBuf, "%*.*s", l, l, p); + + p += l + 1; /* slant field */ + l = strchr(p, '-') - p; + sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p); + + p += l + 1; /* setwidth_name */ + l = strchr(p, '-') - p; + sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p); + + p += l + 1; /* add_style_name field */ + l = strchr(p, '-') - p; + sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p); + + strcat(tmpBuf, "-"); + if ((tmpvals.values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY) + { + char buffer[80]; + strcat(tmpBuf, "["); + strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[0], + buffer, 0)); + strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[1], + buffer, 1)); + strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[2], + buffer, 1)); + strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[3], + buffer, 1)); + strcat(tmpBuf, "]"); + } + else + { + sprintf(tmpBuf + strlen(tmpBuf), "%d", + (int)(tmpvals.pixel_matrix[3] + .5)); + } + strcat(tmpBuf, "-"); + if ((tmpvals.values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY) + { + char buffer[80]; + strcat(tmpBuf, "["); + strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[0], + buffer, 0)); + strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[1], + buffer, 1)); + strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[2], + buffer, 1)); + strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[3], + buffer, 1)); + strcat(tmpBuf, "]"); + } + else + { + sprintf(tmpBuf + strlen(tmpBuf), "%d", + (int)(tmpvals.point_matrix[3] * 10.0 + .5)); + } + sprintf(tmpBuf + strlen(tmpBuf), "-%d-%d%*.*s%d%s", + tmpvals.x, tmpvals.y, + spacingLen, spacingLen, ptr3, tmpvals.width, ptr5); + strcpy(ptr1 + 1, tmpBuf); + if ((vals->values_supplied & CHARSUBSET_SPECIFIED) && !vals->nranges) + strcat(fname, "[]"); + else + append_ranges(fname, vals->nranges, vals->ranges); + break; + } + return TRUE; +} + +fsRange *FontParseRanges(char *name, int *nranges) +{ + int n; + unsigned long l; + char *p1, *p2; + fsRange *result = (fsRange *)0; + + name = strchr(name, '-'); + for (n = 1; name && n < 14; n++) + name = strchr(name + 1, '-'); + + *nranges = 0; + if (!name || !(p1 = strchr(name, '['))) return (fsRange *)0; + p1++; + + while (*p1 && *p1 != ']') + { + fsRange thisrange; + + l = strtol(p1, &p2, 0); + if (p2 == p1 || l > 0xffff) break; + thisrange.max_char_low = thisrange.min_char_low = l & 0xff; + thisrange.max_char_high = thisrange.min_char_high = l >> 8; + + p1 = p2; + if (*p1 == ']' || *p1 == ' ') + { + while (*p1 == ' ') p1++; + if (add_range(&thisrange, nranges, &result, TRUE) != Successful) + break; + } + else if (*p1 == '_') + { + l = strtol(++p1, &p2, 0); + if (p2 == p1 || l > 0xffff) break; + thisrange.max_char_low = l & 0xff; + thisrange.max_char_high = l >> 8; + p1 = p2; + if (*p1 == ']' || *p1 == ' ') + { + while (*p1 == ' ') p1++; + if (add_range(&thisrange, nranges, &result, TRUE) != Successful) + break; + } + } + else break; + } + + return result; +} diff --git a/src/util/format.c b/src/util/format.c new file mode 100755 index 0000000..f5424fe --- /dev/null +++ b/src/util/format.c @@ -0,0 +1,124 @@ +/* + * Copyright 1990, 1991 Network Computing Devices; + * Portions Copyright 1987 by Digital Equipment Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the names of Network Computing Devices or Digital + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Network Computing + * Devices and Digital make no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES OR DIGITAL BE + * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include + +int +CheckFSFormat(fsBitmapFormat format, + fsBitmapFormatMask fmask, + int *bit_order, + int *byte_order, + int *scan, + int *glyph, + int *image) +{ + /* convert format to what the low levels want */ + if (fmask & BitmapFormatMaskBit) { + *bit_order = format & BitmapFormatBitOrderMask; + *bit_order = (*bit_order == BitmapFormatBitOrderMSB) + ? MSBFirst : LSBFirst; + } + if (fmask & BitmapFormatMaskByte) { + *byte_order = format & BitmapFormatByteOrderMask; + *byte_order = (*byte_order == BitmapFormatByteOrderMSB) + ? MSBFirst : LSBFirst; + } + if (fmask & BitmapFormatMaskScanLineUnit) { + *scan = format & BitmapFormatScanlineUnitMask; + /* convert byte paddings into byte counts */ + switch (*scan) { + case BitmapFormatScanlineUnit8: + *scan = 1; + break; + case BitmapFormatScanlineUnit16: + *scan = 2; + break; + case BitmapFormatScanlineUnit32: + *scan = 4; + break; + default: + return BadFontFormat; + } + } + if (fmask & BitmapFormatMaskScanLinePad) { + *glyph = format & BitmapFormatScanlinePadMask; + /* convert byte paddings into byte counts */ + switch (*glyph) { + case BitmapFormatScanlinePad8: + *glyph = 1; + break; + case BitmapFormatScanlinePad16: + *glyph = 2; + break; + case BitmapFormatScanlinePad32: + *glyph = 4; + break; + default: + return BadFontFormat; + } + } + if (fmask & BitmapFormatMaskImageRectangle) { + *image = format & BitmapFormatImageRectMask; + + if (*image != BitmapFormatImageRectMin && + *image != BitmapFormatImageRectMaxWidth && + *image != BitmapFormatImageRectMax) + return BadFontFormat; + } + return Successful; +} diff --git a/src/util/miscutil.c b/src/util/miscutil.c new file mode 100755 index 0000000..7173d36 --- /dev/null +++ b/src/util/miscutil.c @@ -0,0 +1,61 @@ +/* + +Copyright 1991, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include "stubs.h" + +#define XK_LATIN1 +#include + + +#ifdef __SUNPRO_C +#pragma weak serverGeneration +#pragma weak register_fpe_functions +#endif + +extern void BuiltinRegisterFpeFunctions(void); + +#ifndef NO_WEAK_SYMBOLS +/* make sure everything initializes themselves at least once */ +weak long serverGeneration = 1; +#endif + +weak void +register_fpe_functions (void) +{ + BuiltinRegisterFpeFunctions(); + FontFileRegisterFpeFunctions(); +#ifdef XFONT_FC + fs_register_fpe_functions(); +#endif +} diff --git a/src/util/patcache.c b/src/util/patcache.c new file mode 100755 index 0000000..548105a --- /dev/null +++ b/src/util/patcache.c @@ -0,0 +1,218 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +/* + * Static sized hash table for looking up font name patterns + * + * LRU entries, reusing old entries + */ + +#define NBUCKETS 16 +#define NENTRIES 64 + +#define UNSET (NENTRIES+1) + +typedef unsigned char EntryPtr; + +typedef struct _FontPatternCacheEntry { + struct _FontPatternCacheEntry *next, **prev; + short patlen; + char *pattern; + int hash; + FontPtr pFont; /* associated font */ +} FontPatternCacheEntryRec, *FontPatternCacheEntryPtr; + +typedef struct _FontPatternCache { + FontPatternCacheEntryPtr buckets[NBUCKETS]; + FontPatternCacheEntryRec entries[NENTRIES]; + FontPatternCacheEntryPtr free; +} FontPatternCacheRec; + +/* Empty cache (for rehash) */ +void +EmptyFontPatternCache (FontPatternCachePtr cache) +{ + int i; + + for (i = 0; i < NBUCKETS; i++) + cache->buckets[i] = 0; + for (i = 0; i < NENTRIES; i++) + { + cache->entries[i].next = &cache->entries[i+1]; + cache->entries[i].prev = 0; + cache->entries[i].pFont = 0; + free (cache->entries[i].pattern); + cache->entries[i].pattern = 0; + cache->entries[i].patlen = 0; + } + cache->free = &cache->entries[0]; + cache->entries[NENTRIES - 1].next = 0; +} + +/* Create and initialize cache */ +FontPatternCachePtr +MakeFontPatternCache (void) +{ + FontPatternCachePtr cache; + int i; + cache = malloc (sizeof *cache); + if (!cache) + return 0; + for (i = 0; i < NENTRIES; i++) { + cache->entries[i].patlen = 0; + cache->entries[i].pattern = 0; + cache->entries[i].pFont = 0; + } + EmptyFontPatternCache (cache); + return cache; +} + +/* toss cache */ +void +FreeFontPatternCache (FontPatternCachePtr cache) +{ + int i; + + for (i = 0; i < NENTRIES; i++) + free (cache->entries[i].pattern); + free (cache); +} + +/* compute id for string */ +static int +Hash (const char *string, int len) +{ + int hash; + + hash = 0; + while (len--) + hash = (hash << 1) ^ *string++; + if (hash < 0) + hash = -hash; + return hash; +} + +/* add entry */ +void +CacheFontPattern (FontPatternCachePtr cache, + char *pattern, + int patlen, + FontPtr pFont) +{ + FontPatternCacheEntryPtr e; + char *newpat; + int i; + + newpat = malloc (patlen); + if (!newpat) + return; + if (cache->free) + { + e = cache->free; + cache->free = e->next; + } + else + { + i = rand (); + if (i < 0) + i = -i; + i %= NENTRIES; + e = &cache->entries[i]; + if (e->next) + e->next->prev = e->prev; + *e->prev = e->next; + free (e->pattern); + } + /* set pattern */ + memcpy (newpat, pattern, patlen); + e->pattern = newpat; + e->patlen = patlen; + /* link to new hash chain */ + e->hash = Hash (pattern, patlen); + i = e->hash % NBUCKETS; + e->next = cache->buckets[i]; + if (e->next) + e->next->prev = &(e->next); + cache->buckets[i] = e; + e->prev = &(cache->buckets[i]); + e->pFont = pFont; +} + +/* find matching entry */ +FontPtr +FindCachedFontPattern (FontPatternCachePtr cache, + char *pattern, + int patlen) +{ + int hash; + int i; + FontPatternCacheEntryPtr e; + + hash = Hash (pattern, patlen); + i = hash % NBUCKETS; + for (e = cache->buckets[i]; e; e = e->next) + { + if (e->patlen == patlen && e->hash == hash && + !memcmp (e->pattern, pattern, patlen)) + { + return e->pFont; + } + } + return 0; +} + +void +RemoveCachedFontPattern (FontPatternCachePtr cache, + FontPtr pFont) +{ + FontPatternCacheEntryPtr e; + int i; + + for (i = 0; i < NENTRIES; i++) + { + if ((e = &cache->entries[i])->pFont == pFont) + { + e->pFont = 0; + if (e->next) + e->next->prev = e->prev; + *e->prev = e->next; + e->next = cache->free; + cache->free = e; + free (e->pattern); + e->pattern = 0; + } + } +} diff --git a/src/util/private.c b/src/util/private.c new file mode 100755 index 0000000..36715b1 --- /dev/null +++ b/src/util/private.c @@ -0,0 +1,105 @@ +/* + +Copyright 1991, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include + +static int _FontPrivateAllocateIndex = 0; + +int +AllocateFontPrivateIndex (void) +{ + return _FontPrivateAllocateIndex++; +} + +FontPtr +CreateFontRec (void) +{ + FontPtr pFont; + int size; + + size = sizeof(FontRec) + (sizeof(pointer) * _FontPrivateAllocateIndex); + + pFont = malloc(size); + + if(pFont) { + bzero((char*)pFont, size); + pFont->maxPrivate = _FontPrivateAllocateIndex - 1; + if(_FontPrivateAllocateIndex) + pFont->devPrivates = (pointer)(&pFont[1]); + } + + return pFont; +} + +void +DestroyFontRec (FontPtr pFont) +{ + if (pFont->devPrivates && pFont->devPrivates != (pointer)(&pFont[1])) + free(pFont->devPrivates); + free(pFont); +} + +void +ResetFontPrivateIndex (void) +{ + _FontPrivateAllocateIndex = 0; +} + +Bool +_FontSetNewPrivate (FontPtr pFont, int n, pointer ptr) +{ + pointer *new; + + if (n > pFont->maxPrivate) { + if (pFont->devPrivates && pFont->devPrivates != (pointer)(&pFont[1])) { + new = realloc (pFont->devPrivates, (n + 1) * sizeof (pointer)); + if (!new) + return FALSE; + } else { + /* omg realloc */ + new = malloc ((n + 1) * sizeof (pointer)); + if (!new) + return FALSE; + if (pFont->devPrivates) + memcpy (new, pFont->devPrivates, (pFont->maxPrivate + 1) * sizeof (pointer)); + } + pFont->devPrivates = new; + /* zero out new, uninitialized privates */ + while(++pFont->maxPrivate < n) + pFont->devPrivates[pFont->maxPrivate] = (pointer)0; + } + pFont->devPrivates[n] = ptr; + return TRUE; +} + diff --git a/src/util/utilbitmap.c b/src/util/utilbitmap.c new file mode 100755 index 0000000..5feb2d1 --- /dev/null +++ b/src/util/utilbitmap.c @@ -0,0 +1,185 @@ +/* + +Copyright 1990, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +/* Utility functions for reformating font bitmaps */ + +static const unsigned char _reverse_byte[0x100] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff +}; + +/* + * Invert bit order within each BYTE of an array. + */ +void +BitOrderInvert(unsigned char *buf, int nbytes) +{ + const unsigned char *rev = _reverse_byte; + + for (; --nbytes >= 0; buf++) + *buf = rev[*buf]; +} + +/* + * Invert byte order within each 16-bits of an array. + */ +void +TwoByteSwap(unsigned char *buf, int nbytes) +{ + unsigned char c; + + for (; nbytes > 0; nbytes -= 2, buf += 2) + { + c = buf[0]; + buf[0] = buf[1]; + buf[1] = c; + } +} + +/* + * Invert byte order within each 32-bits of an array. + */ +void +FourByteSwap(unsigned char *buf, int nbytes) +{ + unsigned char c; + + for (; nbytes > 0; nbytes -= 4, buf += 4) + { + c = buf[0]; + buf[0] = buf[3]; + buf[3] = c; + c = buf[1]; + buf[1] = buf[2]; + buf[2] = c; + } +} + +/* + * Repad a bitmap + */ + +int +RepadBitmap (char *pSrc, char *pDst, + unsigned int srcPad, unsigned int dstPad, + int width, int height) +{ + int srcWidthBytes,dstWidthBytes; + int row,col; + char *pTmpSrc,*pTmpDst; + + switch (srcPad) { + case 1: + srcWidthBytes = (width+7)>>3; + break; + case 2: + srcWidthBytes = ((width+15)>>4)<<1; + break; + case 4: + srcWidthBytes = ((width+31)>>5)<<2; + break; + case 8: + srcWidthBytes = ((width+63)>>6)<<3; + break; + default: + return 0; + } + switch (dstPad) { + case 1: + dstWidthBytes = (width+7)>>3; + break; + case 2: + dstWidthBytes = ((width+15)>>4)<<1; + break; + case 4: + dstWidthBytes = ((width+31)>>5)<<2; + break; + case 8: + dstWidthBytes = ((width+63)>>6)<<3; + break; + default: + return 0; + } + + width = srcWidthBytes; + if (width > dstWidthBytes) + width = dstWidthBytes; + pTmpSrc= pSrc; + pTmpDst= pDst; + for (row = 0; row < height; row++) + { + for (col = 0; col < width; col++) + *pTmpDst++ = *pTmpSrc++; + while (col < dstWidthBytes) + { + *pTmpDst++ = '\0'; + col++; + } + pTmpSrc += srcWidthBytes - width; + } + return dstWidthBytes * height; +} + + diff --git a/xfont.pc.in b/xfont.pc.in new file mode 100644 index 0000000..f08dea0 --- /dev/null +++ b/xfont.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Xfont +Description: X font Library +Version: @VERSION@ +Requires: xproto fontsproto +Requires.private: fontenc @FREETYPE_REQUIRES@ +Cflags: -I${includedir} +Libs: -L${libdir} -lXfont +Libs.private: @Z_LIBS@ -lm -- 2.7.4