Add source files

This commit is contained in:
2025-02-10 16:18:49 +01:00
parent 7b08eab832
commit 12ab9f20bc
57 changed files with 1268921 additions and 0 deletions

View File

@ -0,0 +1,23 @@
These are release versions of the GNU FreeFont fonts.
You probably want to get just one of them, the one with the most recent date,
that matches your needs.
As of the 2012 release,
The "otf" files are OpenType, for use in most modern operating systems.
The "ttf" files are TrueType, (strongly) preferred for Windows.
The "woff" files are Web Open Font Format files, for use as Web fonts.
The "src" and "sfd" files hold FontForge "Spline Font Database" files,
for use by font developers.
The ".sig" files are an accountability requirement of GNU upload policies.
You probably don't need that.
(In releases prior to 2012, OpenType was preferred for Windows, and TrueType
for other systems. The essential difference is that now the internal format
of the letters in the OpenType files is cubic spline (PostScript) and of the
TrueType is quadratic spline (TrueType).)

25
src/notes/building.txt Normal file
View File

@ -0,0 +1,25 @@
Building GNU FreeFont
The only files that are "built" in this project are binary font files.
They are built using FontForge, which must be installed before any
build is done.
To build all the font files, just cd to the top directory and type
make
(this will also work from within the sfd/ directory.)
Several special build targets are also present:
ttf TrueType format fonts only
otf OpenType format fonts only
woff WOFF format fonts only
ttfzip .zip archive of TrueType format fonts
otftar tarball of OpenType format fonts
woffzip .zip archive of WOFF format fonts
srctar tarball of sources
tests run a battery of tests on the sources and built files
clean
$Id: building.txt,v 1.10 2011-07-16 08:38:06 Stevan_White Exp $

119
src/notes/features.txt Normal file
View File

@ -0,0 +1,119 @@
OpenType features in GNU FreeFont
The OpenType font standard specifies numerous "features", which describe
how glyphs should be rendered under certain circumstances.
Some features, such as ligatures, substitute one glyph (or glyphs) with
others. Other features such as kerning adjust the positioning of glyphs.
A feature may be activated for text of a certain script (such as Cyrillic
or Arabic) in a certain language or region (as can be specified in HTML
elements with the "lang" attribute), and some are activated only in case
other features are not activated.
The actual rendering of these features is not by the font itself but rather
by font rendering software in the operating system or application or printer.
As of this writing, feature support is far from perfect in many environments.
The features are encoded in the font's "lookup tables". Each table has
a four-byte name.
The feature lookup tables used in FreeFont include:
Substitution (GSUB)
============
rlig required ligature
liga standard ligature
hlig historic ligature
dlig discretionary ligature
hist historic form
locl localized form
smcp lowercase to small capitals
c2sc captials to small capitals
frac diagonal fractions
zero slashed zero
onum oldstyle figures
ccmp glyph decomposition (multiple replacement)
contextual chained substitution
aalt access all alternates
calt contextual alternates
Arabic
------
init initial forms
medi medial forms
fina final formes
Indic scripts
-------------
(these are always applied in exactly the following order)
nukt nukta forms
akhn akhand
rphf reph form
blwf below base forms
half half form
vatu vattu variants
pres pre base substitutions
abvs above base substitutions
blws below base substitutions
psts post base substitutions
haln halant forms
Positioning (GPOS)
===========
kern kerning
mark mark-to-base
mkmk mark-to-mark
Indic scripts
-------------
dist distance (similar to kern)
abvm above mark
blwm below mark
Use and Policies
================
kerning
-------
Kerning is viewed as a delicate adjustment of horizontal positioning of
letters based on the relative shapes of adjacent letters.
The first goal of kerning is to enhance the appearance of coherence in
words, by reducing apparent spaces beteen adjacent letters.
The second is to make the spacing appear somehow "smooth".
A few pairs of letters are strongly kerned, for example 'AV'. With very few
exceptions, one letter should not visually intrude on the horizontal space of
another. (Exceptions might include the hooks on f and y.)
For instance, in serifed fonts, the serifs of most letters should have a
visible space between them, and should not visually intrude on one another
horizontally.
For most others, the policy is "err on the conservative side".
A common mistake is to try to minimize the area between the letters
-- this has a poor effect on the appearance of the text.
After kerning, bulk text should be carefully inspected both in print and on
the screen in different resolutions, that the letters appear evenly-spaced,
and never crash into one another.
mark positioning
----------------
It is conceptually more direct, and in principle easier, to position marks
relative to letters using the various mark positioning lookups.
Unfortunately, the implementation of these features has been rather spotty.
Especially in cases where multiple marks appear on the same base, it can
get just too messy to be practical. Unfortunately, often pre-composed
components are a necessary fallback.
$Id: features.txt,v 1.1 2011-07-16 11:24:10 Stevan_White Exp $

122
src/notes/maintenance.txt Normal file
View File

@ -0,0 +1,122 @@
On preparing the FreeFont package for release.
1) Makefile
The command
make
will build the TrueType font files in the sfd directory.
The command
make package
creates four archive files: one tarball of sources (SFD files), a zip
of TrueType fonts, a tarball of OpenType fonts, and a zip of WOFF
format fonts. The naming convention is:
freefont-src-yyyymmdd.tar.gz
freefont-ttf-yyyymmdd.zip
freefont-otf-yyyymmdd.tar.gz
freefont-woff-yyyymmdd.zip
where yyyymmdd is the year, month and date of release.
The Makefile also has other targets, for building individual components
of the distribution.
2) Checking for font problems
It is important to execute all the available tests before release,
and make the fonts pass all of them. Toward this goal the fonts
should also be checked before commits.
The first check is the FontForge "Verifiy" command.
Beyond that are its checks in "Find Problems...".
Several further FreeFont checks are executed by
make tests
Note that failure of some of these will result in visible problems
when the font is used. For example, failure of some of the "ATT"
checks may cause whole font features in the lookups to be silently
shut off by the font rendering software.
3) Adding files to the download area
The gnupload script, which has some connection to automake, is the
neatest way to upload files to Savannah. You may have to acquire it
from somebody.
Requires 'ncftp'
/bin/sh ~/bin/gnupload --to ftp.gnu.org:freefont freefont-otf-20080324.zip
It prompts for a PGP password, creates the signature files required
by the Savannah upload procedures, and uploads all of them.
4) Creating detached signature file, as in the "raw" upload procedures:
http://www.gnu.org/prep/maintain/maintain.html#Automated-Upload-Registration
gpg -b freefont-ttf-20060126.zip
This creates a "detached GPD binary signature" file freefont-ttf.tar.gz.sig
5) Commiting a SVN file
svn co svn+ssh://user_name@svn.savannah.gnu.org/freefont/trunk/freefont
cd freefont/sfd
svn commit FreeSans.sfd
6) a) Tagging a release in SVN
svn copy svn://svn.savannah.gnu.org/freefont/trunk \
svn://svn.savannah.gnu.org/freefont/tags/RELEASE_20120503 \
-m "Tagging the 03.05.2012 release."
b) Tagging a release in CVS
cvs rtag RELEASE_TAG_NAME freefont
Removing a tag
cvs rtag -d RELEASE_TAG_NAME freefont
Retrieving a tagged release
cvs checkout -P -r RELEASE_TAG_NAME freefont
7) Using Change Log mode in Emacs
C-x 4 a adds a new entry to the change log file
8) New release procedures
Update the Changelog.
Review the AUTHORS and CREDITS files for competeness.
Ensure that "make tests" completes cleanly.
Tag new releases with tag named RELEASE_date, where date is the date.
Add release date field value to bug report field "Release".
Upload the archive files to Savannah.
Write to freefont-announce@gnu.org
Write to info-gnu@gnu.org
Write to pkg-fonts-devel@lists.alioth.debian.org,
and Debian freefont-ttf packager
Mark "Fix in source" bug reports as "Fixed"
9) Adding ssh keys to Savannah
Otherwise get errors like
Permission denied (publickey).
cvs [checkout aborted]: end of file from server
Log in as Savannah project admin
Click My Account Conf (from menu list on far left)
Edit the (n) SSH Public Keys registered
Paste in a public rsa key (can have up to 5)
Click Update.
10) Adding binaries (such as TrueType fonts) to CVS, as for web pages
Remember to add with the -kb flag,
cvs add -kb myfont.ttf
or it will mess the binary up and waste days of your life.
$Id: maintenance.txt 2267 2012-05-03 11:57:14Z Stevan_White $

View File

@ -0,0 +1,115 @@
Troubleshooting GNU FreeFont
So your text looks lousy, although you installed FreeFont and you seem to be
using it. What do you do?
Before you blame the problem on FreeFont, take the time to double-check that
the text you are looking at is really rendered with FreeFont.
Be aware that not all Unicode characters are supported by FreeFont, and
even characters supported by one face, such as Serif, might not be
supported by other faces such as Sans.
Also, some systems have settings that strongly affect the rendering
of fonts. It may be worth tweaking these.
glyph substitution
==================
When given the task of displaying characters in text, modern font rendering
software usually tries to display *something*, even if the font it is
*supposed* to be using does not contain glyphs for all the characters in the
text. The software will snoop through all the fonts on the system to find
one that has a glyph for the one missing in the desired font. So although
you have specified FreeSans-bold, you may be looking at a letter from quite
a different font.
First double-check that the font in question really contains the character
in question. If you don't have font development software, this can be
tricky. In the case of FreeFont, you can check if a given character
range is supported: <http://www.gnu.org/software/freefont/coverage.html>
Next double-check that your application (web browser, text editor, etc)
has indeed been properly instructed to use the font.
Then double-check that the font is really installed in the system.
(This depends on the operating system, of course.)
Linux and Unix
==============
Modern Linux systems use a system called fontconfig, which maintains a font
cache, for efficiency.
The font cache can really complicate font installation and troubleshooting
however. It can happen that when a font is newly installed, what is
displayed is coming out of an old cache entry rather than the new font.
Just what to do depends on how and where the font was installed.
Fonts installed system-wide are usually put in a directory such as
/usr/share/fonts/
the font cache for these might be in
/var/cache/fontconfig/
Fonts installed just for one user account will typically be in
~/.fonts/
and the cache will be
~/.fontconfig/
You can clean your local cache merely by emptying the directory
~/.fontconfig/
In any case, to clean the cache, you can use the fontconfig command
fc-cache -vf
If run as root, it will clean the system cache, if run as a normal user,
it cleans only the normal user's cache.
The procedure for local fonts is:
1) shut off any program using the fonts in question
2) clean the cache
3) re-start the program
The procedure for system-wide fonts is:
1) log out of the X Windows session
2) in a console, clean the cache
3) log in to an X Windows session
LibreOffice / OpenOffice
========================
These products have their own font rendering libraries, which have
idiosyncratic behavior.
It has recently been reported that as of LibreOffice 3.5.1, font features
are disabled for OpenType fonts. If you use FreeFont with these products,
you may want to install the TrueType versions of the fonts.
Windows
=======
The most common complaint has to do with "blurry text". There are two
causes.
The first is that ClearType smoothing is turned off. The best way to check
is to use the native Windows Web browser. Do a search for "ClearType Tuner".
The Microsoft pages install a tuner for ClearType. A security block notice
will appear at the top of the window--you have to allow the installation.
Then check the box "Turn on ClearType". The change happens immediately.
The secont cause is that the FreeFont version with cubic spline outlines is
installed. As of the 2012 GNU FreeFont release, the TrueType builds have
quadratic splines, which work best with Windows' rendering software.
TTF (TrueType) quadratic splines Windows 7, Vista, Windows XP.
OTF (OpenType) cubic splines Linux, Mac
Note also: Firefox has a setting for ClearType:
gfx.font_rendering.cleartype_params.rendering_mode
A value of 2 sets it to old-style GDI rendering, while -1 is the default.
reporting problems
==================
If you really think you're seeing a bug in FreeFont, or if you have
a suggestion, consider opening a problem report at
https://savannah.gnu.org/bugs/?group=freefont
It is best that you make a Savannah account and log in with that, so
you can be e-mailed whenever changes are made to your report.
$Id: troubleshooting.txt,v 1.10 2011-07-16 08:38:06 Stevan_White Exp $

185
src/notes/usage.txt Normal file
View File

@ -0,0 +1,185 @@
Usage of GNU FreeFont
Language scripts and faces
==========================
There are three faces (serif, sans-serif, and monospace), and four styles
(regular, bold, cursive/italic, and bold cursive/italic) for each face.
There is one font file per face/style combination: 12 files in total.
The letters for various languages, as well as specialized symbols, exist
among the various font files, but they are not uniformly populated.
All the fonts have complete support for Latin, Cyrillic, and Greek, as
well as most of the extensions for those scripts.
At this time, serif regular has by far the largest number of letters, and
supports the largest number of writing scripts. However there are writing
scripts supported by the sans-serif but not by serif.
For an overview of which scripts and sets of symbols are supported by
which face, see the FreeFont 'coverage' web page.
Font features
=============
FreeFont has numerous font "features" that perform alterations to the basic
letters of the font, replacing them with other letters, or positioning them
with respect to other letters.
Many features are activated automatically, but in some environments, they
present some user control. This documents those features with user control.
Language-specific features
==========================
Some OpenType font features are activated only when the text is specified to
be of a certain language.
This is done in HTML by enclosing the text with a tag whose 'lang' attribute
is set to the appropriate ISO 632.2 language code. In a word processor,
any block of text can be given a language setting.
Latin
-----
Catalan ligature improving l·l
Dutch ligatures for ij, IJ
Sami localized form for letter Eng
Turkish overrides ligatures fi ffi of Latin
Cyrillic
--------
Ukrainian ligature for double i-diaresis
Serbian/Macedonian localized letters be, and more in italic
Bulgarian style set for modern glyphs
Hebrew
------
Yiddish raised vowels under yo
Devanagari
----------
Sanskrit much larger set of ligatures
Hindi, Marathi better spacing of Western punctuation marks
Indic languages
---------------
The 'danda' character is encoded in Unicode only in the Devanagari range.
When writing in scripts of other Indic languages, this same character is to
be used. But the shapes and line thicknesses of glyphs vary slightly from
one script to another, so the same glyph for 'danda' may not fit all scripts.
By specifying the language of the text, an appropriate glyph for 'danda'
will be obtained.
Style sets
==========
These replacements are activated by specifying a "Style Set".
These features are accessible only from typesetting software.
Cyrillic Bulgarian modern (ss01)
Devanagari Bombay (ss02), Calcutta (ss03), Nepali (ss04)
Discretionary features
======================
These features are accessible only from typesetting software.
Typically the user must specifically request them.
Unless otherwise noted, these are available only in FreeSerif.
Ligatures and substitutions
---------------------------
Arabic, Armenian, Hebrew, German, Dutch
Small captials
--------------
A limited set of specially drawn small capital letters in Latin.
Superscript and subscript
-------------------------
Transform a limited set of characters--mostly Latin letters and numerals--
to versions well-sized and positioned as superscript or subscript.
Numeral styles
--------------
The default numerals of FreeSerif are mono-spaced and of even height.
It also features proportionally-spaced numerals, and "old-style" numerals--
those which vary in height and sometimes go beneath the baseline.
These can be had at discretion.
Diagonal fractions
------------------
A limited set of diagonal fraction substitutions are available at discretion.
The set is more than what is encoded in Unicode.
They work with the ASCII slash or the mathematical slash U+2215.
The transform a sequence "number-slash-number" to a diagonal form.
Zero
----
A slashed form of the numeral zero is available at discretion.
Available in all faces.
Alternative characters
======================
FreeSerif has some listings of alternatives for specific characters.
Again this is use primarily in specialized typesetting software.
Greek, Latin
Use in LaTeX
============
It is possible to use Unicode fonts in recent LaTeX implementations, but in
LuaTeX http://www.luatex.org/ and
XeTeX http://tug.org/xetex/
it is particularly easy to use Unicode text, and to enable font features.
Recent versions of these systems use the 'fontspec' package to choose fonts
and features.
A very simple document might contain the lines
---------------------------------------------------------------------------
\documentclass{ltxdockit}
\usepackage{fontspec}
\usepackage{xunicode}
\setmainfont[]{FreeSerif}
\begin{document}
{\fontspec[Script=Default,Fractions={On}]{FreeSerif}
1/7 3/10 7/10}
x\raisebox{-0.5ex}{{\scriptsize ai}}
x{\fontspec[Script=Default,VerticalPosition={Inferior}]{FreeSerif}
abcdefghijklmnopqrstuvwxyz+(0123456789)} \\
x\raisebox{0.85ex}{{\scriptsize ai}}
x{\fontspec[Script=Default,VerticalPosition={Superior}]{FreeSerif}
abcdefghijklmnopqrstuvwxyz+(0123456789)}
{\fontspec[Script=Latin]{FreeSerif}
\textsc{Small Caps} }
{ Bсички хора се раждат свободни и равни по достойнство и права.
\fontspec[Script=Cyrillic,Language=Bulgarian,Variant={1}]{FreeSerif} \selectfont
Bсички хора се раждат свободни и равни по достойнство и права. }
\end{document}
---------------------------------------------------------------------------
Here are some 'fontspec' setting-value pairs meaningful for FreeFont.
Numbers: Lining OldStyle Proportional SlashedZero
Fractions: On
VerticalPosition: Superior Inferior
Ligatures: Common Historical
Letters: UppercaseSmallCaps
Variant: 1 (etc. -- must be in {} picks style set.)
---------------------------------------------------------------------------
$Id: usage.txt,v 1.10 2011-07-16 08:38:06 Stevan_White Exp $

View File

@ -0,0 +1,84 @@
GNU FreeFont as Web Font
The GPL and your web site
-------------------------
The GPL license permits the use of GNU FreeFont binary files of release
20100919 or later as Web fonts with the CSS @font-face technology.
Note that releases of the fonts earlier than 20100919 *do not* contain
adequate license information, and *must not* be used as Web fonts.
We will refer to the releases dated 20100919 or later as "licensed releases".
Proper use of licensed releases of GPL FreeFont with this technology does
not in itself incur the requirements of the GPL, either on the Web page
from which the font is referenced, or the Web site that hosts the font file.
From the point of view of the GPL, the @font-face technology is a distribution
system of font files. According to the GPL, the files must be delivered with
intact notifications of the license, and of where to get the original source
files. Furthermore, if the files are modified in any way, a notice must be
delivered of who modified the files on what date, and what modifications
were made.
The licensed release font binary files as packaged on the GNU FreeFont
download page have embedded within them the license and origin notices
required to re-distribute them unmodified.
Software for reading the contents of font files is readily available for
anybody who wishes to look at the embedded notices.
Using the fonts without modifications
-------------------------------------
If you simply distribute the TrueType, OpenType, or WOFF files of licensed
releases as packaged at the GNU FreeFont download site, the requirements of
the GPL are already fulfilled.
Modifying the fonts for use as Web fonts
----------------------------------------
You may wish to modify the fonts for use as web fonts.
For example, perhaps your site needs only a portion of the font's glyphs.
As the fonts are very large, it may improve loading speed very much to
cut out unneeded parts of the font.
If you provide modified versions of the fonts, you must take care to
satisfy the GPL stipulation that two kinds of notices must be provided
with any distribution of FreeFont. These are
1) the original GPL license and notifications of origin
2) a description of modifications made to the font: who, when, what.
This information *must* be present in the font binary files delivered
from the web site.
There is more than one way to satisfy the GPL.
The simplest strategy would be the following:
Leave undisturbed the original "TTF Names" fields of the licensed release
font binaries:
Version
Copyright
Manufacturer
Vendor
Vendor URL
License
License URL
In the font file's "TTF Names" field with ID "Descriptor", append text
indicating
* who performed the modifications, and their contact information
* date of modifications
* outline of what was modified
For example:
Modified Oct. 2011 by Steve White <stevan.white@gmail.com>
Most character ranges besides Latin were removed.
If you do more than simply trim away character ranges from the font,
we at the FreeFont project we would ask you to
* append your own copyright notice to the Copyright field
* change the Version string to your own
* change Vendor and Vendor URL to your own name and URL.
(We don't want to be getting bug reports on your modifications!)
$Id: webfont_guidelines.txt 2221 2012-04-16 22:45:30Z Stevan_White $

95642
src/sfd/FreeMono.sfd Normal file

File diff suppressed because it is too large Load Diff

45230
src/sfd/FreeMonoBold.sfd Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

53553
src/sfd/FreeMonoOblique.sfd Normal file

File diff suppressed because it is too large Load Diff

194635
src/sfd/FreeSans.sfd Normal file

File diff suppressed because it is too large Load Diff

60817
src/sfd/FreeSansBold.sfd Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

76266
src/sfd/FreeSansOblique.sfd Normal file

File diff suppressed because it is too large Load Diff

359706
src/sfd/FreeSerif.sfd Normal file

File diff suppressed because it is too large Load Diff

127785
src/sfd/FreeSerifBold.sfd Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

96510
src/sfd/FreeSerifItalic.sfd Normal file

File diff suppressed because it is too large Load Diff

51
src/sfd/Makefile Normal file
View File

@ -0,0 +1,51 @@
# $Id: Makefile,v 1.8 2010-04-06 19:33:54 Stevan_White Exp $
SFDS=FreeMonoBoldOblique.sfd FreeMonoBold.sfd FreeMonoOblique.sfd FreeMono.sfd \
FreeSansBoldOblique.sfd FreeSansBold.sfd FreeSansOblique.sfd FreeSans.sfd \
FreeSerifBoldItalic.sfd FreeSerifBold.sfd FreeSerifItalic.sfd FreeSerif.sfd
MSFDS=FreeMonoBoldOblique.sfd FreeMonoBold.sfd FreeMonoOblique.sfd FreeMono.sfd
TTFS=$(SFDS:.sfd=.ttf)
OTFS=$(SFDS:.sfd=.otf)
WOFFS=$(SFDS:.sfd=.woff)
FF=fontforge -lang=ff -script
FFPY=fontforge -lang=py -script
FFPY=fontforge -lang=py -script
ffversion=`fontforge --version 2> /dev/null | grep '^fontforge' | sed -e 's/^fontforge //'`
TESTFF=if test -z ${ffversion}; then echo FontForge program is required to build FreeFont; exit 1; fi; if test `fontforge --version 2> /dev/null | grep '^fontforge' | sed -e 's/^fontforge //'` -lt 20080429 ; then echo FontForge version too old; exit 1; fi
.SUFFIXES: $(SUFFIXES) .sfd .ttf .otf .woff
%.otf : %.sfd
@ $(TESTFF)
@ ( $(FFPY) ../tools/generate/OpenType $< 3>&1 1>&2 2>&3 | tail -n +4 ) 3>&1 1>&2 2>&3 2>&1
%.ttf : %.sfd
@ $(TESTFF)
@ ( $(FFPY) ../tools/generate/TrueType $< 3>&1 1>&2 2>&3 | tail -n +4 ) 3>&1 1>&2 2>&3 2>&1
%.woff : %.sfd
@ $(TESTFF)
@ ( $(FFPY) ../tools/generate/WOFF $< 3>&1 1>&2 2>&3 | tail -n +4 ) 3>&1 1>&2 2>&3 2>&1
all: ttf otf woff
ttf: $(TTFS)
otf: $(OTFS)
woff: $(WOFFS)
tests:
@ $(TESTFF)
@ ( $(FFPY) ../tools/test/isMonoMono.py $(MSFDS) 3>&1 1>&2 2>&3 | tail -n +4 ) 3>&1 1>&2 2>&3 2>&1
@ $(FFPY) ../tools/test/checkGlyphNumbers.py `pwd` $(SFDS) 2>&1
@ $(FFPY) ../tools/test/validate.py 2>&1
clean:
rm -f $(TTFS) $(OTFS) $(WOFFS) build.log
distclean:
rm -f $(TTFS) $(OTFS) $(WOFFS) build.log

54
src/tools/generate/MacTT Executable file
View File

@ -0,0 +1,54 @@
# vim: set filetype=python :
__license__ = """
This file is part of Gnu FreeFont.
Gnu FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Gnu FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Gnu FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Stevan White"
__email__ = "stevan.white@googlemail.com"
__copyright__ = "Copyright 2009, 2010, 2012, Stevan White"
__date__ = "$Date: 2012-04-21 18:47:22 +0200 (Sat, 21 Apr 2012) $"
__version__ = "$Revision: 2231 $"
__doc__ = """
Convert fonts from FontForge's native SFD format to TrueType format
First auto-hints whole font
Old-style kern tables seem to be what is actually used by Windows and
some Linux programs such as OpenOffice.
According to the FAQ, need to pass Flags=(apple) to build Mac fonts.
But this option seems to rule out old-style kern tables
"""
import fontforge
from sys import argv
from buildutils import *
scriptname = argv[0];
argc = len( argv )
if argc > 1:
for i in range( 1, argc ):
f = fontforge.open( argv[i] )
ttfile = f.fontname + ".mac.ttf"
vstr = trim_version_str( f )
print "Generating Mac TrueType file ", ttfile, ' ', vstr
f.selection.all()
f.autoHint()
f.autoInstr()
# Mac OS Font Book doesn't like the old-kern flag
#f.generate( ttfile, flags=('opentype','old-kern') )
f.close()
else:
print "Usage: " + scriptname + " font.sfd [font.sfd ...]"

54
src/tools/generate/OpenType Executable file
View File

@ -0,0 +1,54 @@
# vim: set filetype=python :
__license__ = """
This file is part of Gnu FreeFont.
Gnu FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Gnu FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Gnu FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Stevan White"
__email__ = "stevan.white@googlemail.com"
__copyright__ = "Copyright 2009, 2010, 2012, Stevan White"
__date__ = "$Date: 2012-04-24 13:09:08 +0200 (Tue, 24 Apr 2012) $"
__version__ = "$Revision: 2245 $"
__doc__ = """
Convert fonts from FontForge's native SFD format to OpenType format
Issues: Currently, FontForge does not include gasp tables in OpenType fonts.
However, in Windows, that functionality is clearly present in other fonts.
The result, I think, is that hinting is applied to small font sizes when
it is inappropriate.
Therefore, hinting is presently turned off
"""
import fontforge
from sys import argv
from buildutils import *
scriptname = argv[0];
argc = len( argv )
if argc > 1:
for i in range( 1, argc ):
f = fontforge.open( argv[i] )
otfile = f.fontname + ".otf"
vstr = trim_version_str( f )
print "Generating OpenType file ", otfile, ' ', vstr
# Wanted to set to 'UniocdeBmp' if there were no high unicodes
# but all attemtps to determine that from Python failed.
f.encoding = 'UnicodeFull'
f.selection.all()
f.autoHint() # because without gasp table, small sizes ugly
f.generate( otfile, flags=('opentype','old-kern','round') )
f.close()
else:
print "Usage: " + scriptname + " font.sfd [font.sfd ...]"

57
src/tools/generate/TrueType Executable file
View File

@ -0,0 +1,57 @@
# vim: set filetype=python :
__license__ = """
This file is part of Gnu FreeFont.
Gnu FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Gnu FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Gnu FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Stevan White"
__email__ = "stevan.white@googlemail.com"
__copyright__ = "Copyright 2009, 2010, 2012, Stevan White"
__date__ = "$Date: 2012-04-21 18:47:22 +0200 (Sat, 21 Apr 2012) $"
__version__ = "$Revision: 2231 $"
__doc__ = """
Convert fonts from FontForge's native SFD format to TrueType format
First auto-hints whole font
Old-style kern tables seem to be what is actually used by Windows and
some Linux programs such as OpenOffice.
According to the FAQ, need to pass Flags=(apple) to build Mac fonts.
But this option seems to rule out old-style kern tables
"""
import fontforge
import sys
from buildutils import *
scriptname = sys.argv[0];
argc = len( sys.argv )
if argc > 1:
for i in range( 1, argc ):
f = fontforge.open( sys.argv[i] )
ttfile = f.fontname + ".ttf"
vstr = trim_version_str( f )
print "Generating TrueType file ", ttfile, ' ', vstr
# Wanted to set to 'UniocdeBmp' if there were no high unicodes
# but all attemtps to determine that from Python failed.
f.encoding = 'UnicodeFull'
f.layers['Fore'].is_quadratic = True
f.selection.all()
f.autoHint()
f.autoInstr()
f.generate( ttfile, flags=('opentype','old-kern','no-hints') )
f.close()
else:
print "Usage: " + scriptname + " font.sfd [font.sfd ...]"

174
src/tools/generate/WOFF Executable file
View File

@ -0,0 +1,174 @@
# vim: set filetype=python :
__license__ = """
This file is part of Gnu FreeFont.
Gnu FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Gnu FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Gnu FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Stevan White"
__email__ = "stevan.white@googlemail.com"
__copyright__ = "Copyright 2011, 2012, Stevan White"
__date__ = "$Date: 2011-11-03 01:50:14 +0100 (Thu, 03 Nov 2011) $"
__version__ = "$Revision: 1863 $"
__doc__ = """
Convert fonts from FontForge's native SFD format to Web Open Font Format (WOFF)
First auto-hints whole font
Mainly, this copies information out of the font's existing TT names strings,
and uses them to generate XML information for the WOFF metadata.
Then it just saves the file as *.woff.
The settings should otherwise be like those for generic OpenType fonts.
"""
import fontforge
import sys
import xml.dom.minidom
from buildutils import *
scriptname = sys.argv[0];
argc = len( sys.argv )
class SFNT_name:
def __init__( self, lang, string ):
self.lang = lang
self.string = string
def fontStrings2dict( font, lang_filter=None ):
sfnt_strings = {}
for n in font.sfnt_names:
if lang_filter:
if n[0].startswith( lang_filter ):
sfnt_strings[n[1]] = SFNT_name(n[0],n[2])
else:
sfnt_strings[n[1]] = SFNT_name(n[0],n[2])
return sfnt_strings
def stripmeta( meta ):
lst = meta.split( '\n' )
nlst = []
for line in lst[1:-2]:
if line.startswith( '\t' ):
line = line[1:]
nlst.append( line )
return '\n'.join( nlst )
def add_text_decorated_with_divs( doc, parent, text ):
for line in text.split( '\n' ):
if line:
div = doc.createElement( 'div' )
div.appendChild( doc.createTextNode( line ) )
parent.appendChild( div )
def fontInfo2WOFFxml( font ):
sfnt_strings = fontStrings2dict( f, 'English' )
copyright = sfnt_strings['Copyright'].string
license = sfnt_strings['License'].string
licenseURL = sfnt_strings['License URL'].string
vendorURL = sfnt_strings['Vendor URL'].string
version = sfnt_strings['Version'].string
fontFamily = sfnt_strings['Family'].string
fontStyle = sfnt_strings['SubFamily'].string
doc = xml.dom.minidom.Document()
meta = doc.createElement( 'metadata' )
doc.appendChild( meta )
# <uniqueid id="org.gnu.freefont.freeserif.1877" />
elt = doc.createElement( 'uniqueid' )
version_prefix = 'Revision: '
if version.startswith( version_prefix ):
revision = version[len(version_prefix):]
else:
revision = version
elt.setAttribute( 'id', 'org.gnu.freefont.' + fontFamily + '.'
+ fontStyle + '.' + revision )
meta.appendChild( elt )
# <vendor name="Font Vendor" url="https://savannah.gnu.org/projects/freefont/" />
elt = doc.createElement( 'vendor' )
elt.setAttribute( 'name', 'Font Vendor' )
elt.setAttribute( 'url', vendorURL )
meta.appendChild( elt )
# <credits>
# <credit name="Font Designer"
# url="https://savannah.gnu.org/projects/freefont/" />
# </credits>
elt_credits = doc.createElement( 'credits' )
elt = doc.createElement( 'credit' )
elt.setAttribute( 'name', 'Font Designer' )
elt.setAttribute( 'url', vendorURL )
elt_credits.appendChild( elt )
meta.appendChild( elt_credits )
#<description>
# <text xml:lang="en">
# FreeSerif-Medium is a member of the GNU FreeFont font family.
# </text>
#</description>
elt_description = doc.createElement( 'description' )
elt = doc.createElement( 'text' )
elt.setAttribute( 'xml:lang', 'en' )
text = doc.createTextNode( fontFamily + '-' + fontStyle
+ " is a member of the GNU FreeFont font family.")
elt.appendChild( text )
elt_description.appendChild( elt )
meta.appendChild( elt_description )
#<license url="http://www.gnu.org/copyleft/gpl.html"
# id="fontvendor-Web-corporate-v2">
# <text xml:lang="en">
# ...
elt_license = doc.createElement( 'license' )
elt_license.setAttribute( 'url', licenseURL )
elt = doc.createElement( 'text' )
elt.setAttribute( 'xml:lang', 'en' )
add_text_decorated_with_divs( doc, elt, license )
elt_license.appendChild( elt )
meta.appendChild( elt_license )
#<copyright>
#<text xml:lang="en">Copyright &#x0089;2002, 2003, 2005, 2008, 2009, 2010, 2011 GNU Freefont contributors.</text>
#</copyright>
elt_copyright = doc.createElement( 'copyright' )
elt = doc.createElement( 'text' )
elt.setAttribute( 'xml:lang', 'en' )
elt.appendChild( doc.createTextNode( copyright ) )
elt_copyright.appendChild( elt )
meta.appendChild( elt_copyright )
strrep = meta.toprettyxml()
return stripmeta( strrep )
if argc > 1:
for i in range( 1, argc ):
f = fontforge.open( sys.argv[i] )
woff_file = f.fontname + ".woff"
vstr = trim_version_str( f )
print "Generating WOFF file ", woff_file, ' ', vstr
# Wanted to set to 'UniocdeBmp' if there were no high unicodes
# but all attemtps to determine that from Python failed.
f.encoding = 'UnicodeFull'
f.layers['Fore'].is_quadratic = True
f.selection.all()
f.autoHint()
f.autoInstr()
# Copy copyright info etc from the tt tables into the
# WOFF XML section.
xml = fontInfo2WOFFxml( f )
f.woffMajor = 1
f.woffMajor = 0
f.woffMetadata = xml
#f.generate( woff_file, flags=('opentype','round') )
f.generate( woff_file, flags=('opentype','no-hints') )
f.close()
else:
print "Usage: " + scriptname + " font.sfd [font.sfd ...]"

View File

@ -0,0 +1,46 @@
__license__ = """
This file is part of Gnu FreeFont.
Gnu FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Gnu FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Gnu FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Stevan White"
__email__ = "stevan.white@googlemail.com"
__copyright__ = "Copyright 2011, 2012, Stevan White"
__date__ = "$Date: 2012-04-24 13:10:12 +0200 (Tue, 24 Apr 2012) $"
__version__ = "$Revision: 2246 $"
__doc__ = """
Common tools used by the generate scripts.
"""
import re
_re_vstr = re.compile( '\$Revision: (\d*)\s*\$(.*)' )
def trim_version_str( font ):
""" SVN automatically puts a revision number between dollar signs
in the sfd file's Version string.
However the OpenType standard recommends
Version n.m
Where n and m are decimal numbers.
"""
vstr_match = _re_vstr.match( font.version )
ot_stdized = ''
if vstr_match:
trimmed = vstr_match.group( 1 )
rest = vstr_match.group( 2 )
otstdized = '0412.' + trimmed + rest
font.version = otstdized
#font.appendSFNTName( n[0], n[1], otstdized )
return trimmed
return otstdized

Binary file not shown.

View File

@ -0,0 +1,7 @@
#!/bin/sh
# Needs George Williams' showttf
for FILE in Free*.ttf
do
printf "%-23s" $FILE
showttf $FILE | grep -a UnicodeRange
done

View File

@ -0,0 +1,567 @@
__license__ = """
This file is part of Gnu FreeFont.
Gnu FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Gnu FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Gnu FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Stevan White"
__email__ = "stevan.white@googlemail.com"
__copyright__ = "Copyright 2009, 2010, 2011, Stevan White"
__date__ = "$Date: 2012-04-22 13:43:44 +0200 (Sun, 22 Apr 2012) $"
__version__ = "$Revision: 2238 $"
__doc__ = """
Encodes the correspondence between Unicode code intervals
and the script support field 'ulUnicodeRange' of OpenType fonts.
A Unicode script range, such as Greek, is not an unbroken list of
characters, but rather several "intervals" of defined characters,
broken by undefined or reserved character slots.
OpenType contains an attempt to report whether a given font supports
a certain range of Unicode, e.g. Greek or Kanji. This was done using
a bit mask, with (roughly) one bit for each range.
This is complicated by:
1) some ranges overlap, or have other interactions
A) Greek and Coptic are not completely distinct
B) Accent ranges are often used by several scripts
C) FontForge has the occasional bug in its internal
notion of Unicode ranges
2) What is meant by "support"? Is it enough to have a single
glyph in a range, to say it is supported?
3) both Unicode and OpenType are in a state of flux
See
Roadmap tf the BMP
http://www.unicode.org/roadmaps/bmp/
The intervals are partly just the assigned interval, but often I have
listed the ranges that have characters assigned to them.
OpenType standard: OS/2 and Windows Metrics
http://www.microsoft.com/typography/otspec/os2.htm
Apple Developer: The TrueType Font File
http://developer.apple.com/fonts/TTRefMan/RM06/Chap6.html
Says 128 bits are split into 96 and 32 bits.
96 is Unicode block, 32 for script sets...
Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification
http://www.w3.org/TR/CSS2/
"""
class interval:
def __init__( self, begin, end ):
self.begin = begin
self.end = end
def len( self ):
return 1 + self.end - self.begin
def __str__( self ):
return '[' + str( self.begin ) + ',' + str( self.end ) + ']'
def contains( self, val ):
return val <= self.end and val >= self.begin
# NOTE the OpenType spec is much more thorough
ulUnicodeRange = [
[0, 'Basic Latin', [interval(0,1), # Nul character, mapped to notdef
# and .nul; required by TrueType
interval(0x0d, 0x0d), # non-marking return
interval(0x20, 0x7E)] ], # Latin range
[1, 'Latin-1 Supplement',[interval(0xA0, 0xFF)] ],
[2, 'Latin Extended-A', [interval(0x0100, 0x017F)] ],
[3, 'Latin Extended-B', [interval(0x0180, 0x024F)]],
[4, 'IPA and Phonetic Extensions', [interval(0x0250, 0x02AF),
interval(0x1D00, 0x1D7F), # Phonetic Extensions
interval(0x1D80, 0x1DBF) # Phonetic Extensions S.
]],
[5, 'Spacing Modifier Letters', [interval(0x02B0, 0x02FF),
interval(0xA700, 0xA71F) # Modifier Tone Letters
]],
[6, 'Combining Diacritical Marks (+suppl.)', [interval(0x0300, 0x036F),
interval(0x1DC0, 0x1DE6), # Supplement
interval(0x1DFC, 0x1DFF) # Supplement
] ],
[7, 'Greek and Coptic', [interval(0x0370, 0x0377),
interval(0x037A, 0x037E),
interval(0x0384, 0x038A),
interval(0x038C, 0x038C),
interval(0x038E, 0x03A1),
interval(0x03A3, 0x03FF)
] ],
[8, 'Coptic', [interval(0x2C80, 0x2CFF)]],
[9, 'Cyrillic (+suppl., +ext.-A, -B)', [
interval(0x0400, 0x04FF), # Cyrillic
interval(0x0500, 0x0527), # Cyrillic Supplement
interval(0x2DE0, 0x2DFF), # Cyrillic Extended-A
interval(0xA640, 0xA673), # Cyrillic Extended-B
interval(0xA67C, 0xA697)
]
],
[10, 'Armenian', [interval(0x0531, 0x0556),
interval(0x0559, 0x055F),
interval(0x0561, 0x0587),
interval(0x0589, 0x058A),
interval(0x058F, 0x058F)
]
],
[11, 'Hebrew', [
interval(0x0591, 0x05C7),
interval(0x05D0, 0x05EA),
interval(0x05F0, 0x05F4)
# See also Alphabetic Presentation Forms
]],
[12, 'Vai', [interval(0xA500, 0xA62B),
]],
[13, 'Arabic (+suppl.)', [interval(0x0600, 0x0603),
interval(0x0606, 0x061B),
interval(0x061E, 0x06FF),
interval(0x0750, 0x077F) # Supplement
]
],
[14, "N'Ko", [interval(0x07C0, 0x07FF)]],
[15, 'Devanagari (+ext.)', [ interval(0x0900, 0x0977),
interval(0x0979, 0x097F),
interval(0xA8E0, 0xA8FB) # Extended
]],
[16, 'Bengali', [interval(0x0981, 0x0983),
interval(0x0985, 0x098C),
interval(0x098F, 0x0990),
interval(0x0993, 0x09A8),
interval(0x09AA, 0x09B0),
interval(0x09B2, 0x09B2),
interval(0x09B6, 0x09B9),
interval(0x09BC, 0x09C4),
interval(0x09C7, 0x09C8),
interval(0x09CB, 0x09CE),
interval(0x09D7, 0x09D7),
interval(0x09DC, 0x09DD),
interval(0x09DF, 0x09E3),
interval(0x09E6, 0x09FB),
]],
[17, 'Gurmukhi', [interval(0x0A01, 0x0A03),
interval(0x0A05, 0x0A0A),
interval(0x0A0F, 0x0A10),
interval(0x0A13, 0x0A28),
interval(0x0A2A, 0x0A30),
interval(0x0A32, 0x0A33),
interval(0x0A35, 0x0A36),
interval(0x0A38, 0x0A39),
interval(0x0A3C, 0x0A3C),
interval(0x0A3E, 0x0A42),
interval(0x0A47, 0x0A48),
interval(0x0A4B, 0x0A4D),
interval(0x0A51, 0x0A51),
interval(0x0A59, 0x0A5C),
interval(0x0A5E, 0x0A5E),
interval(0x0A66, 0x0A75),
]],
[18, 'Gujarati', [interval(0x0A81, 0x0A83),
interval(0x0A85, 0x0A8D),
interval(0x0A8F, 0x0A91),
interval(0x0A93, 0x0AA8),
interval(0x0AAA, 0x0AB0),
interval(0x0AB2, 0x0AB3),
interval(0x0AB5, 0x0AB9),
interval(0x0ABC, 0x0AC5),
interval(0x0AC7, 0x0AC9),
interval(0x0ACB, 0x0ACD),
interval(0x0AD0, 0x0AD0),
interval(0x0AE0, 0x0AE3),
interval(0x0AE6, 0x0AEF),
interval(0x0AF0, 0x0AF1)
]],
[19, 'Oriya', [interval(0x0B01, 0x0B03),
interval(0x0B05, 0x0B0C),
interval(0x0B0F, 0x0B10),
interval(0x0B13, 0x0B28),
interval(0x0B2A, 0x0B30),
interval(0x0B32, 0x0B33),
interval(0x0B35, 0x0B39),
interval(0x0B3C, 0x0B44),
interval(0x0B47, 0x0B48),
interval(0x0B4B, 0x0B4D),
interval(0x0B56, 0x0B57),
interval(0x0B5C, 0x0B5D),
interval(0x0B5F, 0x0B63),
interval(0x0B66, 0x0B77),
]],
[20, 'Tamil', [interval(0x0B82, 0x0B83),
interval(0x0B85, 0x0B8A),
interval(0x0B8E, 0x0B90),
interval(0x0B92, 0x0B95),
interval(0x0B99, 0x0B9A),
interval(0x0B9C, 0x0B9C),
interval(0x0B9E, 0x0B9F),
interval(0x0BA3, 0x0BA4),
interval(0x0BA8, 0x0BAA),
interval(0x0BAE, 0x0BB9),
interval(0x0BBE, 0x0BC2),
interval(0x0BC6, 0x0BC8),
interval(0x0BCA, 0x0BCD),
interval(0x0BD0, 0x0BD0),
interval(0x0BD7, 0x0BD7),
interval(0x0BE6, 0x0BFA)
]],
[21, 'Telugu', [interval(0x0C01, 0x0C03),
interval(0x0C05, 0x0C0C),
interval(0x0C0E, 0x0C11),
interval(0x0C12, 0x0C28),
interval(0x0C2A, 0x0C33),
interval(0x0C35, 0x0C39),
interval(0x0C3d, 0x0C44),
interval(0x0C46, 0x0C48),
interval(0x0C4a, 0x0C4d),
interval(0x0C55, 0x0C56),
interval(0x0C58, 0x0C59),
interval(0x0C60, 0x0C63),
interval(0x0C66, 0x0C6f),
interval(0x0C78, 0x0C7f),
]
],
[22, 'Kannada', [interval(0x0C82, 0x0C83),
interval(0x0C85, 0x0C8C),
interval(0x0C8E, 0x0C90),
interval(0x0C92, 0x0CA8),
interval(0x0CAA, 0x0CB3),
interval(0x0CB5, 0x0CB9),
interval(0x0CBC, 0x0CC4),
interval(0x0CC6, 0x0CC8),
interval(0x0CCA, 0x0CCD),
interval(0x0CD5, 0x0CD6),
interval(0x0CDE, 0x0CDE),
interval(0x0CE0, 0x0CE3),
interval(0x0CE6, 0x0CEF),
interval(0x0CF1, 0x0CF2),
]],
[23, 'Malayalam', [interval(0x0D02, 0x0D03),
interval(0x0D05, 0x0D0C),
interval(0x0D0E, 0x0D10),
interval(0x0D12, 0x0D3A),
interval(0x0D3D, 0x0D44),
interval(0x0D46, 0x0D48),
interval(0x0D4A, 0x0D4E),
interval(0x0D57, 0x0D57),
interval(0x0D60, 0x0D63),
interval(0x0D66, 0x0D75),
interval(0x0D79, 0x0D7F),
]],
[24, 'Thai', [interval(0x0E01, 0x0E3A),
interval(0x0E3F, 0x0E5B)
]
],
[25, 'Lao', [interval(0x0E80, 0x0EFF)]],
[26, 'Georgian (+suppl.)', [
interval(0x10A0, 0x10C5),
interval(0x10D0, 0x10FC),
interval(0x2D00, 0x2D25) # Supplement
]],
[27, 'Balinese', [interval(0x1B00, 0x1B7F)]],
# 'Batak', [interval(0x1BC0, 0x1BFF)]],
[28, 'Hangul Jamo', [interval(0x1100, 0x11FF)]],
[29, 'Latin Extended (Additional,C,D)', [
interval(0x1E00, 0x1EFF), # Additional
interval(0x2C60, 0x2C7F), # C
interval(0xA720, 0xA78E), # D
interval(0xA790, 0xA793), # D
interval(0xA7A0, 0xA7AA), # D
interval(0xA7F8, 0xA7FF) # D
]],
[30, 'Greek Extended', [interval(0x1F00, 0x1F15),
interval(0x1F18, 0x1F1D),
interval(0x1F20, 0x1F45),
interval(0x1F48, 0x1F4D),
interval(0x1F50, 0x1F57),
interval(0x1F59, 0x1F59),
interval(0x1F5B, 0x1F5B),
interval(0x1F5D, 0x1F5D),
interval(0x1F5F, 0x1F7D),
interval(0x1F80, 0x1FB4),
interval(0x1FB6, 0x1FC4),
interval(0x1FC6, 0x1FD3),
interval(0x1FD6, 0x1FDB),
interval(0x1FDD, 0x1FEF),
interval(0x1FF2, 0x1FF4),
interval(0x1FF6, 0x1FFE)
]],
[31, 'General Punctuation (+suppl.)', [interval(0x2000, 0x2064),
# interval(0x206A, 0x206F), # deprecated
interval(0x2E00, 0x2E31), # Supplemental
]],
[32, 'Superscripts and Subscripts', [interval(0x2070, 0x2071),
interval(0x2074, 0x208E),
interval(0x2090, 0x2094)
]
],
[33, 'Currency Symbols', [interval(0x20A0, 0x20B9)]],
[34, 'Combining Diacritical Marks for Symbols', [interval(0x20D0, 0x20F0)]],
[35, 'Letterlike Symbols', [interval(0x2100, 0x214F)]],
[36, 'Number Forms', [interval(0x2150, 0x2189)]],
[37, 'Arrows (+suppl.)', [interval(0x2190, 0x21FF),
interval(0x27F0, 0x27FF), # Supplemental Arrows-A
interval(0x2900, 0x297F), # Supplemental Arrows-B
interval(0x2B00, 0x2B4C), # Miscellaneous Symbols and Arrows
interval(0x2B40, 0x2BF9) # "
]],
[38, 'Mathematical Operators', [
interval(0x2200, 0x22FF),
interval(0x2A00, 0x2AFF), # Supplemental Mathematical Operators
interval(0x27C0, 0x27CA), # Miscellaneous Mathematical Symbols-A
interval(0x27CC, 0x27CC),
interval(0x27CE, 0x27EF),
interval(0x2980, 0x29FF) # Miscellaneous Mathematical Symbols-B
]
],
[39, 'Miscellaneous Technical', [interval(0x2300, 0x23E7)]],
[40, 'Control Pictures', [interval(0x2400, 0x2426)]],
[41, 'Optical Character Recognition', [interval(0x2440, 0x244A)]],
[42, 'Enclosed Alphanumerics', [interval(0x2460, 0x24FF)]],
[43, 'Box Drawing', [interval(0x2500, 0x257F)]],
[44, 'Block Elements', [interval(0x2580, 0x259F)]],
[45, 'Geometric Shapes', [interval(0x25A0, 0x25FF)]],
[46, 'Miscellaneous Symbols', [
interval(0x2600, 0x26FF),
]
],
[47, 'Dingbats', [interval(0x2701, 0x27BF),
]],
[48, 'CJK Symbols and Punctuation', [interval(0x3000, 0x303F)]],
[49, 'Hiragana', [interval(0x3040, 0x309F)]],
[50, 'Katakana', [interval(0x30A0, 0x30FF)]],
[51, 'Bopomofo', [interval(0x3100, 0x312F)]],
[52, 'Hangul Compatibility Jamo', [interval(0x3130, 0x318F)]],
[53, 'Kanbun', [interval(0x3190, 0x319F)]], # was CJK Miscellaneous
[54, 'Enclosed CJK Letters and Months', [interval(0x3200, 0x32FF)]],
[55, 'CJK Compatibility', [interval(0x3300, 0x33FF)]],
# 'Lisu', [interval(0xA4D0, 0xA4FF)]],
[56, 'Hangul Syallables', [interval(0xAC00, 0xD7A3)]],
[57, 'Non-Plane 0', [interval(0xD800, 0xDFFF)]],
[58, 'Phoenician', [interval(0x10900, 0x1091B),
interval(0x1091F, 0x1091F)], True],
[59, 'CJK Unified Ideographs', [interval(0x4E00, 0x9FFF)]], #FIXME complex
# Meetai Mayek ABC0 ABFF
[60, 'Private Use Area', [interval(0xE000, 0xF8FF)]],
[61, 'CJK Compatibility Ideographs', [interval(0xF900, 0xFAFF)]],
[62, 'Alphabetic Presentation Forms', [
interval(0xFB00, 0xFB06),
interval(0xFB13, 0xFB17),
interval(0xFB1D, 0xFB36),
interval(0xFB38, 0xFB3C),
interval(0xFB3E, 0xFB3E),
interval(0xFB40, 0xFB41),
interval(0xFB43, 0xFB44),
interval(0xFB46, 0xFB4F),
]],
[63, 'Arabic Presentation Forms-A', [interval(0xFB50, 0xFBC1),
interval(0xFBD3, 0xFD3F),
interval(0xFD50, 0xFD8F),
interval(0xFD92, 0xFDC7),
interval(0xFDF0, 0xFDFD)
]
],
[64, 'Combining Half Marks', [interval(0xFE20, 0xFE26)]],
[65, 'CJK Compatibility Forms', [interval(0xFE10, 0xFE1F), # Vertical forms
interval(0xFE30, 0xFE4F) # Compatability forms
]],
[66, 'Small Form Variants', [interval(0xFE50, 0xFE52),
interval(0xFE54, 0xFE66),
interval(0xFE68, 0xFE6B)
]
],
[67, 'Arabic Presentation Forms-B', [interval(0xFE70, 0xFE74),
interval(0xFE76, 0xFEFC),
interval(0xFEFF, 0xFEFF)
]
],
[68, 'Halfwidth and Fullwidth Forms', [interval(0xFF00, 0xFFEF)]],
[69, 'Specials', [interval(0xFFF9, 0xFFFD)]],
[70, 'Tibetan', [interval(0x0F00, 0x0FFF)]],
[71, 'Syriac', [interval(0x0700, 0x070D),
interval(0x070F, 0x074A),
interval(0x074D, 0x074F)
]],
[72, 'Thaana', [interval(0x0780, 0x07B1)]],
[73, 'Sinhala', [interval(0x0D82, 0x0D83),
interval(0x0D85, 0x0D96),
interval(0x0D9A, 0x0DB1),
interval(0x0DB3, 0x0DBB),
interval(0x0DBD, 0x0DBD),
interval(0x0DC0, 0x0DC6),
interval(0x0DCA, 0x0DCA),
interval(0x0DCF, 0x0DD4),
interval(0x0DD6, 0x0DD6),
interval(0x0DD8, 0x0DDF),
interval(0x0DF2, 0x0DF4)]],
[74, 'Myanmar', [interval(0x1000, 0x109F)]],
[75, 'Ethiopic (+suppl., +ext.)', [
interval(0x1200, 0x1248),
interval(0x124A, 0x124D),
interval(0x1250, 0x1256),
interval(0x1258, 0x1258),
interval(0x125A, 0x125D),
interval(0x1260, 0x1288),
interval(0x128A, 0x128D),
interval(0x1290, 0x12B0),
interval(0x12B2, 0x12B5),
interval(0x12B8, 0x12BE),
interval(0x12C0, 0x12C0), # page 2
interval(0x12C2, 0x12C5),
interval(0x12C8, 0x12D6),
interval(0x12D8, 0x1310),
interval(0x1312, 0x1315),
interval(0x1318, 0x135A),
interval(0x135F, 0x137C),
interval(0x1380, 0x139F), # supplement
interval(0x2D80, 0x2DDF) # extended
]
],
[76, 'Cherokee', [interval(0x13A0, 0x13F4)]],
[77, 'Unified Canadian Aboriginal Syllabics',
[interval(0x1400, 0x167F),
interval(0x18B0, 0x18F5) # UCAS Extended
]
],
[78, 'Ogham', [interval(0x1680, 0x169F)]],
[79, 'Runic', [interval(0x16A0, 0x16F0)]],
[80, 'Khmer (+symbols)', [interval(0x1780, 0x17FF),
interval(0x19E0, 0x19FF) # symbols
]],
[81, 'Mongolian', [interval(0x1800, 0x18AF)]], #FIXME ranges
[82, 'Braille Patterns', [interval(0x2800, 0x28FF)]],
[83, 'Yi Syllables, Radicals', [interval(0xA000, 0xA0EF),
interval(0xA490, 0xA4CF)]
],
[84, 'Tagalog Hanunoo Buhid Tagbanwa',
[interval(0x1700, 0x1714),
interval(0x1720, 0x1736),
interval(0x1740, 0x1753),
interval(0x1750, 0x1773)
]
],
[85, 'Old Italic', [interval(0x10300, 0x1031E),
interval(0x10320, 0x10323)
], True],
[86, 'Gothic', [interval(0x10330, 0x1034A)], True],
[87, 'Deseret', [interval(0x10400, 0x1044F)], True],
#'Karoshthi', [interval(0x10A00, 0x10A5F)], True],
#'Kaithi', [interval(0x11080, 0x110C1)], True],
#'Sora Sompeng', [interval(0x110D0, 0x110F0)], True],
#'Chakma', [interval(0x11100, 0x1114F)], True],
#'Sharada', [interval(0x11180, 0x111DF)], True],
#'Takri', [interval(0x11680, 0x116CF)], True],
#'Miao', [interval(0x16F00, 0x16F9F)], True],
[88, 'Byzantine &amp; Western Musical Symbols', [interval(0x1D000, 0x1D0F5),
interval(0x1D100, 0x1D126),
interval(0x1D129, 0x1D1DD)
], True],
[89, 'Mathematical Alphanumeric Symbols', [interval(0x1D400, 0x1D454),
interval(0x1D456, 0x1D49C),
interval(0x1D49E, 0x1D49F),
interval(0x1D4A2, 0x1D4A2),
interval(0x1D4A5, 0x1D4A6),
interval(0x1D4A9, 0x1D4AC),
interval(0x1D4AE, 0x1D4B9),
interval(0x1D4BB, 0x1D4BB),
interval(0x1D4BD, 0x1D4C3),
interval(0x1D4C5, 0x1D4FF),
interval(0x1D500, 0x1D505), # page 2
interval(0x1D507, 0x1D50A),
interval(0x1D50D, 0x1D514),
interval(0x1D516, 0x1D51C),
interval(0x1D51E, 0x1D539),
interval(0x1D53B, 0x1D53E),
interval(0x1D540, 0x1D544),
interval(0x1D546, 0x1D546),
interval(0x1D54A, 0x1D550),
interval(0x1D552, 0x1D5FF),
interval(0x1D600, 0x1D6A5), # page 3
interval(0x1D6A8, 0x1D6FF),
interval(0x1D700, 0x1D7CB), # page 4
interval(0x1D7CE, 0x1D7FF),
], True],
[90, 'Private Use (plane 15,16)', [
interval(0xFF000, 0xFFFFD), # plane 15
interval(0x100000, 0x10FFFD) # plane 16
], True],
[91, 'Variation Selectors (+suppl.)', [interval(0xFE00, 0xFE0F),
interval(0xE0100, 0xE01EF) # supplement
], True],
[92, 'Tags', [interval(0xE0000, 0xE01EF)], True],
[93, 'Limbu', [interval(0x1900, 0x194F)]],
[94, 'Tai Le', [interval(0x1950, 0x196D),
interval(0x1970, 0x1974)
]],
[95, 'New Tai Lue', [interval(0x1980, 0x19DF)]],
[96, 'Buginese', [interval(0x1A00, 0x1A1B),
interval(0x1A1E, 0x1A1F)]],
[97, 'Glagolitic', [ interval(0x2C00, 0x2C2E),
interval(0x2C30, 0x2C5E) ]],
[98, 'Tifinagh', [interval(0x2D30, 0x2D67),
interval(0x2D6F, 0x2D6F)
]],
[99, 'Yijing Hexagram Symbols', [interval(0x4DC0, 0x4DFF)]],
[100, 'Syloti Nagri', [interval(0xA800, 0xA82F)]],
[101, 'Linear B Syllabary etc', [interval(0x10000, 0x1013F)], True],
[102, 'Ancient Greek Numbers', [interval(0x10140, 0x1018F)], True],
[103, 'Ugaritic', [interval(0x10380, 0x1039D),
interval(0x1039F, 0x1039F)
], True],
[104, 'Old Persian', [interval(0x103A0, 0x103C3),
interval(0x103C8, 0x103D6),
], True],
[105, 'Shavian', [interval(0x10450, 0x1047F)], True],
[106, 'Osmanya', [interval(0x10480, 0x104AF)], True],
[107, 'Cypriot Syllabary', [interval(0x10800, 0x1083F)], True],
[108, 'Kharoshthi', [interval(0x10A00, 0x10A5F)], True],
[109, 'Tai Xuan Jing Symbols', [interval(0x1D300, 0x1D35F)], True],
[110, 'Cuneiform (+numbers)', [interval(0x12000, 0x1247F)], True],
[111, 'Counting Rod Numerals', [interval(0x1D360, 0x1D37F)], True],
[112, 'Sundanese', [interval(0x1B80, 0x1BAA),
interval(0x1BAE, 0x1BB9)
]],
[113, 'Lepcha', [interval(0x1C00, 0x1C4F)]], # FIXME
[114, 'Ol Chiki', [interval(0x1C50, 0x1C7F)]],
[115, 'Saurashtra', [interval(0xA880, 0xA8C4),
interval(0xA8CE, 0xA8D9)
]],
[116, 'Kayah Li', [interval(0xA900, 0xA92F)]],
[117, 'Rejang', [interval(0xA930, 0xA953),
interval(0xA95F, 0xA95F)
]],
[118, 'Cham', [interval(0xAA00, 0xAA5F)]], #FIXME more complex
[119, 'Ancient Symbols', [interval(0x10190, 0x101CF)], True],
[120, 'Phaistos Disc', [interval(0x101D0, 0x101FF)], True],
[121, 'Carian, Lycian, Lydian', [interval(0x102A0, 0x102D0), #Carian
interval(0x10280, 0x1029C), # Lycian
interval(0x10920, 0x10939), # Lydian
interval(0x1093F, 0x1093F)
], True],
[122, 'Domino and Mahjong Tiles', [
interval(0x1F000, 0x1F02B), # Mahjong
interval(0x1F030, 0x1F093) # Domino
], True],
#[123-127, 'Reserved for process-internal usage', []]
]
def codepointIsInSomeRange( encoding ):
for ulr in ulUnicodeRange:
ranges = ulr[2]
for r in ranges:
if r.contains( encoding ):
return True
return False

View File

169
src/tools/report/kernclasses.py Executable file
View File

@ -0,0 +1,169 @@
#!/usr/bin/fontforge -script
__author__ = "Stevan White <stevan.white@googlemail.com>"
import fontforge
import sys
from OpenType.UnicodeRanges import *
def get_kern_subtables( font ):
try:
tables = []
for lookup in font.gpos_lookups:
if font.getLookupInfo( lookup )[0] == 'gpos_pair':
sts = font.getLookupSubtables( lookup )
for st in sts:
if font.isKerningClass( st ):
tables.append( st )
return tables
except EnvironmentError, ( e ):
print >> sys.stderr, 'EnvironmentError ' + str( e )
except TypeError, ( t ):
print >> sys.stderr, 'TypeError ' + str( t )
return None
preamble = """
<html>
<head>
<style type="text/css">
.nonexistent { background-color: red; }
td { text-align: right; font-family: inherit; }
.I td { font-style: italic; }
.B td { font-weight: bold; }
.BI td { font-weight: bold; font-style: italic; }
td { line-height: 1; }
.classes td { text-align: left; vertical-align: top; }
td span { font-weight: normal; font-style: normal; font-size: smaller; color: lime; }
td span.pos { color: magenta; }
td.zero { color: gray; }
</style>
</head>
<body>
"""
postamble="""
</body>
</html>
"""
def print_kerns( fontPath ):
font = fontforge.open( fontPath )
print '<h2>Kerning classes in ' + font.fontname + '</h2>'
weight = ''
if font.os2_weight > 500:
weight = 'B'
style = ''
if font.italicangle < 0.0:
style = 'I'
print '<div style="font-family: ' + font.familyname + '" ' \
+ 'class="' + weight + style + '">'
subtables = get_kern_subtables( font )
for st in subtables:
print '<h3>Subtable ' + st + '</h3>'
printKernsOfSubtable( font, st )
print '</div>'
sys.stdout.flush()
def printKernsOfSubtable( font, subtable ):
kclass = font.getKerningClass( subtable )
n = 0
leftclasses = kclass[0]
rightclasses = kclass[1]
kerns = kclass[2]
nr = len( rightclasses )
print '<table class="classes"><tr>'
print '<th>left classes: </th>'
print '<th>right classes: </th>'
print '<tr><td>'
for lc in leftclasses:
if lc:
for c in lc:
printentity( font, c )
print "<br />"
print "</td>"
print "<td>"
for rc in rightclasses:
if rc:
for c in rc:
printentity( font, c )
print "<br />"
print "</td>"
print "</tr>"
print "</table>"
print "<table>"
print "<tr>"
print "<th></th>"
for rc in rightclasses:
if rc:
sys.stdout.write( "<th>" )
printentity( font, rc[0] )
sys.stdout.write( "</th>" )
print "</tr>"
for lc in leftclasses:
m = 0
if lc:
print "<tr>"
sys.stdout.write( "<th>" )
printentity( font, lc[0] )
sys.stdout.write( "</th>" )
for rc in rightclasses:
kern = kerns[ n * nr + m ]
if rc:
ccolor = ''
ncolor = ''
if kern > 0:
ncolor = ' class="pos"'
if kern == 0:
ccolor = ' class="zero"'
sys.stdout.write( '<td' + ccolor + '><span' + ncolor + '>' )
if kern == 0:
sys.stdout.write( '&nbsp;' )
else:
sys.stdout.write( str( kern ) )
sys.stdout.write( '</span><br />' )
printpair( font, lc[0], rc[0] )
sys.stdout.write( '</td>' )
m += 1
print "</tr>"
n += 1
print "</table>"
def printentity( font, a ):
s = font.findEncodingSlot( a )
v = formatted_hex_value( s )
if s == -1:
v = '<span class="nonexistent">&nbsp;</span>'
print >> sys.stderr, font.fullname, 'Missing glyph: ' + a
elif not codepointIsInSomeRange( s ):
print >> sys.stderr, font.fullname, 'Non-unicode: ' + v
sys.stdout.write( v )
def printpair( font, p, q ):
printentity( font, p )
printentity( font, q )
sys.stdout.write( ' ' )
def formatted_hex_value( n ):
return '%s%0.4x%s' %( "&#x", n, ";" )
def printlist( lst ):
s = ''
delim = ''
for m in lst:
s += delim + m
delim = ' '
print s
print preamble
#print_kerns( '/home/swhite/font_stuff/urwsr-ttf/URWPalladioL-Roman-test.sfd' )
print_kerns( '../../sfd/FreeSerif.sfd' )
print_kerns( '../../sfd/FreeSerifItalic.sfd' )
print_kerns( '../../sfd/FreeSerifBold.sfd' )
print_kerns( '../../sfd/FreeSerifBoldItalic.sfd' )
print_kerns( '../../sfd/FreeSans.sfd' )
print_kerns( '../../sfd/FreeSansOblique.sfd' )
print_kerns( '../../sfd/FreeSansBold.sfd' )
print_kerns( '../../sfd/FreeSansBoldOblique.sfd' )
print_kerns( '../../sfd/FreeMono.sfd' )
print_kerns( '../../sfd/FreeMonoOblique.sfd' )
print_kerns( '../../sfd/FreeMonoBold.sfd' )
print_kerns( '../../sfd/FreeMonoBoldOblique.sfd' )
print postamble

View File

@ -0,0 +1,276 @@
#!/usr/bin/env ../utility/fontforge-interp.sh
__license__ = """
This file is part of Gnu FreeFont.
Gnu FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Gnu FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Gnu FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Stevan White"
__email__ = "stevan.white@googlemail.com"
__copyright__ = "Copyright 2009, 2010, 2012 Stevan White"
__date__ = "$Date: 2012-03-28 21:24:32 +0200 (Wed, 28 Mar 2012) $"
__version__ = "$Revision: 2184 $"
__doc__ = """
ligaturelookups
fontforge -script ligature.ookups font_file_path...
Output is HTML showing all the ligature lookups in the font.
To display the ligature, the HTML entities for the component Unicode charaters
are printed together. Then to show the components sparately they, are printed
with intervening spaces.
Most web browsers do not display any character unless it is Unicode.
It may replace a sequence of Unicode characters by a ligature, however.
Some of the ligatures in Indic ranges expand to (are made of) non-Unicode
characters, which themselves are ligatures. Ultimately, they all should
resolve to Unicode characters, although there isn't any real limit to how many
steps it may take.
The resulting string of Unicode characters can then be put into HTML, which
should be properly rendered by a browser.
"""
__usage = """Usage:
fontforge -script ligaturelookups.py font-path-1 font-path-2 ...
"""
import fontforge
from sys import stdout, stderr, argv, exit
def get_ligature_lookups( font ):
try:
tables = []
for lookup in font.gsub_lookups:
if font.getLookupInfo( lookup )[0] == 'gsub_ligature':
sts = font.getLookupSubtables( lookup )
for st in sts:
tables.append( st )
return tables
except EnvironmentError, ( e ):
print >> stderr, 'EnvironmentError ' + str( e )
except TypeError, ( t ):
print >> stderr, 'TypeError ' + str( t )
return None
_preamble= """<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Ligatures</title>
<style type="text/css">
.nonchar { background-color: red; }
table, tr, td { font-family: inherit; }
table, tr, td { font-style: inherit; }
table, tr, td { font-weight: inherit; }
td { text-align: right; }
td { line-height: 1; }
.ligatures td { width: 2em; }
.ligatures th { text-align: left; font-family: freemono, monospace; }
</style>
</head>
<body>
"""
_postamble="""
</body>
</html>
"""
_style_div_html = """<div style="font-family: '%s';%s%s">"""
_lig_header_html = '<h2>Ligatures in %s</h2>'
def print_ligatures( fontPath ):
subtables = []
font = fontforge.open( fontPath )
style = ''
if font.italicangle != 0.0:
style = "font-style: italic; "
weight = ''
if font.weight == 'Bold':
weight = "font-weight: bold; "
print _style_div_html % ( font.familyname, style, weight )
print _lig_header_html % ( font.fontname )
subtable_names = get_ligature_lookups( font )
for subtable_name in subtable_names:
subtables.append( makeLigatureSubtable( font, subtable_name ) )
for subtable in subtables:
out = htmlListOfLigSubtable( font, subtable, subtables )
stdout.writelines( out )
stdout.flush()
print '</div>'
class Ligature:
def __init__( self, glyph ):
self.glyph = glyph
self.parts = []
def setParts( self, parts ):
self.parts = parts
def append( self, part ):
self.parts.append( part )
class LigatureSubtable:
def __init__( self, tablename, name ):
self.tablename = tablename
self.name = name
self.ligatures = []
def append( self, ligature ):
self.ligatures.append( ligature )
def findLigatureGlyph( self, g ):
for p in self.ligatures:
if g == p.glyph.encoding:
return p
return False
def findLigatureGlyph( g, subtables ):
for s in subtables:
lig = s.findLigatureGlyph( g )
if lig:
return lig
return False
def makeLigatureSubtable( font, subtable_name ):
"""
From FontForge Python scripting doc
glyph.getPosSub( lookup-subtable-name )
Returns any positioning/substitution data attached to the glyph
controlled by the lookup-subtable. If the name is "*" then returns
data from all subtables.
The data are returned as a tuple of tuples.
The first element of the subtuples is the name of the lookup-subtable.
The second element will be one of the strings:
"Position", "Pair", "Substitution", "AltSubs", "MultSubs","Ligature".
...
Ligature data will be followed by several strings each containing
the name of a ligature component glyph.
BUT...
this info is attached to glyphs...
which glyph is it attached to? ones in the range, or the ligatures?
how to get the glyphs in the range referred to by the lookup??
Evidently, the library has stuff arranged internally to do the search
efficiently in the backwards direction, from glyph to subtable.
font.getLookupInfo gets a feature-script-lang-tuple, which in principle
should be able to resolve a glyph list... but can't see how to use it...
"""
subtable = LigatureSubtable( "", subtable_name )
for g in font.glyphs():
ligs = g.getPosSub( subtable_name )
if ligs:
ligature = Ligature( g )
for lr in ligs:
if len( lr ) < 3 or lr[1] != 'Ligature':
print >> stderr, font.fullname, '- non-ligature: ', g.glyphname
break
i = 2
while i < len( lr ):
ligature.append( lr[i] )
i += 1
subtable.append( ligature )
return subtable
_table_head_html = '''<table class="ligatures" rules="groups">
<caption>%s</caption>
<colgroup>
<col style="width: 50ex" />
</colgroup>
<colgroup>
<col style="width: 4ex" />
</colgroup>
'''
def htmlListOfLigSubtable( font, subtable, subtables ):
out = [ _table_head_html % ( subtable.name ) ]
for lig in subtable.ligatures:
out += [ '<tr>\n<th>' ]
# FIXME this will fail for high Unicode
if lig.glyph.unicode > -1:
s = font.findEncodingSlot( lig.glyph.unicode )
out += [ '%s%0.4x%s' %( "U+", s, " " ) ]
else:
out += [ '%s%0.4x%s' %( "#", lig.glyph.encoding, " " ) ]
out += [ lig.glyph.glyphname ]
out += [ '</th>' ]
out += [ '<td>' ]
for p in lig.parts:
out += [ nestedEntity( font, subtable, p, subtables ) ]
out += [ '</td>' ]
for p in lig.parts:
out += [ '<td>' ]
out += [ nestedEntity( font, subtable, p, subtables ) ]
out += [ '</td>' ]
out += [ '</tr>\n' ]
out += [ "</table>" ]
return out
def nestedEntity( font, subtable, a, subtables ):
"""
Expands each ligature, then checks each component to see if it's
Unicode.
If not, it looks through all the ligature tables to expand it,
and so on recursively until only Unicode characters remain.
"""
s = font.findEncodingSlot( a )
if s >= 0xe000 and s <= 0xf8ff: # Unicode only
lig = findLigatureGlyph( s, subtables )
if lig:
#print >> stderr, 'Nested glyph found: ' + a
for p in lig.parts:
return nestedEntity( font, subtable, p, subtables )
else:
print >> stderr, font.fullname, '- No nested glyph: ', a
return '<span class="nonchar">&nbsp;</span>'
else:
return entityHTML( font, a )
def entityHTML( font, a ):
s = font.findEncodingSlot( a )
if s == -1:
print >> stderr, font.fullname, '- Missing glyph: ', a
return '<span class="nonchar">&nbsp;</span>'
else:
return formatted_hex_value( s )
def formatted_hex_value( n ):
return '%s%0.4x%s' %( "&#x", n, ";" )
# --------------------------------------------------------------------------
args = argv[1:]
if len( args ) < 1 or len( args[0].strip() ) == 0:
print >> stderr, __usage
exit( 0 )
print _preamble
for font_name in args:
print_ligatures( font_name )
print _postamble

92
src/tools/report/private_use.py Executable file
View File

@ -0,0 +1,92 @@
#!/usr/bin/env ../utility/fontforge-interp.sh
__doc__ = """
private_use.py
fontforge -script private_use.py font_file_path...
Output is HTML showing all the font's glyphs that are in Unicode "Private Use"
areas.
Also reports whether glyphs have references, or if they are ligatures.
"""
__author__ = "Stevan White <stevan.white@googlemail.com>"
__date__ = "Dec 2009"
__version__ = "$Revision: 1.2 $"
import fontforge
import sys
preamble = """<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Private Use area</title>
<style type="text/css">
.nonchar { background-color: red; }
table, tr, td { font-family: inherit; }
table, tr, td { font-style: inherit; }
table, tr, td { font-weight: inherit; }
td { text-align: right; }
td { line-height: 1; }
.ligatures td { width: 2em; }
.ligatures th { text-align: left; font-family: freemono, monospace; }
</style>
</head>
<body>
"""
def makePreamble():
return preamble
postamble="""
</body>
</html>
"""
def print_private( fontPath ):
font = fontforge.open( fontPath )
print '<div style="font-family: \'' + font.familyname + '\'; ' \
'\">'
print '<h2>Private Use Area in ' + font.fontname + '</h2>'
font.selection.select(("ranges",None),0xe000,0xf8ff)
print '<table>'
for g in font.selection.byGlyphs:
print '<tr><td>'
print '%s%0.4x%s' %( "0x", g.encoding, "" )
print '</td><td>'
print '' + g.glyphname
print '</td><td>'
if g.getPosSub( '*' ):
print "is ligature"
if g.references:
print "has references"
print '</td><td>'
print '</td></tr>'
print '</table>'
print '</div>'
sys.stdout.flush()
def printentity( font, s ):
if s == -1:
print >> sys.stderr, 'Missing glyph: ' + a
sys.stdout.write( '<span class="nonchar">&nbsp;</span>' )
else:
sys.stdout.write( formatted_hex_value( s ) )
def formatted_hex_value( n ):
return '%s%0.4x%s' %( "&#x", n, ";" )
args = sys.argv[1:]
if len( args ) < 1 or len( args[0].strip() ) == 0:
sys.exit( 0 )
print makePreamble()
for font_name in args:
print_private( font_name )
print postamble

323
src/tools/report/range_report.py Executable file
View File

@ -0,0 +1,323 @@
#!/usr/bin/env ../utility/fontforge-interp.sh
__license__ = """
This file is part of Gnu FreeFont.
Gnu FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Gnu FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Gnu FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Stevan White"
__email__ = "stevan.white@googlemail.com"
__copyright__ = "Copyright 2009, 2010, 2011, Stevan White"
__date__ = "$Date: 2010-09-14 13:02:02 $"
__version__ = "$Revision: 1.9 $"
__doc__ = """
Makes an HTML table showing how many glyphs are in each range in each font,
and tries to collate that with the OS/2 character range support bit flags.
Runs under FontForge.
fontforge -script ranges.py
This is a hack--in no way authoritative.
Lots of guesswork; much is wrong; the coding is gross.
See
http://www.w3.org/TR/REC-CSS2/notes.html
http://shlimazl.nm.ru/eng/fonts_ttf.htm
http://www.evertype.com/standards/iso10646/ucs-collections.html
The intervals are partly just the assigned interval, but often I have
listed the ranges that have characters assigned to them.
"""
import fontforge
from sys import stderr
from time import tzset, strftime
from OpenType.UnicodeRanges import *
def total_intervals( intervals ):
num = 0
for i in intervals:
num += i.len()
return num
def count_glyphs_in_intervals( font, intervals ):
num = 0
for r in intervals:
if r.begin < len( font ) and r.end < len( font ):
# select() will throw up if try to select value
# beyond the range of the encoding
try:
font.selection.select( ( 'ranges', None ),
r.begin, r.end )
g = font.selection.byGlyphs
for e in g:
num += 1
except ValueError:
print >> stderr, "interval " + str( r ) \
+ " not representable in " + font.fontname
exit( 1 )
return num
special_TT_points = ( 0x00, 0x01, 0x0D )
def codepointIsSpecialTT( encoding ):
""" See Recommendations for OpenType Fonts
http://www.microsoft.com/typography/otspec/recom.htm """
return encoding in special_TT_points
class SupportInfo:
def __init__( self, os2bit, supports, total ):
self.os2bit = os2bit
self.supports = supports
self.total = total
class FontSupport:
""" A record of support for all OS/2 ranges within a single font.
Uses a dictionary internally, to avoid loss of the index info.
"""
def __init__( self, fontPath, short ):
font = fontforge.open( fontPath )
self.name = font.fontname
self.short = short
self.myInfos = {}
self.totalGlyphs = 0
self.fontTotalGlyphs = 0
self.privateUseGlyphs = 0
r = font.os2_unicoderanges
# print >> stderr, font.fontname, hex( r[0] ), hex( r[1] ),hex( r[2] ),hex( r[3] );
nRanges = len( ulUnicodeRange )
for index in range( 0, nRanges ):
byte = index / 32
bit = index % 32
self.collectRangeInfo( font, r[byte], bit, index )
for g in font.glyphs():
self.fontTotalGlyphs += 1
cp = g.encoding
if ( not codepointIsInSomeRange( cp )
and not codepointIsSpecialTT( cp ) ):
print >> stderr, font.fontname, \
"no range for", hex( cp )
""" '''Would like to check that special TT slots are
present, but don't know how...'''
for cp in special_TT_points:
font.selection.all()
if not cp in font.selection.byGlyphs:
print >> stderr, font.fontname, \
"special TT glyph missing", hex( cp )
"""
def collectRangeInfo( self, font, os2supportbyte, bit, index ):
supports = ( os2supportbyte & (1 << bit) ) != 0
rangeName = ulUnicodeRange[index][1]
intervals = ulUnicodeRange[index][2]
nglyphs = count_glyphs_in_intervals( font, intervals )
self.setRangeSupport( index, supports, nglyphs )
self.totalGlyphs += nglyphs
if index == 60 or index == 90:
self.privateUseGlyphs += nglyphs
def setRangeSupport( self, idx, supports, total ):
if self.myInfos.has_key( idx ):
print >> stderr, "OS/2 index ", idx, " duplicated"
exit( 1 )
self.myInfos[idx] = SupportInfo( idx, supports, total )
def getInfo( self, idx ):
if not self.myInfos.has_key( idx ):
print >> stderr, "OS/2 index ", idx, " not found"
exit( 1 )
return self.myInfos[ idx ]
table_head = '''
<table class="fontrangereport" cellspacing="0" cellpadding="0" frame="box" rules="all">
<caption>
OS/2 character ranges vs. font faces
</caption>
<colgroup>
<col /><col /><col />
</colgroup>
<colgroup>
<col class="roman"/><col /><col /><col />
<col /><col /><col /><col />
</colgroup>
<colgroup>
<col class="roman"/><col /><col /><col />
<col /><col /><col /><col />
</colgroup>
<colgroup>
<col class="roman"/><col /><col /><col />
<col /><col /><col /><col />
</colgroup>
<thead>
<tr><th>OS/2 character range</th>
<th>range<br />total</th>
<td></td>
%s
</tr>
</thead>'''
def print_font_range_table( fontSupportList ):
headings = ''
for fsl in fontSupportList:
headings += '<th colspan="2">' + fsl.short + '</th>'
print table_head % ( headings )
for r in ulUnicodeRange:
idx = r[0]
range_name = r[1]
intervals = r[2]
rowclass = ' class="low"'
if len( ulUnicodeRange[idx] ) > 3 and ulUnicodeRange[ idx ][3]:
rowclass = ' class="high"'
if idx == 60 or idx == 90:
rowclass = ' class="private"'
print '<tr%s><td>%s</td>' % ( rowclass, range_name )
print '<td class="num">%i</td>' % (
total_intervals( intervals ) )
print '<td></td>'
for fsl in fontSupportList:
supportInfo = fsl.getInfo( idx )
supportString = ''
if supportInfo.supports:
supportString = '&bull;'
totalStr = '&nbsp;'
if supportInfo.total:
totalStr = str( supportInfo.total )
print '<td class="num">%s</td><td>%s</td>' % (
totalStr, supportString )
print '</tr>'
print '<tr><th colspan="3">total in Unicode ranges</th>'
for fsl in fontSupportList:
print '<td class="num" colspan="2">%i&nbsp;</td>' % (
fsl.totalGlyphs )
print '</tr>'
print '<tr><th colspan="3">total in font</th>'
for fsl in fontSupportList:
print '<td class="num" colspan="2">%i&nbsp;</td>' % (
fsl.fontTotalGlyphs )
print '</tr>'
print '<tr><th colspan="3">total in Private Use</th>'
for fsl in fontSupportList:
print '<td class="num" colspan="2">%i&nbsp;</td>' % (
fsl.privateUseGlyphs )
print '</tr>'
# Would also like to total glyphs in ranges for each font,
# and also print total glyphs in each font.
print '</table>'
table_introduction = """
For historical reasons, TrueType classifies Unicode ranges according to
an extension of the old OS/2 character ranges. This table shows how many
characters FontForge finds in each of the ranges for each face in the family.
"""
table_explanation = """
<p>
Ranges for which (FontForge reports that) the font's OS/2 support
bit is set are marked with a bullet.
</p>
<p>
For many ranges, I took the liberty of reducing the set of characters
considered to those listed for the range in the current Unicode charts.
The number of characters supported can thus be less than the width of the range.
</p>
<p>
The totals include glyphs in the Private Use areas (where there
are many ligatures, alternative forms, and glyph components). The glyphs
in these areas do not correspond to Unicode characters.
</p>
<p>
Three control characters are inserted at 0x00, 0x01 and 0x0d to satisfy the
TrueType recommendations. These are counted under Basic Latin, but other
control characters there are not counted.
</p>
<p>
Note that there is a discrepancy in the Greek Symbols, Hebrew Extended and
Arabic Extended ranges, between what FontForge reports here and in its Font
Info window under OS/2 Character Ranges. I don't know why, but these ranges
are also not well defined in the TrueType standard.
</p>
<p>
Note the two characters from Devanagri. These are the danda and double-danda
used by other Indic scripts.
</p>
<p>
The ranges <span style="color: #555">beyond Unicode point 0xFFFF</span>, are
shaded. </p>
"""
html_heading = '''
<html>
<head>
<title>
Gnu FreeFont character range support
</title>
<style type="text/css">
tr.high { color: #555 }
tr.private { background-color: silver; }
td.num { text-align: right }
td { padding-right: 0.25ex }
th { padding: 0.25ex }
.roman { border-left: medium black solid; }
caption { font-size: larger; font-weight: bold; }
</style>
</head>
'''
def print_font_range_report( fontSupportList ):
print html_heading
print '<body>'
print '<h1>'
print 'Gnu FreeFont support for OpenType OS/2 character ranges'
print '</h1>'
print '<p>'
print table_introduction
print '</p>'
print_font_range_table( fontSupportList )
print '<p>'
print table_explanation
tzset()
print 'Generated by <code>range_report.py</code> on %s.' % (
strftime('%X %x %Z') )
print '</p>'
print '</body>'
print '</html>'
supportList = []
supportList.append( FontSupport( '../../sfd/FreeSerif.sfd', 'Srf' ) )
supportList.append( FontSupport( '../../sfd/FreeSerifItalic.sfd', 'Srf I' ) )
supportList.append( FontSupport( '../../sfd/FreeSerifBold.sfd', 'Srf B' ) )
supportList.append( FontSupport( '../../sfd/FreeSerifBoldItalic.sfd', 'Srf BI' ) )
supportList.append( FontSupport( '../../sfd/FreeSans.sfd', 'Sans' ) )
supportList.append( FontSupport( '../../sfd/FreeSansOblique.sfd', 'Sans O' ) )
supportList.append( FontSupport( '../../sfd/FreeSansBold.sfd', 'Sans B' ) )
supportList.append( FontSupport( '../../sfd/FreeSansBoldOblique.sfd', 'Sans BO' ) )
supportList.append( FontSupport( '../../sfd/FreeMono.sfd', 'Mono' ) )
supportList.append( FontSupport( '../../sfd/FreeMonoOblique.sfd', 'Mono O' ) )
supportList.append( FontSupport( '../../sfd/FreeMonoBold.sfd', 'Mono B' ) )
supportList.append( FontSupport( '../../sfd/FreeMonoBoldOblique.sfd', 'Mono BO' ) )
print_font_range_report( supportList )

View File

@ -0,0 +1,62 @@
__license__ = """
This file is part of Gnu FreeFont.
Gnu FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Gnu FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Gnu FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Stevan White"
__email__ = "stevan.white@googlemail.com"
__copyright__ = "Copyright 2009, 2010, Stevan White"
__date__ = "$Date: 2010-09-14 13:02:02 $"
__version__ = "$Revision: 1.3 $"
__doc__ = """
For use from the FontForge Script Menu.
Add it to the Scripts Menu using the Preferences dialog.
Sets the name and unicode values of the selected range of slots to the
encoding, that is
Name: uniXXXX
Unocode: u+XXXX
where XXXX is the n-digit hex value for the slot encoding.
Careful! it changes the value whether it was previously set or not.
Detailed info is printed to standard output (see by launching FontForge
from a console).
"""
import fontforge
def explain_error_and_quit( e ):
if e:
print 'Error: ', e
exit( 1 )
try:
glyphs = fontforge.activeFont().selection.byGlyphs
for g in glyphs:
if g.encoding <= 0xFFFF:
newname = 'uni%0.4x' %( g.encoding )
elif g.encoding <= 0xFFFFF:
newname = 'uni%0.5x' %( g.encoding )
elif g.encoding <= 0xFFFFFF:
newname = 'uni%0.6x' %( g.encoding )
elif g.encoding <= 0xFFFFFFF:
newname = 'uni%0.7x' %( g.encoding )
elif g.encoding <= 0xFFFFFFFF:
newname = 'uni%0.8x' %( g.encoding )
print "naming " + str( g.glyphname ) + ' as ' + newname
g.glyphname = newname
g.unicode = g.encoding
except ValueError, e:
explain_error_and_quit( e )

View File

@ -0,0 +1,54 @@
__license__ = """
This file is part of Gnu FreeFont.
Gnu FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Gnu FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Gnu FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Stevan White"
__email__ = "stevan.white@googlemail.com"
__copyright__ = "Copyright 2009, 2010, Stevan White"
__date__ = "$Date: 2010-09-14 13:02:02 $"
__version__ = "$Revision: 1.3 $"
__doc__ = """
For use from the FontForge Script Menu.
Add it to the Scripts Menu using the Preferences dialog.
Sets the name and unicode values of the selected range of slots to
the encoding, that is
Name: uniXXXX
Unocode: u+XXXX
where XXXX is the 4-digit hex value for the slot encoding.
Careful! it changes the falue whether it was previously set or not.
Detailed info is printed to standard output (see by launching FontForge
from a console).
"""
import fontforge
def explain_error_and_quit( e ):
if e:
print 'Error: ', e
exit( 1 )
try:
glyphs = fontforge.activeFont().selection.byGlyphs
for g in glyphs:
newname = 'NameMe.%s' %( str( g.encoding ) )
print "naming " + str( g.glyphname ) + ' as ' + newname
g.glyphname = newname
g.unicode = -1
except ValueError, e:
explain_error_and_quit( e )

View File

@ -0,0 +1,60 @@
#!/usr/bin/perl
# $Id: CheckConformance.pl,v 1.1 2009-12-27 16:25:15 Stevan_White Exp $
#
# Check conformance of font file with given character sets.
# Get the characters in the font file
# Regexp for ENCODING line matches BDF and PfaEdit's SFD formats
if ($#ARGV >= 0) {
open(FONTFILE, $ARGV[0]);
} else {
open(FONTFILE, "<stdin");
}
while (<FONTFILE>) {
if (/^E[Nn][Cc][Oo][Dd][Ii][Nn][Gg]:? ([\d]+)/) {
$char{$1} = 1;
}
}
close (FONTFILE);
$tbldir = "./";
@tables = ("MES-1.lst", "MES-2.lst", "MES-3B.lst");
foreach $table (0 .. $#tables) {
$tblfile = $tbldir.$tables[$table];
# Read in the table with the named entities
open(TABLE, "<$tblfile") || die "Cannot find $tblfile\n";
delete @table{keys %table};
while (<TABLE>) {
if (/^\#.*/) {
next;
} else {
chomp;
($code,$name) = split(/:/, $_, 9999);
$table{hex($code)} = $name;
}
}
close(TABLE);
# Get the list of missing chars, sorted numerically by their code
foreach $key (sort {$a <=> $b} keys %table) {
if ($char{$key} != 1) {
push @missing, $key;
}
}
# Print the list of missing chars, code and ISO 10646 name
if ($#missing >= 0) {
print "\n$#missing characters are found missing for conformance with ";
print "$tblfile:\n";
for ($i = 0; $i <= $#missing; $i++) {
printf("%04X %s\n", $missing[$i], $table{$missing[$i]});
}
} else {
print "\nCongratulations!\n";
print "No characters are found missing for conformance with ";
print "$tblfile.\n";
}
}

View File

@ -0,0 +1,335 @@
0020:SPACE
0021:EXCLAMATION MARK
0022:QUOTATION MARK
0023:NUMBER SIGN
0024:DOLLAR SIGN
0025:PERCENT SIGN
0026:AMPERSAND
0027:APOSTROPHE
0028:LEFT PARENTHESIS
0029:RIGHT PARENTHESIS
002A:ASTERISK
002B:PLUS SIGN
002C:COMMA
002D:HYPHEN-MINUS
002E:FULL STOP
002F:SOLIDUS
0030:DIGIT ZERO
0031:DIGIT ONE
0032:DIGIT TWO
0033:DIGIT THREE
0034:DIGIT FOUR
0035:DIGIT FIVE
0036:DIGIT SIX
0037:DIGIT SEVEN
0038:DIGIT EIGHT
0039:DIGIT NINE
003A:COLON
003B:SEMICOLON
003C:LESS-THAN SIGN
003D:EQUALS SIGN
003E:GREATER-THAN SIGN
003F:QUESTION MARK
0040:COMMERCIAL AT
0041:LATIN CAPITAL LETTER A
0042:LATIN CAPITAL LETTER B
0043:LATIN CAPITAL LETTER C
0044:LATIN CAPITAL LETTER D
0045:LATIN CAPITAL LETTER E
0046:LATIN CAPITAL LETTER F
0047:LATIN CAPITAL LETTER G
0048:LATIN CAPITAL LETTER H
0049:LATIN CAPITAL LETTER I
004A:LATIN CAPITAL LETTER J
004B:LATIN CAPITAL LETTER K
004C:LATIN CAPITAL LETTER L
004D:LATIN CAPITAL LETTER M
004E:LATIN CAPITAL LETTER N
004F:LATIN CAPITAL LETTER O
0050:LATIN CAPITAL LETTER P
0051:LATIN CAPITAL LETTER Q
0052:LATIN CAPITAL LETTER R
0053:LATIN CAPITAL LETTER S
0054:LATIN CAPITAL LETTER T
0055:LATIN CAPITAL LETTER U
0056:LATIN CAPITAL LETTER V
0057:LATIN CAPITAL LETTER W
0058:LATIN CAPITAL LETTER X
0059:LATIN CAPITAL LETTER Y
005A:LATIN CAPITAL LETTER Z
005B:LEFT SQUARE BRACKET
005C:REVERSE SOLIDUS
005D:RIGHT SQUARE BRACKET
005E:CIRCUMFLEX ACCENT
005F:LOW LINE
0060:GRAVE ACCENT
0061:LATIN SMALL LETTER A
0062:LATIN SMALL LETTER B
0063:LATIN SMALL LETTER C
0064:LATIN SMALL LETTER D
0065:LATIN SMALL LETTER E
0066:LATIN SMALL LETTER F
0067:LATIN SMALL LETTER G
0068:LATIN SMALL LETTER H
0069:LATIN SMALL LETTER I
006A:LATIN SMALL LETTER J
006B:LATIN SMALL LETTER K
006C:LATIN SMALL LETTER L
006D:LATIN SMALL LETTER M
006E:LATIN SMALL LETTER N
006F:LATIN SMALL LETTER O
0070:LATIN SMALL LETTER P
0071:LATIN SMALL LETTER Q
0072:LATIN SMALL LETTER R
0073:LATIN SMALL LETTER S
0074:LATIN SMALL LETTER T
0075:LATIN SMALL LETTER U
0076:LATIN SMALL LETTER V
0077:LATIN SMALL LETTER W
0078:LATIN SMALL LETTER X
0079:LATIN SMALL LETTER Y
007A:LATIN SMALL LETTER Z
007B:LEFT CURLY BRACKET
007C:VERTICAL LINE
007D:RIGHT CURLY BRACKET
007E:TILDE
00A0:NO-BREAK SPACE
00A1:INVERTED EXCLAMATION MARK
00A2:CENT SIGN
00A3:POUND SIGN
00A4:CURRENCY SIGN
00A5:YEN SIGN
00A6:BROKEN BAR
00A7:SECTION SIGN
00A8:DIAERESIS
00A9:COPYRIGHT SIGN
00AA:FEMININE ORDINAL INDICATOR
00AB:LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
00AC:NOT SIGN
00AD:SOFT HYPHEN
00AE:REGISTERED SIGN
00AF:MACRON
00B0:DEGREE SIGN
00B1:PLUS-MINUS SIGN
00B2:SUPERSCRIPT TWO
00B3:SUPERSCRIPT THREE
00B4:ACUTE ACCENT
00B5:MICRO SIGN
00B6:PILCROW SIGN
00B7:MIDDLE DOT
00B8:CEDILLA
00B9:SUPERSCRIPT ONE
00BA:MASCULINE ORDINAL INDICATOR
00BB:RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
00BC:VULGAR FRACTION ONE QUARTER
00BD:VULGAR FRACTION ONE HALF
00BE:VULGAR FRACTION THREE QUARTERS
00BF:INVERTED QUESTION MARK
00C0:LATIN CAPITAL LETTER A WITH GRAVE
00C1:LATIN CAPITAL LETTER A WITH ACUTE
00C2:LATIN CAPITAL LETTER A WITH CIRCUMFLEX
00C3:LATIN CAPITAL LETTER A WITH TILDE
00C4:LATIN CAPITAL LETTER A WITH DIAERESIS
00C5:LATIN CAPITAL LETTER A WITH RING ABOVE
00C6:LATIN CAPITAL LETTER AE
00C7:LATIN CAPITAL LETTER C WITH CEDILLA
00C8:LATIN CAPITAL LETTER E WITH GRAVE
00C9:LATIN CAPITAL LETTER E WITH ACUTE
00CA:LATIN CAPITAL LETTER E WITH CIRCUMFLEX
00CB:LATIN CAPITAL LETTER E WITH DIAERESIS
00CC:LATIN CAPITAL LETTER I WITH GRAVE
00CD:LATIN CAPITAL LETTER I WITH ACUTE
00CE:LATIN CAPITAL LETTER I WITH CIRCUMFLEX
00CF:LATIN CAPITAL LETTER I WITH DIAERESIS
00D0:LATIN CAPITAL LETTER ETH
00D1:LATIN CAPITAL LETTER N WITH TILDE
00D2:LATIN CAPITAL LETTER O WITH GRAVE
00D3:LATIN CAPITAL LETTER O WITH ACUTE
00D4:LATIN CAPITAL LETTER O WITH CIRCUMFLEX
00D5:LATIN CAPITAL LETTER O WITH TILDE
00D6:LATIN CAPITAL LETTER O WITH DIAERESIS
00D7:MULTIPLICATION SIGN
00D8:LATIN CAPITAL LETTER O WITH STROKE
00D9:LATIN CAPITAL LETTER U WITH GRAVE
00DA:LATIN CAPITAL LETTER U WITH ACUTE
00DB:LATIN CAPITAL LETTER U WITH CIRCUMFLEX
00DC:LATIN CAPITAL LETTER U WITH DIAERESIS
00DD:LATIN CAPITAL LETTER Y WITH ACUTE
00DE:LATIN CAPITAL LETTER THORN
00DF:LATIN SMALL LETTER SHARP S
00E0:LATIN SMALL LETTER A WITH GRAVE
00E1:LATIN SMALL LETTER A WITH ACUTE
00E2:LATIN SMALL LETTER A WITH CIRCUMFLEX
00E3:LATIN SMALL LETTER A WITH TILDE
00E4:LATIN SMALL LETTER A WITH DIAERESIS
00E5:LATIN SMALL LETTER A WITH RING ABOVE
00E6:LATIN SMALL LETTER AE
00E7:LATIN SMALL LETTER C WITH CEDILLA
00E8:LATIN SMALL LETTER E WITH GRAVE
00E9:LATIN SMALL LETTER E WITH ACUTE
00EA:LATIN SMALL LETTER E WITH CIRCUMFLEX
00EB:LATIN SMALL LETTER E WITH DIAERESIS
00EC:LATIN SMALL LETTER I WITH GRAVE
00ED:LATIN SMALL LETTER I WITH ACUTE
00EE:LATIN SMALL LETTER I WITH CIRCUMFLEX
00EF:LATIN SMALL LETTER I WITH DIAERESIS
00F0:LATIN SMALL LETTER ETH
00F1:LATIN SMALL LETTER N WITH TILDE
00F2:LATIN SMALL LETTER O WITH GRAVE
00F3:LATIN SMALL LETTER O WITH ACUTE
00F4:LATIN SMALL LETTER O WITH CIRCUMFLEX
00F5:LATIN SMALL LETTER O WITH TILDE
00F6:LATIN SMALL LETTER O WITH DIAERESIS
00F7:DIVISION SIGN
00F8:LATIN SMALL LETTER O WITH STROKE
00F9:LATIN SMALL LETTER U WITH GRAVE
00FA:LATIN SMALL LETTER U WITH ACUTE
00FB:LATIN SMALL LETTER U WITH CIRCUMFLEX
00FC:LATIN SMALL LETTER U WITH DIAERESIS
00FD:LATIN SMALL LETTER Y WITH ACUTE
00FE:LATIN SMALL LETTER THORN
00FF:LATIN SMALL LETTER Y WITH DIAERESIS
0100:LATIN CAPITAL LETTER A WITH MACRON
0101:LATIN SMALL LETTER A WITH MACRON
0102:LATIN CAPITAL LETTER A WITH BREVE
0103:LATIN SMALL LETTER A WITH BREVE
0104:LATIN CAPITAL LETTER A WITH OGONEK
0105:LATIN SMALL LETTER A WITH OGONEK
0106:LATIN CAPITAL LETTER C WITH ACUTE
0107:LATIN SMALL LETTER C WITH ACUTE
0108:LATIN CAPITAL LETTER C WITH CIRCUMFLEX
0109:LATIN SMALL LETTER C WITH CIRCUMFLEX
010A:LATIN CAPITAL LETTER C WITH DOT ABOVE
010B:LATIN SMALL LETTER C WITH DOT ABOVE
010C:LATIN CAPITAL LETTER C WITH CARON
010D:LATIN SMALL LETTER C WITH CARON
010E:LATIN CAPITAL LETTER D WITH CARON
010F:LATIN SMALL LETTER D WITH CARON
0110:LATIN CAPITAL LETTER D WITH STROKE
0111:LATIN SMALL LETTER D WITH STROKE
0112:LATIN CAPITAL LETTER E WITH MACRON
0113:LATIN SMALL LETTER E WITH MACRON
0116:LATIN CAPITAL LETTER E WITH DOT ABOVE
0117:LATIN SMALL LETTER E WITH DOT ABOVE
0118:LATIN CAPITAL LETTER E WITH OGONEK
0119:LATIN SMALL LETTER E WITH OGONEK
011A:LATIN CAPITAL LETTER E WITH CARON
011B:LATIN SMALL LETTER E WITH CARON
011C:LATIN CAPITAL LETTER G WITH CIRCUMFLEX
011D:LATIN SMALL LETTER G WITH CIRCUMFLEX
011E:LATIN CAPITAL LETTER G WITH BREVE
011F:LATIN SMALL LETTER G WITH BREVE
0120:LATIN CAPITAL LETTER G WITH DOT ABOVE
0121:LATIN SMALL LETTER G WITH DOT ABOVE
0122:LATIN CAPITAL LETTER G WITH CEDILLA
0123:LATIN SMALL LETTER G WITH CEDILLA
0124:LATIN CAPITAL LETTER H WITH CIRCUMFLEX
0125:LATIN SMALL LETTER H WITH CIRCUMFLEX
0126:LATIN CAPITAL LETTER H WITH STROKE
0127:LATIN SMALL LETTER H WITH STROKE
0128:LATIN CAPITAL LETTER I WITH TILDE
0129:LATIN SMALL LETTER I WITH TILDE
012A:LATIN CAPITAL LETTER I WITH MACRON
012B:LATIN SMALL LETTER I WITH MACRON
012E:LATIN CAPITAL LETTER I WITH OGONEK
012F:LATIN SMALL LETTER I WITH OGONEK
0130:LATIN CAPITAL LETTER I WITH DOT ABOVE
0131:LATIN SMALL LETTER DOTLESS I
0132:LATIN CAPITAL LIGATURE IJ
0133:LATIN SMALL LIGATURE IJ
0134:LATIN CAPITAL LETTER J WITH CIRCUMFLEX
0135:LATIN SMALL LETTER J WITH CIRCUMFLEX
0136:LATIN CAPITAL LETTER K WITH CEDILLA
0137:LATIN SMALL LETTER K WITH CEDILLA
0138:LATIN SMALL LETTER KRA
0139:LATIN CAPITAL LETTER L WITH ACUTE
013A:LATIN SMALL LETTER L WITH ACUTE
013B:LATIN CAPITAL LETTER L WITH CEDILLA
013C:LATIN SMALL LETTER L WITH CEDILLA
013D:LATIN CAPITAL LETTER L WITH CARON
013E:LATIN SMALL LETTER L WITH CARON
013F:LATIN CAPITAL LETTER L WITH MIDDLE DOT
0140:LATIN SMALL LETTER L WITH MIDDLE DOT
0141:LATIN CAPITAL LETTER L WITH STROKE
0142:LATIN SMALL LETTER L WITH STROKE
0143:LATIN CAPITAL LETTER N WITH ACUTE
0144:LATIN SMALL LETTER N WITH ACUTE
0145:LATIN CAPITAL LETTER N WITH CEDILLA
0146:LATIN SMALL LETTER N WITH CEDILLA
0147:LATIN CAPITAL LETTER N WITH CARON
0148:LATIN SMALL LETTER N WITH CARON
0149:LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
014A:LATIN CAPITAL LETTER ENG
014B:LATIN SMALL LETTER ENG
014C:LATIN CAPITAL LETTER O WITH MACRON
014D:LATIN SMALL LETTER O WITH MACRON
0150:LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
0151:LATIN SMALL LETTER O WITH DOUBLE ACUTE
0152:LATIN CAPITAL LIGATURE OE
0153:LATIN SMALL LIGATURE OE
0154:LATIN CAPITAL LETTER R WITH ACUTE
0155:LATIN SMALL LETTER R WITH ACUTE
0156:LATIN CAPITAL LETTER R WITH CEDILLA
0157:LATIN SMALL LETTER R WITH CEDILLA
0158:LATIN CAPITAL LETTER R WITH CARON
0159:LATIN SMALL LETTER R WITH CARON
015A:LATIN CAPITAL LETTER S WITH ACUTE
015B:LATIN SMALL LETTER S WITH ACUTE
015C:LATIN CAPITAL LETTER S WITH CIRCUMFLEX
015D:LATIN SMALL LETTER S WITH CIRCUMFLEX
015E:LATIN CAPITAL LETTER S WITH CEDILLA
015F:LATIN SMALL LETTER S WITH CEDILLA
0160:LATIN CAPITAL LETTER S WITH CARON
0161:LATIN SMALL LETTER S WITH CARON
0162:LATIN CAPITAL LETTER T WITH CEDILLA
0163:LATIN SMALL LETTER T WITH CEDILLA
0164:LATIN CAPITAL LETTER T WITH CARON
0165:LATIN SMALL LETTER T WITH CARON
0166:LATIN CAPITAL LETTER T WITH STROKE
0167:LATIN SMALL LETTER T WITH STROKE
0168:LATIN CAPITAL LETTER U WITH TILDE
0169:LATIN SMALL LETTER U WITH TILDE
016A:LATIN CAPITAL LETTER U WITH MACRON
016B:LATIN SMALL LETTER U WITH MACRON
016C:LATIN CAPITAL LETTER U WITH BREVE
016D:LATIN SMALL LETTER U WITH BREVE
016E:LATIN CAPITAL LETTER U WITH RING ABOVE
016F:LATIN SMALL LETTER U WITH RING ABOVE
0170:LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
0171:LATIN SMALL LETTER U WITH DOUBLE ACUTE
0172:LATIN CAPITAL LETTER U WITH OGONEK
0173:LATIN SMALL LETTER U WITH OGONEK
0174:LATIN CAPITAL LETTER W WITH CIRCUMFLEX
0175:LATIN SMALL LETTER W WITH CIRCUMFLEX
0176:LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
0177:LATIN SMALL LETTER Y WITH CIRCUMFLEX
0178:LATIN CAPITAL LETTER Y WITH DIAERESIS
0179:LATIN CAPITAL LETTER Z WITH ACUTE
017A:LATIN SMALL LETTER Z WITH ACUTE
017B:LATIN CAPITAL LETTER Z WITH DOT ABOVE
017C:LATIN SMALL LETTER Z WITH DOT ABOVE
017D:LATIN CAPITAL LETTER Z WITH CARON
017E:LATIN SMALL LETTER Z WITH CARON
02C7:CARON
02D8:BREVE
02D9:DOT ABOVE
02DA:RING ABOVE
02DB:OGONEK
02DD:DOUBLE ACUTE ACCENT
2015:HORIZONTAL BAR
2018:LEFT SINGLE QUOTATION MARK
2019:RIGHT SINGLE QUOTATION MARK
201C:LEFT DOUBLE QUOTATION MARK
201D:RIGHT DOUBLE QUOTATION MARK
20AC:EURO SIGN
2122:TRADE MARK SIGN
2126:OHM SIGN
215B:VULGAR FRACTION ONE EIGHTH
215C:VULGAR FRACTION THREE EIGHTHS
215D:VULGAR FRACTION FIVE EIGHTHS
215E:VULGAR FRACTION SEVEN EIGHTHS
2190:LEFTWARDS ARROW
2191:UPWARDS ARROW
2192:RIGHTWARDS ARROW
2193:DOWNWARDS ARROW
266A:EIGHTH NOTE

View File

@ -0,0 +1,8 @@
# Plane 00
# Rows Positions (Cells)
00 20-7E A0-FF
01 00-13 16-2B 2E-4D 50-7E
02 C7 D8-DB DD
20 15 18-19 1C-1D AC
21 22 26 5B-5E 90-93
26 6A

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,17 @@
# Plane 00
# Rows Positions (Cells)
00 20-7E A0-FF
01 00-7F 8F 92 B7 DE-EF FA-FF
02 18-1B 1E-1F 59 7C 92 BB-BD C6-C7 C9 D8-DD EE
03 74-75 7A 7E 84-8A 8C 8E-A1 A3-CE D7 DA-E1
04 00-5F 90-C4 C7-C8 CB-CC D0-EB EE-F5 F8-F9
1E 02-03 0A-0B 1E-1F 40-41 56-57 60-61 6A-6B 80-85 9B F2-F3
1F 00-15 18-1D 20-45 48-4D 50-57 59 5B 5D 5F-7D 80-B4 B6-C4 C6-D3 D6-DB DD-EF F2-F4 F6-FE
20 13-15 17-1E 20-22 26 30 32-33 39-3A 3C 3E 44 4A 7F 82 A3-A4 A7 AC AF
21 05 16 22 26 5B-5E 90-95 A8
22 00 02-03 06 08-09 0F 11-12 19-1A 1E-1F 27-2B 48 59 60-61 64-65 82-83 95 97
23 02 10 20-21 29-2A
25 00 02 0C 10 14 18 1C 24 2C 34 3C 50-6C 80 84 88 8C 90-93 A0 AC B2 BA BC C4 CA-CB D8-D9
26 3A-3C 40 42 60 63 65-66 6A-6B
FB 01-02
FF FD

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
# Plane 00
# Rows Positions (Cells)
00 20-7E A0-FF
01 00-FF
02 00-1F 22-33 50-AD B0-EE
03 00-4E 60-62 74-75 7A 7E 84-8A 8C 8E-A1 A3-CE D0-D7 DA-F3
04 00-86 88-89 8C-C4 C7-C8 CB-CC D0-F5 F8-F9
05 31-56 59-5F 61-87 89-8A
10 D0-F6 FB
1E 00-9B A0-F9
1F 00-15 18-1D 20-45 48-4D 50-57 59 5B 5D 5F-7D 80-B4 B6-C4 C6-D3 D6-DB DD-EF F2-F4 F6-FE
20 00-46 48-4D 6A-70 74-8E A0-AF D0-E3
21 00-3A 53-83 90-F3
22 00-F1
23 00-7B 7D-9A
34 40-4A
25 00-95 A0-F7
26 00-13 19-71
FB 00-06 13-17
FE 20-23
FF F9-FD

View File

@ -0,0 +1,653 @@
0020:SPACE
0021:EXCLAMATION MARK
0022:QUOTATION MARK
0023:NUMBER SIGN
0024:DOLLAR SIGN
0025:PERCENT SIGN
0026:AMPERSAND
0027:APOSTROPHE
0028:LEFT PARENTHESIS
0029:RIGHT PARENTHESIS
002A:ASTERISK
002B:PLUS SIGN
002C:COMMA
002D:HYPHEN-MINUS
002E:FULL STOP
002F:SOLIDUS
0030:DIGIT ZERO
0031:DIGIT ONE
0032:DIGIT TWO
0033:DIGIT THREE
0034:DIGIT FOUR
0035:DIGIT FIVE
0036:DIGIT SIX
0037:DIGIT SEVEN
0038:DIGIT EIGHT
0039:DIGIT NINE
003A:COLON
003B:SEMICOLON
003C:LESS-THAN SIGN
003D:EQUALS SIGN
003E:GREATER-THAN SIGN
003F:QUESTION MARK
0040:COMMERCIAL AT
0041:LATIN CAPITAL LETTER A
0042:LATIN CAPITAL LETTER B
0043:LATIN CAPITAL LETTER C
0044:LATIN CAPITAL LETTER D
0045:LATIN CAPITAL LETTER E
0046:LATIN CAPITAL LETTER F
0047:LATIN CAPITAL LETTER G
0048:LATIN CAPITAL LETTER H
0049:LATIN CAPITAL LETTER I
004A:LATIN CAPITAL LETTER J
004B:LATIN CAPITAL LETTER K
004C:LATIN CAPITAL LETTER L
004D:LATIN CAPITAL LETTER M
004E:LATIN CAPITAL LETTER N
004F:LATIN CAPITAL LETTER O
0050:LATIN CAPITAL LETTER P
0051:LATIN CAPITAL LETTER Q
0052:LATIN CAPITAL LETTER R
0053:LATIN CAPITAL LETTER S
0054:LATIN CAPITAL LETTER T
0055:LATIN CAPITAL LETTER U
0056:LATIN CAPITAL LETTER V
0057:LATIN CAPITAL LETTER W
0058:LATIN CAPITAL LETTER X
0059:LATIN CAPITAL LETTER Y
005A:LATIN CAPITAL LETTER Z
005B:LEFT SQUARE BRACKET
005C:REVERSE SOLIDUS
005D:RIGHT SQUARE BRACKET
005E:CIRCUMFLEX ACCENT
005F:LOW LINE
0060:GRAVE ACCENT
0061:LATIN SMALL LETTER A
0062:LATIN SMALL LETTER B
0063:LATIN SMALL LETTER C
0064:LATIN SMALL LETTER D
0065:LATIN SMALL LETTER E
0066:LATIN SMALL LETTER F
0067:LATIN SMALL LETTER G
0068:LATIN SMALL LETTER H
0069:LATIN SMALL LETTER I
006A:LATIN SMALL LETTER J
006B:LATIN SMALL LETTER K
006C:LATIN SMALL LETTER L
006D:LATIN SMALL LETTER M
006E:LATIN SMALL LETTER N
006F:LATIN SMALL LETTER O
0070:LATIN SMALL LETTER P
0071:LATIN SMALL LETTER Q
0072:LATIN SMALL LETTER R
0073:LATIN SMALL LETTER S
0074:LATIN SMALL LETTER T
0075:LATIN SMALL LETTER U
0076:LATIN SMALL LETTER V
0077:LATIN SMALL LETTER W
0078:LATIN SMALL LETTER X
0079:LATIN SMALL LETTER Y
007A:LATIN SMALL LETTER Z
007B:LEFT CURLY BRACKET
007C:VERTICAL LINE
007D:RIGHT CURLY BRACKET
007E:TILDE
00A0:NO-BREAK SPACE
00A1:INVERTED EXCLAMATION MARK
00A2:CENT SIGN
00A3:POUND SIGN
00A4:CURRENCY SIGN
00A5:YEN SIGN
00A6:BROKEN BAR
00A7:SECTION SIGN
00A8:DIAERESIS
00A9:COPYRIGHT SIGN
00AA:FEMININE ORDINAL INDICATOR
00AB:LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
00AC:NOT SIGN
00AD:SOFT HYPHEN
00AE:REGISTERED SIGN
00AF:MACRON
00B0:DEGREE SIGN
00B1:PLUS-MINUS SIGN
00B2:SUPERSCRIPT TWO
00B3:SUPERSCRIPT THREE
00B4:ACUTE ACCENT
00B5:MICRO SIGN
00B6:PILCROW SIGN
00B7:MIDDLE DOT
00B8:CEDILLA
00B9:SUPERSCRIPT ONE
00BA:MASCULINE ORDINAL INDICATOR
00BB:RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
00BC:VULGAR FRACTION ONE QUARTER
00BD:VULGAR FRACTION ONE HALF
00BE:VULGAR FRACTION THREE QUARTERS
00BF:INVERTED QUESTION MARK
00C0:LATIN CAPITAL LETTER A WITH GRAVE
00C1:LATIN CAPITAL LETTER A WITH ACUTE
00C2:LATIN CAPITAL LETTER A WITH CIRCUMFLEX
00C3:LATIN CAPITAL LETTER A WITH TILDE
00C4:LATIN CAPITAL LETTER A WITH DIAERESIS
00C5:LATIN CAPITAL LETTER A WITH RING ABOVE
00C6:LATIN CAPITAL LETTER AE
00C7:LATIN CAPITAL LETTER C WITH CEDILLA
00C8:LATIN CAPITAL LETTER E WITH GRAVE
00C9:LATIN CAPITAL LETTER E WITH ACUTE
00CA:LATIN CAPITAL LETTER E WITH CIRCUMFLEX
00CB:LATIN CAPITAL LETTER E WITH DIAERESIS
00CC:LATIN CAPITAL LETTER I WITH GRAVE
00CD:LATIN CAPITAL LETTER I WITH ACUTE
00CE:LATIN CAPITAL LETTER I WITH CIRCUMFLEX
00CF:LATIN CAPITAL LETTER I WITH DIAERESIS
00D0:LATIN CAPITAL LETTER ETH
00D1:LATIN CAPITAL LETTER N WITH TILDE
00D2:LATIN CAPITAL LETTER O WITH GRAVE
00D3:LATIN CAPITAL LETTER O WITH ACUTE
00D4:LATIN CAPITAL LETTER O WITH CIRCUMFLEX
00D5:LATIN CAPITAL LETTER O WITH TILDE
00D6:LATIN CAPITAL LETTER O WITH DIAERESIS
00D7:MULTIPLICATION SIGN
00D8:LATIN CAPITAL LETTER O WITH STROKE
00D9:LATIN CAPITAL LETTER U WITH GRAVE
00DA:LATIN CAPITAL LETTER U WITH ACUTE
00DB:LATIN CAPITAL LETTER U WITH CIRCUMFLEX
00DC:LATIN CAPITAL LETTER U WITH DIAERESIS
00DD:LATIN CAPITAL LETTER Y WITH ACUTE
00DE:LATIN CAPITAL LETTER THORN
00DF:LATIN SMALL LETTER SHARP S
00E0:LATIN SMALL LETTER A WITH GRAVE
00E1:LATIN SMALL LETTER A WITH ACUTE
00E2:LATIN SMALL LETTER A WITH CIRCUMFLEX
00E3:LATIN SMALL LETTER A WITH TILDE
00E4:LATIN SMALL LETTER A WITH DIAERESIS
00E5:LATIN SMALL LETTER A WITH RING ABOVE
00E6:LATIN SMALL LETTER AE
00E7:LATIN SMALL LETTER C WITH CEDILLA
00E8:LATIN SMALL LETTER E WITH GRAVE
00E9:LATIN SMALL LETTER E WITH ACUTE
00EA:LATIN SMALL LETTER E WITH CIRCUMFLEX
00EB:LATIN SMALL LETTER E WITH DIAERESIS
00EC:LATIN SMALL LETTER I WITH GRAVE
00ED:LATIN SMALL LETTER I WITH ACUTE
00EE:LATIN SMALL LETTER I WITH CIRCUMFLEX
00EF:LATIN SMALL LETTER I WITH DIAERESIS
00F0:LATIN SMALL LETTER ETH
00F1:LATIN SMALL LETTER N WITH TILDE
00F2:LATIN SMALL LETTER O WITH GRAVE
00F3:LATIN SMALL LETTER O WITH ACUTE
00F4:LATIN SMALL LETTER O WITH CIRCUMFLEX
00F5:LATIN SMALL LETTER O WITH TILDE
00F6:LATIN SMALL LETTER O WITH DIAERESIS
00F7:DIVISION SIGN
00F8:LATIN SMALL LETTER O WITH STROKE
00F9:LATIN SMALL LETTER U WITH GRAVE
00FA:LATIN SMALL LETTER U WITH ACUTE
00FB:LATIN SMALL LETTER U WITH CIRCUMFLEX
00FC:LATIN SMALL LETTER U WITH DIAERESIS
00FD:LATIN SMALL LETTER Y WITH ACUTE
00FE:LATIN SMALL LETTER THORN
00FF:LATIN SMALL LETTER Y WITH DIAERESIS
0100:LATIN CAPITAL LETTER A WITH MACRON
0101:LATIN SMALL LETTER A WITH MACRON
0102:LATIN CAPITAL LETTER A WITH BREVE
0103:LATIN SMALL LETTER A WITH BREVE
0104:LATIN CAPITAL LETTER A WITH OGONEK
0105:LATIN SMALL LETTER A WITH OGONEK
0106:LATIN CAPITAL LETTER C WITH ACUTE
0107:LATIN SMALL LETTER C WITH ACUTE
0108:LATIN CAPITAL LETTER C WITH CIRCUMFLEX
0109:LATIN SMALL LETTER C WITH CIRCUMFLEX
010A:LATIN CAPITAL LETTER C WITH DOT ABOVE
010B:LATIN SMALL LETTER C WITH DOT ABOVE
010C:LATIN CAPITAL LETTER C WITH CARON
010D:LATIN SMALL LETTER C WITH CARON
010E:LATIN CAPITAL LETTER D WITH CARON
010F:LATIN SMALL LETTER D WITH CARON
0110:LATIN CAPITAL LETTER D WITH STROKE
0111:LATIN SMALL LETTER D WITH STROKE
0112:LATIN CAPITAL LETTER E WITH MACRON
0113:LATIN SMALL LETTER E WITH MACRON
0114:LATIN CAPITAL LETTER E WITH BREVE
0115:LATIN SMALL LETTER E WITH BREVE
0116:LATIN CAPITAL LETTER E WITH DOT ABOVE
0117:LATIN SMALL LETTER E WITH DOT ABOVE
0118:LATIN CAPITAL LETTER E WITH OGONEK
0119:LATIN SMALL LETTER E WITH OGONEK
011A:LATIN CAPITAL LETTER E WITH CARON
011B:LATIN SMALL LETTER E WITH CARON
011C:LATIN CAPITAL LETTER G WITH CIRCUMFLEX
011D:LATIN SMALL LETTER G WITH CIRCUMFLEX
011E:LATIN CAPITAL LETTER G WITH BREVE
011F:LATIN SMALL LETTER G WITH BREVE
0120:LATIN CAPITAL LETTER G WITH DOT ABOVE
0121:LATIN SMALL LETTER G WITH DOT ABOVE
0122:LATIN CAPITAL LETTER G WITH CEDILLA
0123:LATIN SMALL LETTER G WITH CEDILLA
0124:LATIN CAPITAL LETTER H WITH CIRCUMFLEX
0125:LATIN SMALL LETTER H WITH CIRCUMFLEX
0126:LATIN CAPITAL LETTER H WITH STROKE
0127:LATIN SMALL LETTER H WITH STROKE
0128:LATIN CAPITAL LETTER I WITH TILDE
0129:LATIN SMALL LETTER I WITH TILDE
012A:LATIN CAPITAL LETTER I WITH MACRON
012B:LATIN SMALL LETTER I WITH MACRON
012C:LATIN CAPITAL LETTER I WITH BREVE
012D:LATIN SMALL LETTER I WITH BREVE
012E:LATIN CAPITAL LETTER I WITH OGONEK
012F:LATIN SMALL LETTER I WITH OGONEK
0130:LATIN CAPITAL LETTER I WITH DOT ABOVE
0131:LATIN SMALL LETTER DOTLESS I
0132:LATIN CAPITAL LIGATURE IJ
0133:LATIN SMALL LIGATURE IJ
0134:LATIN CAPITAL LETTER J WITH CIRCUMFLEX
0135:LATIN SMALL LETTER J WITH CIRCUMFLEX
0136:LATIN CAPITAL LETTER K WITH CEDILLA
0137:LATIN SMALL LETTER K WITH CEDILLA
0138:LATIN SMALL LETTER KRA
0139:LATIN CAPITAL LETTER L WITH ACUTE
013A:LATIN SMALL LETTER L WITH ACUTE
013B:LATIN CAPITAL LETTER L WITH CEDILLA
013C:LATIN SMALL LETTER L WITH CEDILLA
013D:LATIN CAPITAL LETTER L WITH CARON
013E:LATIN SMALL LETTER L WITH CARON
013F:LATIN CAPITAL LETTER L WITH MIDDLE DOT
0140:LATIN SMALL LETTER L WITH MIDDLE DOT
0141:LATIN CAPITAL LETTER L WITH STROKE
0142:LATIN SMALL LETTER L WITH STROKE
0143:LATIN CAPITAL LETTER N WITH ACUTE
0144:LATIN SMALL LETTER N WITH ACUTE
0145:LATIN CAPITAL LETTER N WITH CEDILLA
0146:LATIN SMALL LETTER N WITH CEDILLA
0147:LATIN CAPITAL LETTER N WITH CARON
0148:LATIN SMALL LETTER N WITH CARON
0149:LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
014A:LATIN CAPITAL LETTER ENG
014B:LATIN SMALL LETTER ENG
014C:LATIN CAPITAL LETTER O WITH MACRON
014D:LATIN SMALL LETTER O WITH MACRON
014E:LATIN CAPITAL LETTER O WITH BREVE
014F:LATIN SMALL LETTER O WITH BREVE
0150:LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
0151:LATIN SMALL LETTER O WITH DOUBLE ACUTE
0152:LATIN CAPITAL LIGATURE OE
0153:LATIN SMALL LIGATURE OE
0154:LATIN CAPITAL LETTER R WITH ACUTE
0155:LATIN SMALL LETTER R WITH ACUTE
0156:LATIN CAPITAL LETTER R WITH CEDILLA
0157:LATIN SMALL LETTER R WITH CEDILLA
0158:LATIN CAPITAL LETTER R WITH CARON
0159:LATIN SMALL LETTER R WITH CARON
015A:LATIN CAPITAL LETTER S WITH ACUTE
015B:LATIN SMALL LETTER S WITH ACUTE
015C:LATIN CAPITAL LETTER S WITH CIRCUMFLEX
015D:LATIN SMALL LETTER S WITH CIRCUMFLEX
015E:LATIN CAPITAL LETTER S WITH CEDILLA
015F:LATIN SMALL LETTER S WITH CEDILLA
0160:LATIN CAPITAL LETTER S WITH CARON
0161:LATIN SMALL LETTER S WITH CARON
0162:LATIN CAPITAL LETTER T WITH CEDILLA
0163:LATIN SMALL LETTER T WITH CEDILLA
0164:LATIN CAPITAL LETTER T WITH CARON
0165:LATIN SMALL LETTER T WITH CARON
0166:LATIN CAPITAL LETTER T WITH STROKE
0167:LATIN SMALL LETTER T WITH STROKE
0168:LATIN CAPITAL LETTER U WITH TILDE
0169:LATIN SMALL LETTER U WITH TILDE
016A:LATIN CAPITAL LETTER U WITH MACRON
016B:LATIN SMALL LETTER U WITH MACRON
016C:LATIN CAPITAL LETTER U WITH BREVE
016D:LATIN SMALL LETTER U WITH BREVE
016E:LATIN CAPITAL LETTER U WITH RING ABOVE
016F:LATIN SMALL LETTER U WITH RING ABOVE
0170:LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
0171:LATIN SMALL LETTER U WITH DOUBLE ACUTE
0172:LATIN CAPITAL LETTER U WITH OGONEK
0173:LATIN SMALL LETTER U WITH OGONEK
0174:LATIN CAPITAL LETTER W WITH CIRCUMFLEX
0175:LATIN SMALL LETTER W WITH CIRCUMFLEX
0176:LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
0177:LATIN SMALL LETTER Y WITH CIRCUMFLEX
0178:LATIN CAPITAL LETTER Y WITH DIAERESIS
0179:LATIN CAPITAL LETTER Z WITH ACUTE
017A:LATIN SMALL LETTER Z WITH ACUTE
017B:LATIN CAPITAL LETTER Z WITH DOT ABOVE
017C:LATIN SMALL LETTER Z WITH DOT ABOVE
017D:LATIN CAPITAL LETTER Z WITH CARON
017E:LATIN SMALL LETTER Z WITH CARON
017F:LATIN SMALL LETTER LONG S
0192:LATIN SMALL LETTER F WITH HOOK
01FA:LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE
01FB:LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE
01FC:LATIN CAPITAL LETTER AE WITH ACUTE
01FD:LATIN SMALL LETTER AE WITH ACUTE
01FE:LATIN CAPITAL LETTER O WITH STROKE AND ACUTE
01FF:LATIN SMALL LETTER O WITH STROKE AND ACUTE
02C6:MODIFIER LETTER CIRCUMFLEX ACCENT
02C7:CARON
02C9:MODIFIER LETTER MACRON
02D8:BREVE
02D9:DOT ABOVE
02DA:RING ABOVE
02DB:OGONEK
02DC:SMALL TILDE
02DD:DOUBLE ACUTE ACCENT
0384:GREEK TONOS
0385:GREEK DIALYTIKA TONOS
0386:GREEK CAPITAL LETTER ALPHA WITH TONOS
0387:GREEK ANO TELEIA
0388:GREEK CAPITAL LETTER EPSILON WITH TONOS
0389:GREEK CAPITAL LETTER ETA WITH TONOS
038A:GREEK CAPITAL LETTER IOTA WITH TONOS
038C:GREEK CAPITAL LETTER OMICRON WITH TONOS
038E:GREEK CAPITAL LETTER UPSILON WITH TONOS
038F:GREEK CAPITAL LETTER OMEGA WITH TONOS
0390:GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
0391:GREEK CAPITAL LETTER ALPHA
0392:GREEK CAPITAL LETTER BETA
0393:GREEK CAPITAL LETTER GAMMA
0394:GREEK CAPITAL LETTER DELTA
0395:GREEK CAPITAL LETTER EPSILON
0396:GREEK CAPITAL LETTER ZETA
0397:GREEK CAPITAL LETTER ETA
0398:GREEK CAPITAL LETTER THETA
0399:GREEK CAPITAL LETTER IOTA
039A:GREEK CAPITAL LETTER KAPPA
039B:GREEK CAPITAL LETTER LAMDA
039C:GREEK CAPITAL LETTER MU
039D:GREEK CAPITAL LETTER NU
039E:GREEK CAPITAL LETTER XI
039F:GREEK CAPITAL LETTER OMICRON
03A0:GREEK CAPITAL LETTER PI
03A1:GREEK CAPITAL LETTER RHO
03A3:GREEK CAPITAL LETTER SIGMA
03A4:GREEK CAPITAL LETTER TAU
03A5:GREEK CAPITAL LETTER UPSILON
03A6:GREEK CAPITAL LETTER PHI
03A7:GREEK CAPITAL LETTER CHI
03A8:GREEK CAPITAL LETTER PSI
03A9:GREEK CAPITAL LETTER OMEGA
03AA:GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
03AB:GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
03AC:GREEK SMALL LETTER ALPHA WITH TONOS
03AD:GREEK SMALL LETTER EPSILON WITH TONOS
03AE:GREEK SMALL LETTER ETA WITH TONOS
03AF:GREEK SMALL LETTER IOTA WITH TONOS
03B0:GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
03B1:GREEK SMALL LETTER ALPHA
03B2:GREEK SMALL LETTER BETA
03B3:GREEK SMALL LETTER GAMMA
03B4:GREEK SMALL LETTER DELTA
03B5:GREEK SMALL LETTER EPSILON
03B6:GREEK SMALL LETTER ZETA
03B7:GREEK SMALL LETTER ETA
03B8:GREEK SMALL LETTER THETA
03B9:GREEK SMALL LETTER IOTA
03BA:GREEK SMALL LETTER KAPPA
03BB:GREEK SMALL LETTER LAMDA
03BC:GREEK SMALL LETTER MU
03BD:GREEK SMALL LETTER NU
03BE:GREEK SMALL LETTER XI
03BF:GREEK SMALL LETTER OMICRON
03C0:GREEK SMALL LETTER PI
03C1:GREEK SMALL LETTER RHO
03C2:GREEK SMALL LETTER FINAL SIGMA
03C3:GREEK SMALL LETTER SIGMA
03C4:GREEK SMALL LETTER TAU
03C5:GREEK SMALL LETTER UPSILON
03C6:GREEK SMALL LETTER PHI
03C7:GREEK SMALL LETTER CHI
03C8:GREEK SMALL LETTER PSI
03C9:GREEK SMALL LETTER OMEGA
03CA:GREEK SMALL LETTER IOTA WITH DIALYTIKA
03CB:GREEK SMALL LETTER UPSILON WITH DIALYTIKA
03CC:GREEK SMALL LETTER OMICRON WITH TONOS
03CD:GREEK SMALL LETTER UPSILON WITH TONOS
03CE:GREEK SMALL LETTER OMEGA WITH TONOS
0401:CYRILLIC CAPITAL LETTER IO
0402:CYRILLIC CAPITAL LETTER DJE
0403:CYRILLIC CAPITAL LETTER GJE
0404:CYRILLIC CAPITAL LETTER UKRAINIAN IE
0405:CYRILLIC CAPITAL LETTER DZE
0406:CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
0407:CYRILLIC CAPITAL LETTER YI
0408:CYRILLIC CAPITAL LETTER JE
0409:CYRILLIC CAPITAL LETTER LJE
040A:CYRILLIC CAPITAL LETTER NJE
040B:CYRILLIC CAPITAL LETTER TSHE
040C:CYRILLIC CAPITAL LETTER KJE
040E:CYRILLIC CAPITAL LETTER SHORT U
040F:CYRILLIC CAPITAL LETTER DZHE
0410:CYRILLIC CAPITAL LETTER A
0411:CYRILLIC CAPITAL LETTER BE
0412:CYRILLIC CAPITAL LETTER VE
0413:CYRILLIC CAPITAL LETTER GHE
0414:CYRILLIC CAPITAL LETTER DE
0415:CYRILLIC CAPITAL LETTER IE
0416:CYRILLIC CAPITAL LETTER ZHE
0417:CYRILLIC CAPITAL LETTER ZE
0418:CYRILLIC CAPITAL LETTER I
0419:CYRILLIC CAPITAL LETTER SHORT I
041A:CYRILLIC CAPITAL LETTER KA
041B:CYRILLIC CAPITAL LETTER EL
041C:CYRILLIC CAPITAL LETTER EM
041D:CYRILLIC CAPITAL LETTER EN
041E:CYRILLIC CAPITAL LETTER O
041F:CYRILLIC CAPITAL LETTER PE
0420:CYRILLIC CAPITAL LETTER ER
0421:CYRILLIC CAPITAL LETTER ES
0422:CYRILLIC CAPITAL LETTER TE
0423:CYRILLIC CAPITAL LETTER U
0424:CYRILLIC CAPITAL LETTER EF
0425:CYRILLIC CAPITAL LETTER HA
0426:CYRILLIC CAPITAL LETTER TSE
0427:CYRILLIC CAPITAL LETTER CHE
0428:CYRILLIC CAPITAL LETTER SHA
0429:CYRILLIC CAPITAL LETTER SHCHA
042A:CYRILLIC CAPITAL LETTER HARD SIGN
042B:CYRILLIC CAPITAL LETTER YERU
042C:CYRILLIC CAPITAL LETTER SOFT SIGN
042D:CYRILLIC CAPITAL LETTER E
042E:CYRILLIC CAPITAL LETTER YU
042F:CYRILLIC CAPITAL LETTER YA
0430:CYRILLIC SMALL LETTER A
0431:CYRILLIC SMALL LETTER BE
0432:CYRILLIC SMALL LETTER VE
0433:CYRILLIC SMALL LETTER GHE
0434:CYRILLIC SMALL LETTER DE
0435:CYRILLIC SMALL LETTER IE
0436:CYRILLIC SMALL LETTER ZHE
0437:CYRILLIC SMALL LETTER ZE
0438:CYRILLIC SMALL LETTER I
0439:CYRILLIC SMALL LETTER SHORT I
043A:CYRILLIC SMALL LETTER KA
043B:CYRILLIC SMALL LETTER EL
043C:CYRILLIC SMALL LETTER EM
043D:CYRILLIC SMALL LETTER EN
043E:CYRILLIC SMALL LETTER O
043F:CYRILLIC SMALL LETTER PE
0440:CYRILLIC SMALL LETTER ER
0441:CYRILLIC SMALL LETTER ES
0442:CYRILLIC SMALL LETTER TE
0443:CYRILLIC SMALL LETTER U
0444:CYRILLIC SMALL LETTER EF
0445:CYRILLIC SMALL LETTER HA
0446:CYRILLIC SMALL LETTER TSE
0447:CYRILLIC SMALL LETTER CHE
0448:CYRILLIC SMALL LETTER SHA
0449:CYRILLIC SMALL LETTER SHCHA
044A:CYRILLIC SMALL LETTER HARD SIGN
044B:CYRILLIC SMALL LETTER YERU
044C:CYRILLIC SMALL LETTER SOFT SIGN
044D:CYRILLIC SMALL LETTER E
044E:CYRILLIC SMALL LETTER YU
044F:CYRILLIC SMALL LETTER YA
0451:CYRILLIC SMALL LETTER IO
0452:CYRILLIC SMALL LETTER DJE
0453:CYRILLIC SMALL LETTER GJE
0454:CYRILLIC SMALL LETTER UKRAINIAN IE
0455:CYRILLIC SMALL LETTER DZE
0456:CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
0457:CYRILLIC SMALL LETTER YI
0458:CYRILLIC SMALL LETTER JE
0459:CYRILLIC SMALL LETTER LJE
045A:CYRILLIC SMALL LETTER NJE
045B:CYRILLIC SMALL LETTER TSHE
045C:CYRILLIC SMALL LETTER KJE
045E:CYRILLIC SMALL LETTER SHORT U
045F:CYRILLIC SMALL LETTER DZHE
0490:CYRILLIC CAPITAL LETTER GHE WITH UPTURN
0491:CYRILLIC SMALL LETTER GHE WITH UPTURN
1E80:LATIN CAPITAL LETTER W WITH GRAVE
1E81:LATIN SMALL LETTER W WITH GRAVE
1E82:LATIN CAPITAL LETTER W WITH ACUTE
1E83:LATIN SMALL LETTER W WITH ACUTE
1E84:LATIN CAPITAL LETTER W WITH DIAERESIS
1E85:LATIN SMALL LETTER W WITH DIAERESIS
1EF2:LATIN CAPITAL LETTER Y WITH GRAVE
1EF3:LATIN SMALL LETTER Y WITH GRAVE
2013:EN DASH
2014:EM DASH
2015:HORIZONTAL BAR
2017:DOUBLE LOW LINE
2018:LEFT SINGLE QUOTATION MARK
2019:RIGHT SINGLE QUOTATION MARK
201A:SINGLE LOW-9 QUOTATION MARK
201B:SINGLE HIGH-REVERSED-9 QUOTATION MARK
201C:LEFT DOUBLE QUOTATION MARK
201D:RIGHT DOUBLE QUOTATION MARK
201E:DOUBLE LOW-9 QUOTATION MARK
2020:DAGGER
2021:DOUBLE DAGGER
2022:BULLET
2026:HORIZONTAL ELLIPSIS
2030:PER MILLE SIGN
2032:PRIME
2033:DOUBLE PRIME
2039:SINGLE LEFT-POINTING ANGLE QUOTATION MARK
203A:SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
203C:DOUBLE EXCLAMATION MARK
203E:OVERLINE
2044:FRACTION SLASH
207F:SUPERSCRIPT LATIN SMALL LETTER N
20A3:FRENCH FRANC SIGN
20A4:LIRA SIGN
20A7:PESETA SIGN
20AC:EURO SIGN
2105:CARE OF
2113:SCRIPT SMALL L
2116:NUMERO SIGN
2122:TRADE MARK SIGN
2126:OHM SIGN
212E:ESTIMATED SYMBOL
215B:VULGAR FRACTION ONE EIGHTH
215C:VULGAR FRACTION THREE EIGHTHS
215D:VULGAR FRACTION FIVE EIGHTHS
215E:VULGAR FRACTION SEVEN EIGHTHS
2190:LEFTWARDS ARROW
2191:UPWARDS ARROW
2192:RIGHTWARDS ARROW
2193:DOWNWARDS ARROW
2194:LEFT RIGHT ARROW
2195:UP DOWN ARROW
21A8:UP DOWN ARROW WITH BASE
2202:PARTIAL DIFFERENTIAL
2206:INCREMENT
220F:N-ARY PRODUCT
2211:N-ARY SUMMATION
2212:MINUS SIGN
2215:DIVISION SLASH
2219:BULLET OPERATOR
221A:SQUARE ROOT
221E:INFINITY
221F:RIGHT ANGLE
2229:INTERSECTION
222B:INTEGRAL
2248:ALMOST EQUAL TO
2260:NOT EQUAL TO
2261:IDENTICAL TO
2264:LESS-THAN OR EQUAL TO
2265:GREATER-THAN OR EQUAL TO
2302:HOUSE
2310:REVERSED NOT SIGN
2320:TOP HALF INTEGRAL
2321:BOTTOM HALF INTEGRAL
2500:BOX DRAWINGS LIGHT HORIZONTAL
2502:BOX DRAWINGS LIGHT VERTICAL
250C:BOX DRAWINGS LIGHT DOWN AND RIGHT
2510:BOX DRAWINGS LIGHT DOWN AND LEFT
2514:BOX DRAWINGS LIGHT UP AND RIGHT
2518:BOX DRAWINGS LIGHT UP AND LEFT
251C:BOX DRAWINGS LIGHT VERTICAL AND RIGHT
2524:BOX DRAWINGS LIGHT VERTICAL AND LEFT
252C:BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
2534:BOX DRAWINGS LIGHT UP AND HORIZONTAL
253C:BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
2550:BOX DRAWINGS DOUBLE HORIZONTAL
2551:BOX DRAWINGS DOUBLE VERTICAL
2552:BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
2553:BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
2554:BOX DRAWINGS DOUBLE DOWN AND RIGHT
2555:BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
2556:BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
2557:BOX DRAWINGS DOUBLE DOWN AND LEFT
2558:BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
2559:BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
255A:BOX DRAWINGS DOUBLE UP AND RIGHT
255B:BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
255C:BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
255D:BOX DRAWINGS DOUBLE UP AND LEFT
255E:BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
255F:BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
2560:BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
2561:BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
2562:BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
2563:BOX DRAWINGS DOUBLE VERTICAL AND LEFT
2564:BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
2565:BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
2566:BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
2567:BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
2568:BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
2569:BOX DRAWINGS DOUBLE UP AND HORIZONTAL
256A:BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
256B:BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
256C:BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
2580:UPPER HALF BLOCK
2584:LOWER HALF BLOCK
2588:FULL BLOCK
258C:LEFT HALF BLOCK
2590:RIGHT HALF BLOCK
2591:LIGHT SHADE
2592:MEDIUM SHADE
2593:DARK SHADE
25A0:BLACK SQUARE
25A1:WHITE SQUARE
25AA:BLACK SMALL SQUARE
25AB:WHITE SMALL SQUARE
25AC:BLACK RECTANGLE
25B2:BLACK UP-POINTING TRIANGLE
25BA:BLACK RIGHT-POINTING POINTER
25BC:BLACK DOWN-POINTING TRIANGLE
25C4:BLACK LEFT-POINTING POINTER
25CA:LOZENGE
25CB:WHITE CIRCLE
25CF:BLACK CIRCLE
25D8:INVERSE BULLET
25D9:INVERSE WHITE CIRCLE
25E6:WHITE BULLET
263A:WHITE SMILING FACE
263B:BLACK SMILING FACE
263C:WHITE SUN WITH RAYS
2640:FEMALE SIGN
2642:MALE SIGN
2660:BLACK SPADE SUIT
2663:BLACK CLUB SUIT
2665:BLACK HEART SUIT
2666:BLACK DIAMOND SUIT
266A:EIGHTH NOTE
266B:BEAMED EIGHTH NOTES
F001:LATIN SMALL LIGATURE FI
F002:LATIN SMALL LIGATURE FL
FB01:LATIN SMALL LIGATURE FI
FB02:LATIN SMALL LIGATURE FL

View File

@ -0,0 +1,45 @@
#!/usr/bin/perl
# $Id: mes-list-expand.pl,v 1.1 2009-12-27 16:25:15 Stevan_White Exp $
#
# Expand MES ranges, as available in CEN documents, into simple list
# of character codes.
# Unicode table
$tblfile = "/usr/local/share/unicode/UnicodeData-Latest.txt";
# Array size
$#table = 65535;
# Read in complete Unicode table for the named entities
open(TABLE, "<$tblfile") || die "Cannot find $tblfile\n";
while (<TABLE>) {
($code,$name) = split(/[;\n]/, $_, 9999);
$table[hex($code)] = $name;
}
close(TABLE);
if ($#ARGV >= 0) {
open(RANGE, $ARGV[0]);
} else {
open(RANGE, "<stdin");
}
while (<RANGE>) {
if (/^\#.*/) {
next;
} else {
($page,$codes) = split(/[\t]/, $_, 9999);
chomp $codes;
@range = split(/ /, $codes, 9999);
for ($i = 0; $i <= $#range; $i++) {
if (length($range[$i]) == 2) {
$code = 256*hex($page) + hex($range[$i]);
printf("%04X:%s\n", $code, $table[$code]);
} else {
($lower,$upper) = split(/-/, $range[$i], 9999);
for ($j = hex($lower); $j <= hex($upper); $j++) {
$code = 256*hex($page) + $j;
printf("%04X:%s\n", $code, $table[$code]);
}
}
}
}
}

View File

@ -0,0 +1,98 @@
#!/usr/bin/env ../utility/fontforge-interp.sh
__license__ = """
This file is part of Gnu FreeFont.
Gnu FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Gnu FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Gnu FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Stevan White"
__email__ = "stevan.white@googlemail.com"
__copyright__ = "Copyright 2009, 2010, 2011 Stevan White"
__date__ = "$Date: 2011-11-27 01:33:15 +0100 (Sun, 27 Nov 2011) $"
__version__ = "$Revision: 1907 $"
__doc__ = """
For most unicode ranges, glyph slot numbers should be the same as the
Unicode value.
The Private Use ranges are the exception: those characters should have a
definate non-Unicode number: -1
This script checks that this is the case, and prints out a warning
whenever it isn't.
"""
import fontforge
import sys
problem = False
def inPrivateUseRange( glyph ):
e = glyph.encoding
return ( ( e >= 0xE800 and e <= 0xF8FF )
or ( e >= 0xFF000 and e <= 0xFFFFD )
or ( e >= 0x100000 and e <= 0x10FFFD ) )
def isSpecialTrueType( glyph ):
""" Fontforge treats three control characters as the special
TrueType characters recommended by that standard
"""
e = glyph.encoding
return e == 0 or e == 1 or e == 0xD
from os import path
def checkGlyphNumbers( fontDir, fontFile ):
if isinstance( fontFile, ( list, tuple ) ):
print "In directory " + fontDir
for fontName in fontFile:
checkGlyphNumbers( fontDir, fontName )
return
print "Checking slot numbers in " + fontFile
font = fontforge.open( path.join( fontDir, fontFile ) )
g = font.selection.all()
g = font.selection.byGlyphs
valid = True
for glyph in g:
if isSpecialTrueType( glyph ):
# FIXME really should complain if it DOESNT exist
pass
elif inPrivateUseRange( glyph ):
if glyph.unicode != -1:
print "Glyph at slot " + str( glyph.encoding ) \
+ " is Private Use but has Unicode"
problem = True
else:
if glyph.encoding != glyph.unicode:
print "Glyph at slot " + str( glyph.encoding ) \
+ " has wrong Unicode"
problem = True
# --------------------------------------------------------------------------
args = sys.argv[1:]
if len( args ) < 1 or len( args[0].strip() ) == 0:
checkGlyphNumbers( '../../sfd/',
( 'FreeSerif.sfd', 'FreeSerifItalic.sfd',
'FreeSerifBold.sfd', 'FreeSerifBoldItalic.sfd',
'FreeSans.sfd', 'FreeSansOblique.sfd',
'FreeSansBold.sfd', 'FreeSansBoldOblique.sfd',
'FreeMono.sfd', 'FreeMonoOblique.sfd',
'FreeMonoBold.sfd', 'FreeMonoBoldOblique.sfd' ) )
else:
checkGlyphNumbers( args[0], args[1:] )
if problem:
sys.exit( 1 )

View File

@ -0,0 +1,63 @@
#!/usr/bin/env ../utility/fontforge-interp.sh
__license__ = """
This file is part of Gnu FreeFont.
Gnu FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Gnu FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Gnu FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Stevan White"
__email__ = "stevan.white@googlemail.com"
__copyright__ = "Copyright 2009, 2010, Stevan White"
__date__ = "$Date: 2011-11-03 01:51:05 +0100 (Thu, 03 Nov 2011) $"
__version__ = "$Revision: 1864 $"
__doc__ = """
Check for glyphs with back layers.
Haven't see this actually work...
"""
import fontforge
from sys import exit
problem = False
def checkBackLayers( fontPath ):
print "Checking " + fontPath
font = fontforge.open( fontPath )
g = font.selection.all()
g = font.selection.byGlyphs
nonzero = 0
for e in g:
if e.layer_cnt != 2:
print e
checkBackLayers( '../sfd/FreeSerif.sfd' )
checkBackLayers( '../sfd/FreeSerifItalic.sfd' )
checkBackLayers( '../sfd/FreeSerifBold.sfd' )
checkBackLayers( '../sfd/FreeSerifBoldItalic.sfd' )
checkBackLayers( '../sfd/FreeSans.sfd' )
checkBackLayers( '../sfd/FreeSansOblique.sfd' )
checkBackLayers( '../sfd/FreeSansBold.sfd' )
checkBackLayers( '../sfd/FreeSansBoldOblique.sfd' )
checkBackLayers( '../sfd/FreeMono.sfd' )
checkBackLayers( '../sfd/FreeMonoOblique.sfd' )
checkBackLayers( '../sfd/FreeMonoBold.sfd' )
checkBackLayers( '../sfd/FreeMonoBoldOblique.sfd' )
if problem:
exit( 0 )
else:
exit( 1 )

94
src/tools/test/isMonoMono.py Executable file
View File

@ -0,0 +1,94 @@
#!/usr/bin/env ../utility/fontforge-interp.sh
__license__ = """
This file is part of Gnu FreeFont.
Gnu FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Gnu FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Gnu FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Stevan White"
__email__ = "stevan.white@googlemail.com"
__copyright__ = "Copyright 2009, 2010, Stevan White"
__date__ = "$Date: 2011-11-03 01:51:05 +0100 (Thu, 03 Nov 2011) $"
__version__ = "$Revision: 1864 $"
__doc__ = """
Diagnostic tool that checks that fonts are really monospace.
Allows characters to have 0 width though (note this is controversial)
Also: in order for box-drawing characters to connect properly, it is
important that the glyphs all lie between 800 and -200EM vertically.
"""
import fontforge
import sys
problem = False
def ismonomono( fontfilename ):
print "Checking character bounding boxes: " + fontfilename
font = fontforge.open( fontfilename )
g = font.selection.all()
g = font.selection.byGlyphs
nonzero = 0
for e in g:
if nonzero == 0:
if e.width > 0:
nonzero = e.width
else:
if e.width > 0 and e.width != nonzero:
print ' ' + e.glyphname \
+ '(' + str( e.encoding ) \
+ ') width is ' + str( e.width ) \
+ ' not ' + str( nonzero )
problem = True
( xmin, ymin, xmax, ymax ) = e.boundingBox()
if ymin < -200 or ymax > 800:
print ' ' + e.glyphname + ' goes between heights ' \
+ str( ymin ) + ' and ' + str( ymax )
"""
For FontForge handling of TrueType/OpenType magic characters:
1) check that 0x0000 0x0001, 0x000D exist and have names
.notdef, .null, nonmarkingreturn
2) check that 0x0000 and 0x000D are width 600, and
0x0001 has no glyph and is width 0
Othewise complain that FontForge may not treat it right.
"""
if not font[0x0000] \
or font[0x0000].glyphname != '.notdef' \
or font[0x0000].width != nonzero:
print 'Should be full-width ".notdef" glyph at 0x0000.'
if not font[0x0001] \
or font[0x0001].glyphname != '.null' \
or font[0x0001].width != 0:
print 'Should be zero-width ".null" glyph at 0x0001.'
if not font[0x000D] \
or font[0x000D].glyphname != 'nonmarkingreturn' \
or font[0x000D].width != nonzero:
print 'Should be full-width "nonmarkingreturn" glyph at 0x000D.'
scriptname = sys.argv[0];
argc = len( sys.argv )
if argc > 1:
for i in range( 1, argc ):
ismonomono( sys.argv[i] )
if problem:
sys.exit( 1 )
else:
sys.exit( 0 )

View File

@ -0,0 +1,310 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
__license__ = """
This file is part of GNU FreeFont.
GNU FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
GNU FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
GNU FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Emmanuel Vallois"
__email__ = "vallois@polytech.unice.fr"
__copyright__ = "Copyright 2011 Emmanuel Vallois"
__date__ = "$Date$"
__version__ = "$Revision$"
__doc__ = """
Writes in the file named by the first argument an HTML page comprising a table
for testing arabic characters, their behavior and consistency with presentation
forms.
Runs under normal Python, version 2.7 or above.
Typical usage:
arabic_test.py "Arabic test page.html"
"""
import sys
from codecs import open
from string import Template
from io import StringIO
from unicodedata import normalize, name, unidata_version, decomposition
_module_missing_msg = """Please run
generate_arabic_shaping.py
to generate
arabic_shaping.py"""
try:
from arabic_shaping import joining_type
except:
print( _module_missing_msg, file=sys.stderr)
sys.exit( 1 )
if len(sys.argv) > 1:
outfile = sys.argv[1]
else:
outfile = 'Arabic test page.html'
sys.stdout = open(outfile, 'w', 'utf-8')
def uniname(char):
return name(char, new_names.get(char, "&lt;reserved-{:04X}&gt;".format(ord(char))))
def non_positional_name(char):
return uniname(char).replace(' INITIAL','').replace(' FINAL','').replace(' MEDIAL','').replace(' ISOLATED','').replace(' FORM','')
arabic_ranges = list(range(0x600, 0x61B + 1))
arabic_ranges.extend(range(0x61E, 0x6FF + 1))
arabic_ranges.extend(range(0x750, 0x77F + 1))
arabic_ranges.extend(range(0x8A0, 0x8B1 + 1))
arabic_ranges.extend(range(0x8E4, 0x8FF + 1))
arabic_ranges.extend(range(0xFB50, 0xFBC1 + 1))
arabic_ranges.extend(range(0xFBD3, 0xFD3F + 1))
arabic_ranges.extend(range(0xFD50, 0xFD8F + 1))
arabic_ranges.extend(range(0xFD92, 0xFDC7 + 1))
arabic_ranges.extend(range(0xFDF0, 0xFDFD + 1))
arabic_ranges.extend(range(0xFE70, 0xFE74 + 1))
arabic_ranges.extend(range(0xFE76, 0xFEFC + 1))
unicode61_new_ranges = [0x604, 0x8A0]
unicode61_new_ranges.extend(range(0x8A2, 0x8AC + 1))
unicode61_new_ranges.extend(range(0x8E4, 0x8FE + 1))
unicode62_new_ranges = [0x605, 0x8A1]
unicode62_new_ranges.extend(range(0x8AD, 0x8B1 + 1))
unicode62_new_ranges.append(0x8FF)
new_names = {}
new_names['\u0604'] = 'ARABIC SIGN SAMVAT'
new_names['\u0605'] = 'ARABIC NUMBER MARK ABOVE'
new_names['\u08A0'] = 'ARABIC LETTER BEH WITH SMALL V BELOW'
new_names['\u08A1'] = 'ARABIC LETTER BEH WITH HAMZA ABOVE'
new_names['\u08A2'] = 'ARABIC LETTER JEEM WITH TWO DOTS ABOVE'
new_names['\u08A3'] = 'ARABIC LETTER TAH WITH TWO DOTS ABOVE'
new_names['\u08A4'] = 'ARABIC LETTER FEH WITH DOT BELOW AND THREE DOTS ABOVE'
new_names['\u08A5'] = 'ARABIC LETTER QAF WITH DOT BELOW'
new_names['\u08A6'] = 'ARABIC LETTER LAM WITH DOUBLE BAR'
new_names['\u08A7'] = 'ARABIC LETTER MEEM WITH THREE DOTS ABOVE'
new_names['\u08A8'] = 'ARABIC LETTER YEH WITH TWO DOTS BELOW AND HAMZA ABOVE'
new_names['\u08A9'] = 'ARABIC LETTER YEH WITH TWO DOTS BELOW AND DOT ABOVE'
new_names['\u08AA'] = 'ARABIC LETTER REH WITH LOOP'
new_names['\u08AB'] = 'ARABIC LETTER WAW WITH DOT WITHIN'
new_names['\u08AC'] = 'ARABIC LETTER ROHINGYA YEH'
new_names['\u08E4'] = 'ARABIC CURLY FATHA'
new_names['\u08E5'] = 'ARABIC CURLY DAMMA'
new_names['\u08E6'] = 'ARABIC CURLY KASRA'
new_names['\u08E7'] = 'ARABIC CURLY FATHATAN'
new_names['\u08E8'] = 'ARABIC CURLY DAMMATAN'
new_names['\u08E9'] = 'ARABIC CURLY KASRATAN'
new_names['\u08EA'] = 'ARABIC TONE ONE DOT ABOVE'
new_names['\u08EB'] = 'ARABIC TONE TWO DOTS ABOVE'
new_names['\u08EC'] = 'ARABIC TONE LOOP ABOVE'
new_names['\u08ED'] = 'ARABIC TONE ONE DOT BELOW'
new_names['\u08EE'] = 'ARABIC TONE TWO DOTS BELOW'
new_names['\u08EF'] = 'ARABIC TONE LOOP BELOW'
new_names['\u08F0'] = 'ARABIC OPEN FATHATAN'
new_names['\u08F1'] = 'ARABIC OPEN DAMMATAN'
new_names['\u08F2'] = 'ARABIC OPEN KASRATAN'
new_names['\u08F3'] = 'ARABIC SMALL HIGH WAW'
new_names['\u08F4'] = 'ARABIC FATHA WITH RING'
new_names['\u08F5'] = 'ARABIC FATHA WITH DOT ABOVE'
new_names['\u08F6'] = 'ARABIC KASRA WITH DOT BELOW'
new_names['\u08F7'] = 'ARABIC LEFT ARROWHEAD ABOVE'
new_names['\u08F8'] = 'ARABIC RIGHT ARROWHEAD ABOVE'
new_names['\u08F9'] = 'ARABIC LEFT ARROWHEAD BELOW'
new_names['\u08FA'] = 'ARABIC RIGHT ARROWHEAD BELOW'
new_names['\u08FB'] = 'ARABIC DOUBLE RIGHT ARROWHEAD ABOVE'
new_names['\u08FC'] = 'ARABIC DOUBLE RIGHT ARROWHEAD ABOVE WITH DOT'
new_names['\u08FD'] = 'ARABIC RIGHT ARROWHEAD ABOVE WITH DOT'
new_names['\u08FE'] = 'ARABIC DAMMA WITH DOT'
new_names['\u08AD'] = 'ARABIC LETTER LOW ALEF'
new_names['\u08AE'] = 'ARABIC LETTER DAL WITH THREE DOTS BELOW'
new_names['\u08AF'] = 'ARABIC LETTER SAD WITH THREE DOTS BELOW'
new_names['\u08B0'] = 'ARABIC LETTER GAF WITH INVERTED STROKE'
new_names['\u08B1'] = 'ARABIC LETTER STRAIGHT WAW'
new_names['\u08FF'] = 'ARABIC MARK SIDEWAYS NOON GHUNNA'
# Unicode 6.0 additions not present in Python 2.7
new_names['\u0620'] = 'ARABIC LETTER KASHMIRI YEH'
new_names['\u065F'] = 'ARABIC WAVY HAMZA BELOW'
new_names['\uFBB2'] = 'ARABIC SYMBOL DOT ABOVE'
new_names['\uFBB3'] = 'ARABIC SYMBOL DOT BELOW'
new_names['\uFBB4'] = 'ARABIC SYMBOL TWO DOTS ABOVE'
new_names['\uFBB5'] = 'ARABIC SYMBOL TWO DOTS BELOW'
new_names['\uFBB6'] = 'ARABIC SYMBOL THREE DOTS ABOVE'
new_names['\uFBB7'] = 'ARABIC SYMBOL THREE DOTS BELOW'
new_names['\uFBB8'] = 'ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS ABOVE'
new_names['\uFBB9'] = 'ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS BELOW'
new_names['\uFBBA'] = 'ARABIC SYMBOL FOUR DOTS ABOVE'
new_names['\uFBBB'] = 'ARABIC SYMBOL FOUR DOTS BELOW'
new_names['\uFBBC'] = 'ARABIC SYMBOL DOUBLE VERTICAL BAR BELOW'
new_names['\uFBBD'] = 'ARABIC SYMBOL TWO DOTS VERTICALLY ABOVE'
new_names['\uFBBE'] = 'ARABIC SYMBOL TWO DOTS VERTICALLY BELOW'
new_names['\uFBBF'] = 'ARABIC SYMBOL RING'
new_names['\uFBC0'] = 'ARABIC SYMBOL SMALL TAH ABOVE'
new_names['\uFBC1'] = 'ARABIC SYMBOL SMALL TAH BELOW'
'''Class Equiv stores the correspondence between a code point and its NFKC-normalized equivalent,
for usual characters it is the character itself, for decomposable characters it is the compatibility
decompostion.'''
class Equiv:
code_point = 0
compat = 0
def __init__(self, code_point, compat):
self.code_point = code_point
self.compat = compat
def sort_key(self):
return '{:02X}'.format(len(self.compat.lstrip(' '))) + self.compat.lstrip(' ')
def __repr__(self):
return 'Equiv(0x{:04X}, compat={})'.format(self.code_point, self.compat)
equivs = []
for cp in arabic_ranges:
normalized = normalize('NFKC', unichr(cp))
equivs.append(Equiv(cp, normalized))
# Sort our characters by length of the decomposition and by decomposition itself
equivs.sort(key=Equiv.sort_key)
#for e in equivs:
# print(e, file=sys.stderr)
contextual_form_formats = { 'isolat':'{}', 'final>':'&zwj;{}', 'medial':'&zwj;{}&zwj;', 'initia':'{}&zwj;' }
contextual_forms = 'isolat', 'final>', 'medial', 'initia'
current_line = {}
equiv = None
char = None
def store_contextual_form():
# print('store_contextual_form', equiv, file=sys.stderr)
compat_disp = equiv.compat
if equiv.compat[0] == ' ': compat_disp = '\u00A0' + compat_disp[1:]
#nonlocal current_line
form_cells = StringIO()
form = decomposition(char)[1:7]
print('<td class="ch">{}{}</td>'.format(contextual_form_formats.get(form, '{}').format(compat_disp),
'<small><br/>{}</small>'.format(ord_mul(compat_disp)) if len(compat_disp) >=2 else ''), file=form_cells)
print('<td class="ch">{}<small><br />{:04X}</small></td>'.format(char, equiv.code_point), file=form_cells)
#if current_line.get(form, 'not found') != 'not found': print('collision', current_line[form].rstrip(), equiv, file=stderr)
current_line[form] = form_cells.getvalue()
form_cells.close()
table_head = '''
<table frame="box" rules="rows">
{}
<colgroup><col/><col/></colgroup>
<colgroup id="characterCols"><col span="2"/><col span="2"/><col span="2"/><col span="2"/></colgroup>
<tr>
<th rowspan="2">General<br />Unicode</th>
<th rowspan="2">Name</th>
<th colspan="8">Contextual Forms</th>
</tr>
<tr><th>Isolated</th><th>Isolated (compat)</th><th>Final</th><th>Final (compat)</th>
<th>Medial</th><th>Medial (compat)</th><th>Initial</th><th>Initial (compat)</th></tr>'''
def print_table():
global current_line, char
def end_line():
for form in contextual_forms:
print(current_line.get(form, '<td colspan="2"></td>').rstrip())
print('</tr>')
current_line.clear()
def print_equiv(equiv):
# print('print_equiv', equiv, file=sys.stderr)
cp = equiv.code_point
char = unichr(cp)
print('<tr{}><td>{}</td>'.format(' class="nextVersion"' if cp in unicode61_new_ranges else ' class="furtherFuture"' if cp in unicode62_new_ranges else '',
'compat' if len(equiv.compat.replace(' ', '')) > 1 else '{:04X}'.format(ord(equiv.compat.lstrip()[0]))))
print('<td>{}</td>'.format(non_positional_name(char)))
if equiv.compat.replace(' ', '') == char: # character is not a decomposable character, or is a standalone combining mark (decomposable to space + combining mark)
i = 0
for form in contextual_forms:
print('<td class="ch">{}</td><td></td>'.format(contextual_form_formats[form].format(char)))
i += 1
if { 'T':'isolat', 'U':'isolat', 'C':'isolat', 'R':'final>', 'D':'' }[joining_type(cp)] == form:
break
if i < 4:
print('<td colspan="{}"></td>'.format((4 - i) * 2))
print('</tr>')
else:
end_line()
print(table_head.format(caption))
last_equiv = None
global equiv
for equiv in equivs:
char = unichr(equiv.code_point)
if last_equiv:
#special case FC03 because there is one set of plain YEH WITH HAMZA ABOVE WITH ALEF MAKSURA and one of 'uighur kirghiz' compatibility ligatures
if equiv.compat.lstrip() == last_equiv.compat.lstrip() and equiv.code_point != 0xFC03:
store_contextual_form()
else:
print_equiv(last_equiv)
if equiv.compat != char:
store_contextual_form()
last_equiv = equiv
print_equiv(last_equiv)
print('</table>')
def ord_mul(s):
code_points = ''
for c in s:
code_points += '{:X} '.format(ord(c))
return code_points[:-1]
html_heading = Template('''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>$title</title>
<style type="text/css">
.captionSquare { float: left; width: 2em; height: 1em; margin-right: 0.5em }
caption { width: 60em; text-align: left }
table { text-align: center; font-family: FreeSerif }
td { padding: 10px }
small { font-size: small }
#characterCols { border-left: medium double black; border-right: medium double black }
.nextVersion { background-color: #CCFF99 }
.furtherFuture { background-color: #FFFFCC }
.name { width: 10em }
.ch { vertical-align: baseline; line-height: 75%; font-size: 250%; width: 1em; direction: rtl }
.empty { background:#EEEEEE }
</style>
</head>
<body>
<h1>$title</h1>
<p>Choose the font to test: <select onchange="changefont(this)"><option>FreeSerif</option><option>FreeSerif, bold</option><option>FreeMono</option></select></p>
<script type="text/javascript">//<![CDATA[
function changefont(select) {
var font = select.options.item(select.selectedIndex).value.split(', ');
var bold = font.length > 1 ? font[1] == 'bold' : false;
font = font[0];
var elementsToStyle = document.getElementsByClassName("ch");
for (i = 0; i < elementsToStyle.length; i++) {
elementsToStyle[i].style.fontFamily = font;
elementsToStyle[i].style.fontWeight = bold ? 'bold' : 'normal';
}
}//]]></script>''')
caption='''<caption><span class="captionSquare nextVersion">&nbsp;</span> New characters in Unicode 6.1, which will be published in February 2012.
These can be relied upon and will not change or be removed. See <a href="http://www.unicode.org/Public/6.1.0/charts/blocks//U08A0.pdf">the
Unicode chart for the new block <b>Arabic Extended-A</b></a>, and for more about these characters, see <a href="http://std.dkuug.dk/JTC1/SC2/WG2/docs/n3734.pdf">N3734</a>
for U+0604, <a href="http://std.dkuug.dk/JTC1/SC2/WG2/docs/n3882.pdf">the complete
proposal</a> for most characters, <a href="http://std.dkuug.dk/JTC1/SC2/WG2/docs/n3791.pdf">N3791</a> for U+08F0-U+08F3.<br/>
<span class="captionSquare furtherFuture">&nbsp;</span> Future new characters in Unicode 6.2. These can will probably be standardized this way,
but could in principle still change or be removed. See <a href="http://std.dkuug.dk/JTC1/SC2/WG2/docs/n3990.pdf">N3990, in 4.2 Orthography</a> for U+0605,
<a href="http://std.dkuug.dk/JTC1/SC2/WG2/docs/n4072.pdf">N4072 proposal</a> about U+08AD-U+08B1, and
<a href="http://std.dkuug.dk/JTC1/SC2/WG2/docs/n3989.pdf">N3989 proposal</a> about U+08FF.</caption>'''
def print_arabic_test_page():
print(html_heading.substitute(title='Test for Unicode Arabic range'))
print_table()
print('</body>')
print('</html>')
print_arabic_test_page()

View File

@ -0,0 +1,81 @@
#!/usr/bin/python
from __future__ import print_function
__license__ = """
This file is part of Gnu FreeFont.
Gnu FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Gnu FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Gnu FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Emmanuel Vallois"
__email__ = "vallois@polytech.unice.fr"
__copyright__ = "Copyright 2011 Emmanuel Vallois"
__date__ = "$Date$"
__version__ = "$Revision$"
__doc__ = """
Generates test script
arab_shaping.py
from a file
ArabicShaping.txt
which may be obtained from
http://www.unicode.org/Public/UNIDATA/ArabicShaping.txt
"""
'''Convert Unicode ArabicShaping.txt to a Python module containing its data.'''
import sys
sys.stdout = open('arabic_shaping.py', 'w')
print('''#!/usr/bin/python
__license__ = """''' + __license__ + '''
"""
__doc__ = """
Module containing UCD ArabicShaping.txt data."""
from unicodedata import name
from collections import OrderedDict
class ArabicShaping:
def __init__(self, code_point, short_name, joining_type, joining_group):
self.code_point = code_point
self.short_name = short_name
self.joining_type = joining_type
self.joining_group = joining_group
def __repr__(self):
return 'ArabicShaping({:X}, {}, {}, {})'.format(self.code_point, self.short_name, self.joining_type, self.joining_group)
arabic_shapings = OrderedDict()''')
with open('ArabicShaping.txt') as f:
for line in f:
if not line.strip() or line[0] == '#': continue
line = line[:-1] #removes the \n at the end of the line
fields = line.split('; ')
print("arabic_shapings[0x{0[0]}] = ArabicShaping(0x{0[0]}, '{0[1]}', '{0[2]}', '{0[3]}')".format(fields))
if fields[0] == '08A0':
print('''arabic_shapings[0x08A1] = ArabicShaping(0x8A1, 'BEH WITH HAMZA ABOVE','D','BEH')''')
print('''arabic_shapings[0x08AE] = ArabicShaping(0x8AE, 'DAL WITH THREE DOTS BELOW', 'R', 'DAL')
arabic_shapings[0x08AF] = ArabicShaping(0x8AF, 'SAD WITH THREE DOTS BELOW', 'D', 'SAD')
arabic_shapings[0x08B0] = ArabicShaping(0x8B0, 'GAF WITH INVERTED STROKE', 'D', 'GAF')
arabic_shapings[0x08B1] = ArabicShaping(0x8B1, 'STRAIGHT WAW', 'R', 'WAW')''')
print('''
def short_name(cp):
shaping = arabic_shapings.get(cp)
return shaping and shaping.short_name or name(unichr(cp))
def joining_type(cp):
shaping = arabic_shapings.get(cp)
return shaping and shaping.joining_type or 'U'
def joining_group(cp):
shaping = arabic_shapings.get(cp)
return shaping and shaping.joining_group or 'No_Joining_Group\'''')

View File

@ -0,0 +1,207 @@
#!/usr/bin/python
from __future__ import print_function, unicode_literals
__license__ = """
This file is part of GNU FreeFont.
GNU FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
GNU FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
GNU FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Emmanuel Vallois"
__email__ = "vallois@polytech.unice.fr"
__copyright__ = "Copyright 2011 Emmanuel Vallois"
__date__ = "$Date$"
__version__ = "$Revision$"
__doc__ = """
Writes in the file named by the first argument an HTML page comprising a table
for testing joining cursive script characters.
Runs under normal Python, version 2.7 or above.
Typical usage:
unicode_joining.py "Unicode joining test page.html"
"""
import sys
from codecs import open
from string import Template
from collections import OrderedDict
from itertools import chain
_module_missing_msg = """Please run
generate_arabic_shaping.py
to generate
arabic_shaping.py"""
try:
from arabic_shaping import arabic_shapings, joining_type
except:
print( _module_missing_msg, file=sys.stderr)
sys.exit( 1 )
if len(sys.argv) > 1:
outfile = sys.argv[1]
else:
outfile = 'Unicode joining test page.html'
sys.stdout = open(outfile, 'w', 'utf-8')
class OrderedDefaultDict(OrderedDict):
def __missing__(self, key):
self[key] = rv = []
return rv
def move_to_end(self, key):
tmp = self[key]
del self[key]
self[key] = tmp
arabic_ranges = tuple(chain(range(0x600, 0x6FF +1), range(0x750, 0x77F +1), range(0x8A0, 0x8FF)))
unicode61_new_ranges = [0x604, 0x8A0]
unicode61_new_ranges.extend(range(0x8A2, 0x8AC + 1))
unicode61_new_ranges.extend(range(0x8E4, 0x8FE + 1))
unicode62_new_ranges = [0x605, 0x8A1]
unicode62_new_ranges.extend(range(0x8AD, 0x8B1 + 1))
unicode62_new_ranges.append(0x8FF)
shapings = filter(lambda s: s.joining_type in 'RD' and (s.joining_group != 'No_Joining_Group' or s.code_point not in arabic_ranges), arabic_shapings.values())
jg_shapings_arabic = OrderedDefaultDict()
jg_shapings_other_scripts = OrderedDefaultDict()
for s in shapings:
if s.code_point in arabic_ranges:
jg_shapings_arabic[s.joining_group].append(s)
else:
jg_shapings_other_scripts[s.joining_group].append(s)
if s.code_point == 0x62B:
jg_shapings_arabic.move_to_end('TEH MARBUTA')
jg_shapings_arabic['TEH MARBUTA GOAL']
elif s.code_point == 0x642:
jg_shapings_arabic.move_to_end('GAF')
jg_shapings_arabic['SWASH KAF']
elif s.code_point == 0x646:
jg_shapings_arabic['NYA']
elif s.code_point == 0x647:
jg_shapings_arabic['KNOTTED HEH']
jg_shapings_arabic['HEH GOAL']
elif s.code_point == 0x64A:
jg_shapings_arabic.move_to_end('FARSI YEH')
elif s.code_point in chain(range(0x627, 0x63A + 1), range(0x641, 0x64A + 1)):
jg_shapings_arabic.move_to_end(s.joining_group)
#for jg, ls in jg_shapings_arabic.items():
# for s in ls:
# print(jg, ls, file=sys.stderr)
table_head = '''
<table frame="box" rules="rows">
{}
<colgroup><col/><col/><col/></colgroup>
<colgroup id="characterCols"><col/><col/><col/><col/></colgroup>
<colgroup><col/></colgroup>'''
table_internal_title = '''<tr><td colspan="8"><h2>{}</h2></td></tr>
<tr>
<th rowspan="2">Joining Group</th>
<th rowspan="2">Code Point</th>
<th rowspan="2">Short Name</th>
<th colspan="5">Contextual Forms</th>
</tr>
<tr><th>Isolated</th><th>Final</th><th>Medial</th><th>Initial</th><th>Joined</th></tr>'''
def print_table():
contextual_form_formats = { 'isolat':'{}', 'final>':'&zwj;{}', 'medial':'&zwj;{}&zwj;', 'initia':'{}&zwj;' }
contextual_forms = 'isolat', 'final>', 'medial', 'initia'
def print_shaping(shaping, rowspan):
# print('print_shaping', shaping, file=sys.stderr)
cp = shaping.code_point
char = unichr(cp)
print('<tr{}>'.format(' class="nextVersion"' if cp in unicode61_new_ranges else ' class="furtherFuture"' if cp in unicode62_new_ranges else ''))
if rowspan: print('<td rowspan="{}">{}</td>'.format(rowspan, shaping.joining_group))
print('<td>{:04X}</td>'.format(cp))
print('<td>{}</td>'.format(shaping.short_name))
i = 0
for form in contextual_forms:
print('<td class="ch">{}</td>'.format(contextual_form_formats[form].format(char)))
i += 1
if { 'R':'final>', 'D':'' }[joining_type(cp)] == form:
break
if i < 4:
print('<td colspan="{}"></td>'.format(4 - i))
print('<td class="ch">{}</td>'.format('\u0640' * (4 - i) + char * (i - 1) + ' ' + char))
print('</tr>')
print(table_head.format(caption))
print(table_internal_title.format('Arabic'))
for shaping_list in jg_shapings_arabic.values():
rowspan = len(shaping_list)
for shaping in shaping_list:
print_shaping(shaping, rowspan)
rowspan = None
print(table_internal_title.format('Syriac, Nko and Mandaic'))
for shaping_list in jg_shapings_other_scripts.values():
rowspan = len(shaping_list)
for shaping in shaping_list:
print_shaping(shaping, rowspan)
rowspan = None
print('</table>')
html_heading = Template('''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>$title</title>
<style type="text/css">
.captionSquare { float: left; width: 2em; height: 1em; margin-right: 0.5em }
caption { width: 60em; text-align: left }
table { text-align: center; font-family: FreeSerif, FreeSans }
td { padding: 10px }
small { font-size: small }
#characterCols { border-left: medium double black; border-right: medium double black }
.nextVersion { background-color: #CCFF99 }
.furtherFuture { background-color: #FFFFCC }
.name { width: 10em }
.ch { vertical-align: baseline; line-height: 75%; font-size: 250%; direction: rtl }
.empty { background:#EEEEEE }
</style>
</head>
<body>
<h1>$title</h1>
<p>Choose the font to test: <select onchange="changefont(this)"><option>FreeSerif</option><option>FreeSerif, bold</option><option>FreeSans</option><option>FreeMono</option></select></p>
<script type="text/javascript">//<![CDATA[
function changefont(select) {
var font = select.options.item(select.selectedIndex).value.split(', ');
var bold = font.length > 1 ? font[1] == 'bold' : false;
font = font[0];
var elementsToStyle = document.getElementsByClassName("ch");
for (i = 0; i < elementsToStyle.length; i++) {
elementsToStyle[i].style.fontFamily = font;
elementsToStyle[i].style.fontWeight = bold ? 'bold' : 'normal';
}
}//]]></script>''')
caption='''<caption><span class="captionSquare nextVersion">&nbsp;</span> New characters in Unicode 6.1, which will be published in February 2012.
These can be relied upon and will not change or be removed. See <a href="http://www.unicode.org/Public/6.1.0/charts/blocks//U08A0.pdf">the
Unicode chart for the new block <b>Arabic Extended-A</b></a>, and for more about these characters, see <a href="http://std.dkuug.dk/JTC1/SC2/WG2/docs/n3734.pdf">N3734</a>
for U+0604, <a href="http://std.dkuug.dk/JTC1/SC2/WG2/docs/n3882.pdf">the complete
proposal</a> for most characters, <a href="http://std.dkuug.dk/JTC1/SC2/WG2/docs/n3791.pdf">N3791</a> for U+08F0-U+08F3.<br/>
<span class="captionSquare furtherFuture">&nbsp;</span> Future new characters in Unicode 6.2. These can will probably be standardized this way,
but could in principle still change or be removed. See <a href="http://std.dkuug.dk/JTC1/SC2/WG2/docs/n3990.pdf">N3990, in 4.2 Orthography</a> for U+0605,
<a href="http://std.dkuug.dk/JTC1/SC2/WG2/docs/n4072.pdf">N4072 proposal</a> about U+08AD-U+08B1, and
<a href="http://std.dkuug.dk/JTC1/SC2/WG2/docs/n3989.pdf">N3989 proposal</a> about U+08FF.</caption>'''
def print_arabic_test_page():
print(html_heading.substitute(title='Test of Joining Characters From Unicode Cursive Scripts'))
print_table()
print('</body>')
print('</html>')
print_arabic_test_page()

146
src/tools/test/validate.py Executable file
View File

@ -0,0 +1,146 @@
#!/usr/bin/env ../utility/fontforge-interp.sh
__license__ = """
This file is part of Gnu FreeFont.
Gnu FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Gnu FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Gnu FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Stevan White"
__email__ = "stevan.white@googlemail.com"
__copyright__ = "Copyright 2009, 2010, Stevan White"
__date__ = "$Date: 2010-09-14 13:02:02 $"
__version__ = "$Revision: 1.5 $"
__doc__ = """
Runs the FontForge validate function on all the font faces.
Prints report on standard output.
Returns 1 if problems found 0 otherwise.
"""
import fontforge
import sys
problem = False
""" Haven't really figured out why TT limit warniings are turndd on,
or where the limits are set.
"""
def countPointsInLayer( layer ):
problem = True
p = 0
for c in layer:
p += len( c )
return p
def printProblemLine( e, msg ):
print "\t" + e.glyphname + msg
def dealWithValidationState( state, e ):
if state & 0x2:
printProblemLine( e, " has open contour" )
if state & 0x4:
printProblemLine( e, " intersects itself" )
if state & 0x8:
printProblemLine( e, " is drawn in wrong direction" )
if state & 0x10:
printProblemLine( e, " has a flipped reference" )
if state & 0x20:
printProblemLine( e, " is missing extrema" )
if state & 0x40:
printProblemLine( e, " is missing a reference in a table" )
if state & 0x80:
printProblemLine( e, " has more than 1500 pts" )
if state & 0x100:
printProblemLine( e, " has more than 96 hints" )
if state & 0x200:
printProblemLine( e, " has invalid PS name" )
"""
# Not meaningfully set for non-TrueType fonts )
if state & 0x400:
printProblemLine( e, " has more points than allowed by TT: " + str( countPointsInLayer( e.layers[1] ) ) )
if state & 0x800:
printProblemLine( e, " has more paths than allowed by TT" )
if state & 0x1000:
printProblemLine( e, " has more points in composite than allowed by TT" )
if state & 0x2000:
printProblemLine( e, " has more paths in composite than allowed by TT" )
if state & 0x4000:
printProblemLine( e, " has instruction longer than allowed" )
if state & 0x8000:
printProblemLine( e, " has more references than allowed" )
if state & 0x10000:
printProblemLine( e, " has references deeper than allowed" )
if state & 0x20000:
print e.glyphname + " fpgm or prep tables longer than allowed" )
"""
def validate( dir, fontFile ):
try:
font = fontforge.open( dir + fontFile )
print "Validating " + fontFile
g = font.selection.all()
g = font.selection.byGlyphs
valid = True
for e in g:
state = e.validate()
if state != 0:
dealWithValidationState( state, e )
font.validate
except Exception, e:
problem = True
print >> sys.stderr, str( e )
validate( '../sfd/', 'FreeSerif.sfd' )
validate( '../sfd/', 'FreeSerifItalic.sfd' )
validate( '../sfd/', 'FreeSerifBold.sfd' )
validate( '../sfd/', 'FreeSerifBoldItalic.sfd' )
validate( '../sfd/', 'FreeSans.sfd' )
validate( '../sfd/', 'FreeSansOblique.sfd' )
validate( '../sfd/', 'FreeSansBold.sfd' )
validate( '../sfd/', 'FreeSansBoldOblique.sfd' )
validate( '../sfd/', 'FreeMono.sfd' )
validate( '../sfd/', 'FreeMonoOblique.sfd' )
validate( '../sfd/', 'FreeMonoBold.sfd' )
validate( '../sfd/', 'FreeMonoBoldOblique.sfd' )
validate( '../sfd/', 'FreeSerif.ttf' )
validate( '../sfd/', 'FreeSerifItalic.ttf' )
validate( '../sfd/', 'FreeSerifBold.ttf' )
validate( '../sfd/', 'FreeSerifBoldItalic.ttf' )
validate( '../sfd/', 'FreeSans.ttf' )
validate( '../sfd/', 'FreeSansOblique.ttf' )
validate( '../sfd/', 'FreeSansBold.ttf' )
validate( '../sfd/', 'FreeSansBoldOblique.ttf' )
validate( '../sfd/', 'FreeMono.ttf' )
validate( '../sfd/', 'FreeMonoOblique.ttf' )
validate( '../sfd/', 'FreeMonoBold.ttf' )
validate( '../sfd/', 'FreeMonoBoldOblique.ttf' )
validate( '../sfd/', 'FreeSerif.otf' )
validate( '../sfd/', 'FreeSerifItalic.otf' )
validate( '../sfd/', 'FreeSerifBold.otf' )
validate( '../sfd/', 'FreeSerifBoldItalic.otf' )
validate( '../sfd/', 'FreeSans.otf' )
validate( '../sfd/', 'FreeSansOblique.otf' )
validate( '../sfd/', 'FreeSansBold.otf' )
validate( '../sfd/', 'FreeSansBoldOblique.otf' )
validate( '../sfd/', 'FreeMono.otf' )
validate( '../sfd/', 'FreeMonoOblique.otf' )
validate( '../sfd/', 'FreeMonoBold.otf' )
validate( '../sfd/', 'FreeMonoBoldOblique.otf' )
if problem:
sys.exit( 1 )

View File

@ -0,0 +1,117 @@
#!/usr/bin/perl
=pod
=head1 KerningNumerals.pl
Move kerning information from ASCII numerals (U+0030...) to characters in
the Adobe corporate use area (U+F6xx).
By: Primož Peterlin, 2003
$Id: KerningNumerals.pl,v 1.2 2003-05-15 12:04:41 peterlin Exp $
=cut
sub numerically { $a <=> $b; }
if ($#ARGV != 0) {
print $#ARGV;
die "Usage: $0 file.sfd\n";
}
open(INFILE, $ARGV[0]) || die "Failed to open file: $ARGV[0]\n";
while (<INFILE>) {
if (/^Kerns:/) {
# Old-style kerning information
chomp;
# Cut off the first seven characters ("Kerns: ")
substr($_,0,7) = "";
@values = split;
# Construct the hash $kern{$code}
for ($i = 0; $i <= $#values; $i += 2) {
$code = $values[$i];
# Recode ASCII numerals to Adobe corporate use values
if ($code == 48) {
$code = 63033;
} elsif ($code == 49) {
$code = 63196;
} elsif ($code == 50) {
$code = 63034;
} elsif ($code == 51) {
$code = 63035;
} elsif ($code == 52) {
$code = 63036;
} elsif ($code == 53) {
$code = 63037;
} elsif ($code == 54) {
$code = 63038;
} elsif ($code == 55) {
$code = 63039;
} elsif ($code == 56) {
$code = 63040;
} elsif ($code == 57) {
$code = 63041;
}
$kern{$code} = $values[$i+1];
}
print "Kerns:";
foreach $code (sort numerically keys(%kern)) {
print " ",$code," ",$kern{$code};
}
print "\n";
# Clean-up
foreach $code (keys(%kern)) {
delete $kern{$code};
}
} elsif (/^KernsSLIF:/) {
# New-style kerning information
chomp;
# Cut off the first eleven characters ("KernsSLIF: ")
substr($_,0,11) = "";
@values = split;
# Construct the hash $kern{$code}
for ($i = 0; $i <= $#values; $i += 4) {
$code = $values[$i];
# Recode ASCII numerals to Adobe corporate use values
if ($code == 48) {
$code = 63033;
} elsif ($code == 49) {
$code = 63196;
} elsif ($code == 50) {
$code = 63034;
} elsif ($code == 51) {
$code = 63035;
} elsif ($code == 52) {
$code = 63036;
} elsif ($code == 53) {
$code = 63037;
} elsif ($code == 54) {
$code = 63038;
} elsif ($code == 55) {
$code = 63039;
} elsif ($code == 56) {
$code = 63040;
} elsif ($code == 57) {
$code = 63041;
}
$kern{$code} = $values[$i+1];
$unx{$code} = $values[$i+2];
$uny{$code} = $values[$i+3];
}
print "KernsSLIF:";
foreach $code (sort numerically keys(%kern)) {
print " ",$code," ",$kern{$code}," ",$unx{$code}," ",$uny{$code};
}
print "\n";
# Clean-up
foreach $code (keys(%kern)) {
delete $kern{$code};
}
} else {
# All other lines
print;
}
}
close(INFILE);

View File

@ -0,0 +1,9 @@
# fontforge as a script interpreter.
#
# Exists because
# * It is desirable to launch fontforge scripts as executables.
# * The usual #! interpreter-calling mechanism needs an explicit path,
# but custom-installed fontforge should be in a non-distro location.
# * Linux /usr/bin/env won't allow arguments such as -script.
/usr/bin/fontforge -script $@

View File

@ -0,0 +1,83 @@
# This is an RPM 'spec' file, for use with the Redhat Package Manager
# to make packages for that distribution.
%define fontdir %{_datadir}/fonts/freefont
Name: freefont-ttf
Version: 20051206
Release: 1.pingo.1
Summary: FreeFonts
Group: User Interface/X
License: GPL
URL: http://www.nongnu.org/freefont/
Source: freefont-ttf-%{version}.tar
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
BuildArch: noarch
Requires: fontconfig
%description
Freefonts aim to provide a set of free high-quality outline (OpenType,
Truetype, Type 0) UCS fonts, under GNU GPL license.
All the fonts conform to MES-1 (Minimum European Subset) of
Unicode/ISO 10646.
%prep
%setup
%build
%install
/bin/rm -rf $RPM_BUILD_ROOT
#fonts
install -d -m 0755 $RPM_BUILD_ROOT%{fontdir}
install -m 0644 *.ttf $RPM_BUILD_ROOT%{fontdir}
cd ..
# "touch" all files we've got flagged as %ghost but which are not
# present in the RPM_BUILD_ROOT when RPM looks for files
/bin/touch $RPM_BUILD_ROOT%{fontdir}/fonts.cache-1
%clean
/bin/rm -rf $RPM_BUILD_ROOT
%post
if [ -x %{_bindir}/fc-cache ] ; then
%{_bindir}/fc-cache %{_datadir}/fonts ;
fi
%postun
if [ "$1" = "0" ]; then
if [ -x %{_bindir}/fc-cache ] ; then
%{_bindir}/fc-cache %{_datadir}/fonts ;
fi
fi
%files
%defattr(0644,root,root,0755)
%doc README
%doc AUTHORS
%doc CREDITS
%doc COPYING
%doc ChangeLog
%dir %{fontdir}
%{fontdir}/*.ttf
%ghost %{fontdir}/fonts.cache-1
%changelog
* Fri Dec 9 2005 Primoz Peterlin <primoz.peterlin@biofiz.mf.uni-lj.si> 20051206-1.pingo.1
- renamed to freefont-ttf
* Tue Dec 06 2005 Rok Papez <rok.papez@lugos.si> 20051206-1.pingo.1
- Updated fonts to version 2005-12-06
* Fri Sep 09 2005 Rok Papez <rok.papez@lugos.si> 20050407-1.pingo.1
- Updated fonts to version 2005-04-07
- Rebuild for Fedora Core 4 / Pingo 4.0
* Sun Oct 06 2003 Rok Papez <rok.papez@lugos.si> 1.0-1
- Created the first release

67
src/tools/utility/hex_range.py Executable file
View File

@ -0,0 +1,67 @@
#!/usr/bin/env python
__license__ = """
This file is part of Gnu FreeFont.
Gnu FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Gnu FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Gnu FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Stevan White"
__email__ = "stevan.white@googlemail.com"
__copyright__ = "Copyright 2009, 2010, 2011 Stevan White"
__date__ = "$Date: 2011-09-13 13:05:59 +0200 (Tue, 13 Sep 2011) $"
__version__ = "$Revision: 1704 $"
__doc__ = """Sends to standard output a range of hex values formatted
for e.g. HTML.
Takes one or two numerical arguments. With one argument the output
is just the formatted value of the argument.
"""
import sys
# Python Unicode prefix
prefix = '\\u'
postfix = ''
# General Unicode prefix
prefix = 'U+'
postfix = ''
# HTML Entity
prefix = '&#x'
postfix = ';'
def explain_error_and_quit( e ):
if e:
print 'Error: ', e
print "Usage:"
print " hex_range num1 [num2]"
exit( 1 )
def print_formatted_hex_value( n ):
print '%s%0.4x%s' %( prefix, n, postfix )
if len( sys.argv ) == 3:
try:
a = int( sys.argv[1], 0 )
b = int( sys.argv[2], 0 )
for i in xrange( a, b + 1 ):
print_formatted_hex_value( i )
except ValueError, e:
explain_error_and_quit( e )
elif len( sys.argv ) == 2:
try:
a = int( sys.argv[1], 0 )
print_formatted_hex_value( a )
except ValueError, e:
explain_error_and_quit( e )
else:
explain_error_and_quit()

View File

@ -0,0 +1,72 @@
#!/usr/bin/fontforge -script
"""
For use on Metafont fonts.
To import glyphs each in individual .eps files into an empty font file.
First, process with 'mpost'. Procedure is:
1) Make sure you have an mfplain mem file for mpost. It may come with
the distro, but it is possible also to generate it.
I found an mfplain.mp file somewhere. Use it to make an mfplain.mem.
mpost -ini '\input mfplain.mp; dump'
2) Generate .eps files from a .mf file such as skt10.mf
mpost '&./mfplain \mag=1; truecorners:=0; filenametemplate "%j-%4c.eps"; input skt10.mf'
A bunch of eps files should result, with names like
skt10-012.eps
3) Use FontForge to make an empty font file, with a name like SKT.sfd
4) Run this script on the eps files like so
freefont/tools/metafont/bulk_eps_import.py SKT.sfd skt10
Then clean up clean up clean up.
"""
__author__ = "Stevan White"
__email__ = "stevan.white@googlemail.com"
__copyright__ = "Copyright 2008, 2011, Stevan White"
__date__ = "$Date: 2011-09-12 14:25:06 +0200 (Mon, 12 Sep 2011) $"
__version__ = "$Revision: 1694 $"
import fontforge
import sys, os
import fnmatch, re
problem = False
def import_glyph( font, name, chrnum ):
print "importing file: " + name + " to slot " + str( chrnum )
g = font.createChar( chrnum )
print "importing outlines " + name
g.importOutlines( name )
# The glyphs produced by MetaPost usually have a grid, whose
# right side seems to correspond to the proper right side bearing
xmax = g.layers[1].boundingBox()[2]
g.right_side_bearing = max( xmax, 0 )
scriptname = sys.argv[0];
argc = len( sys.argv )
file_pat = r'([A-Za-z0-9]*)-(\d{3,4}).eps'
file_pat = sys.argv[2] + r'-(\d{3,4}).eps'
re_file_pat = re.compile( file_pat )
if argc > 2:
fontfilename = sys.argv[1]
font = fontforge.open( fontfilename )
print "bulk importing to font file: " + fontfilename
chrnum = 0
directories = os.listdir('.')
directories.sort()
for file in directories:
matches = re_file_pat.match( file )
if matches:
chrnum = int( matches.group(1) )
import_glyph( font, file, chrnum )
font.save()
font.close()
sys.exit( int( problem ) )

View File

@ -0,0 +1,80 @@
__license__ = """
This file is part of Gnu FreeFont.
Gnu FreeFont is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Gnu FreeFont is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Gnu FreeFont. If not, see <http://www.gnu.org/licenses/>.
"""
__author__ = "Stevan White"
__email__ = "stevan.white@googlemail.com"
__copyright__ = "Copyright 2010, Stevan White"
__date__ = "$Date: 2010/09/18 08:50:42 $"
__version__ = "$Revision: 1.6 $"
import fontforge
import psMat
from sys import stdout
__doc__ = """
Replaces the Braille Pattern range in a font. There must already be
characters defined there.
Two auxiliar glyphs, in variables glyphOff and glyphOn below, represent the
off and on state of the Braille dots, respectively.
One also needs to set the font file path, the width between columns of dots,
and the width between rows of dots, as well as the width of the glyphs.
The first 64 Braille Patterns consist of two columns of four dots,
the bottom two of which are all zero. The other 6 dots are represented
by the bit patterns of the octal digits of the offset from the range start.
The remaining three sets of 64 patterns repeat the first set, with
the bottom two dots being the bit pattern for the numbers 1 to 4 in binary.
"""
font = fontforge.open( '../../sfd/FreeMono.sfd' )
glyphOff = 'braille_off'
glyphOn = 'braille_on'
colwidth = 220
rowheight = -220
glyphwidth = 600
def drawdot( g, col, row, on ):
move = psMat.translate( col * colwidth, row * rowheight )
if on:
g.addReference( glyphOn, move )
else:
g.addReference( glyphOff, move )
def createAndName( font, off ):
return font.createChar( 0x2800 + off, 'braille%0.2X' % off )
def drawtopsix( g, off ):
print 'created', 'braille%0.2X' % off
g.clear()
g.right_side_bearing = glyphwidth
for col in range ( 0, 2 ):
for row in range ( 0, 3 ):
print 'shift', ( 3 * col + row )
state = ( 1 << ( 3 * col + row ) ) & off
drawdot( g, col, row, state )
# Contrary to the FontForge docs, font.createChar does *not* create a
# glyph if one doesn't exist, but *does* re-name it if it already exists.
for off in range ( 0, 0x0100 ):
g = createAndName( font, off )
drawtopsix( g, off )
drawdot( g, 0, 3, ( off / 0x40 ) % 2 != 0 )
drawdot( g, 1, 3, off / 0x80 != 0 )
font.save()