changeset 1505:842c29861e25

upgraded to 1.0b version by Artur Zaprzala <artur.zaprzala@talex.com.pl>
author arpi
date Mon, 13 Aug 2001 18:37:10 +0000
parents f4f686aed404
children 94d929f91b06
files TOOLS/subfont-c/Makefile TOOLS/subfont-c/README TOOLS/subfont-c/encodings/charmap2enc TOOLS/subfont-c/encodings/osd-mplayer TOOLS/subfont-c/encodings/runme-kr TOOLS/subfont-c/osd/README TOOLS/subfont-c/osd/gen.py TOOLS/subfont-c/osd/osd.t1a TOOLS/subfont-c/osd/runme TOOLS/subfont-c/runme TOOLS/subfont-c/subfont.c
diffstat 11 files changed, 1591 insertions(+), 284 deletions(-) [+]
line wrap: on
line diff
--- a/TOOLS/subfont-c/Makefile	Mon Aug 13 13:12:49 2001 +0000
+++ b/TOOLS/subfont-c/Makefile	Mon Aug 13 18:37:10 2001 +0000
@@ -1,24 +1,18 @@
-#font="/mnt/win/windows/fonts/arial.ttf"
-#font="/mnt/win/windows/fonts/comic.ttf"
-#font="/mnt/win/windows/fonts/verdanai.ttf"
-font="/mnt/win/windows/fonts/verdana.ttf"
-
-#encoding=windows-1250
-encoding=iso-8859-2
-
-fontsize=20
 
 include ../../config.mak
 
 LDLIBS=-lm $(shell freetype-config --libs)
 CFLAGS=$(OPTFLAGS) $(shell freetype-config --cflags)
 
+#CFLAGS+=-DOLD_FREETYPE2
+#CFLAGS+=-g
+#CFLAGS+=-DDEBUG
+
+
 subfont:	subfont.o
 
-run:	subfont
-	./subfont $(encoding) $(fontsize) $(font)
-	cat font.desc.tail >> font.desc
-	cp font.desc *.raw ~/.mplayer/font/
+subfont.S:	subfont.c
+	$(CC) $(CFLAGS) -S $^ -o $@
 
 clean:
-	rm -f subfont subfont.o
+	rm -f subfont subfont.o core
--- a/TOOLS/subfont-c/README	Mon Aug 13 13:12:49 2001 +0000
+++ b/TOOLS/subfont-c/README	Mon Aug 13 18:37:10 2001 +0000
@@ -1,41 +1,62 @@
-About:
-~~~~~~
-`subfont' program renders antialiased fonts for mplayer using freetype library.
-Should work with TrueType, Type1 and any other font supported by libfreetype.
-
-Goals:
- - internationalization: supports any 8 bit encoding (uses iconv).
- - nice look: creates glyph `shadows' using algorithm derived from gaussian blur (slow!).
-
-
-Note:
-~~~~~
-Starting x position of each char and the bitmap width is aligned to multiple of 8
-(required for under-development MMX renderer).
-
-
 Usage:
 ~~~~~~
-Usage: subfont encoding ppem font [alphaFactor [minAlpha [radius]]]
-  Program creates 3 files: font.desc, <encoding>-a.raw, <encoding>-b.raw.
-  You should append font.desc.tail (desc for OSD characters by a'rpi & chass) to font.desc,
-  and copy font.desc and all *.raw files to ~/.mplayer/font/ directory.
-
-  encoding     must be 8 bit encoding, like iso-8859-2.
-               To list encodings available on your system use iconv -l.
-  ppem         Font size in pixels (e.g. 24).
-  font         Font file path. Any format supported by freetype library (*.ttf, *.pf?, *).
-  alphaFactor  Alpha map scaling factor (default is 1.0), float.
-  minAlpha     Alpha map minimum value (default is 1.0, max is 255), float.
-  radius       Alpha map blur radius (default is 6 pixels), integer.
+1. Make sure you have FreeType 2 installed.
+2. Get a TrueType or Type 1 font.
+3. Modify `runme' script for your encoding and font path.
+4. Type: ./runme
+5. Copy *.raw and font.desc files to ~/.mplayer/font/
+6. Run subfont alone to see more options.
 
 
-Example:
-~~~~~~~~
-make
-./subfont iso-8859-2 20 verdana.ttf
-cat font.desc.tail >> font.desc
-cp font.desc *.raw ~/.mplayer/font/
+About:
+~~~~~~
+`subfont' program renders antialiased OSD and subtitle fonts for mplayer.
+
+What you get are bitmap and alpha *.raw files and a font.desc.
+What you need is TrueType, Type 1 or any other font supported by FreeType.
+
+Alpha channel is created using outline and Gaussian blur filters.
+
+ANY encoding is now supported! That is, all 8-bit encodings known by libc
+and user-supplied encodings (also multibyte) through custom encoding files.
+
+I prepared also Type 1 font `osd.pfb' for OSD characters based on bitmaps
+created by chass.
+
+Subfont was tested with Korean fonts from truetype-fonts-ko-2.0-1k.noarch.rpm
+I found on http://rpmfind.net/ and euc-kr encoding.  Custom encoding file
+for euc-kr was generated from charmap I found in /usr/share/i18n/charmaps/EUC-KR.gz
+(glibc package).  This should work with -unicode switch for mplayer
+(though it is not Unicode encoding).
+It took about 14 seconds to render over 8000 characters on P3 @ 600MHz.
+
+
+Custom encodings:
+~~~~~~~~~~~~~~~~~
+For each character you want to render write the line consisting of:
+ hexadecimal Unicode character code,
+ followed by whitespace,
+ followed by hexadecimal number representing your encoding,
+ followed by new line character.
+
+Example: to render a single letter `aogonek' (Unicode 0x0105) and encode
+it using iso-8859-2 encoding (0xB1), your custom encoding file will consist
+of a sigle line:
+0105 B1
+
+
+Notes:
+~~~~~~
+  + Starting x position of each character and the bitmap width is aligned
+to multiple of 8 (required by mplayer).
+
+  + Currently subfont won't work on big-endian systems.
+
+  + My development platform is RedHat 7.1.  FreeType versions tested are
+2.0.1 through 2.0.4.
+
+  + FreeType library has a bug that makes subfont display some warning message
+about Unicode charmap for osd.pfb.
 
 
 Author:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TOOLS/subfont-c/encodings/charmap2enc	Mon Aug 13 18:37:10 2001 +0000
@@ -0,0 +1,11 @@
+#!/usr/bin/awk -f
+# only for mostly 2-byte encodings like euc-kr
+
+$2~"^/x..$" {
+	c = substr($2, 3, 2)
+	if (c<"80")
+	    print substr($1, 3, 4) "\t" c
+}
+$2~"^/x../x..$" {
+	print substr($1, 3, 4) "\t" substr($2, 3, 2) substr($2, 7, 2)
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TOOLS/subfont-c/encodings/osd-mplayer	Mon Aug 13 18:37:10 2001 +0000
@@ -0,0 +1,15 @@
+E001	01
+E002	02
+E003	03
+E004	04
+E005	05
+E006	06
+E007	07
+E008	08
+E009	09
+E00A	0A
+E00B	0B
+E010	10
+E011	11
+E012	12
+E013	13
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TOOLS/subfont-c/encodings/runme-kr	Mon Aug 13 18:37:10 2001 +0000
@@ -0,0 +1,1 @@
+gunzip -c /usr/share/i18n/charmaps/EUC-KR.gz | ./charmap2enc > euc-kr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TOOLS/subfont-c/osd/README	Mon Aug 13 18:37:10 2001 +0000
@@ -0,0 +1,3 @@
+Requires t1utils and python.
+
+Based on font created by chass.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TOOLS/subfont-c/osd/gen.py	Mon Aug 13 18:37:10 2001 +0000
@@ -0,0 +1,441 @@
+#!/usr/bin/python
+
+from math import *
+import sys
+import string
+
+k = (sqrt(2.)-1.)*4./3.
+
+chars = []
+encoding = []
+count = 1
+first = 1
+
+def append(s):
+    chars.append(s)
+
+def rint(x):
+    return int(round(x))
+"""
+    if x>=0:
+	return int(x+0.5)
+    else:
+	return int(x-0.5)
+"""
+
+class vec:
+    def __init__(self, x, y=0):
+        if type(x) is type(()):
+	    self.x, self.y = x
+	else:
+	    self.x = x
+	    self.y = y
+    def set(self, x, y):
+        self.__init__(x, y)
+    def move(self, x, y):
+        self.x = self.x + x
+        self.y = self.y + y
+    def __add__(self, v):
+        return vec(self.x+v.x, self.y+v.y)
+    def __sub__(self, v):
+        return vec(self.x-v.x, self.y-v.y)
+    def int(self):
+        return vec(rint(self.x), rint(self.y))
+    def t(self):
+        return (self.x, self.y)
+
+class pvec(vec):
+    def __init__(self, l, a):
+        self.x = l * cos(a)
+        self.y = l * sin(a)
+
+
+pen = vec(0,0)
+
+def moveto(x, y=0):
+    global first
+    dx = rint(x-pen.x)
+    dy = rint(y-pen.y)
+    if dx!=0:
+        if dy!=0:
+	    append("\t%i %i rmoveto" % (dx, dy))
+	else:
+	    append("\t%i hmoveto" % (dx))
+    elif dy!=0:
+	    append("\t%i vmoveto" % (dy))
+    elif first:
+	    append("\t0 hmoveto")
+	    first = 0
+    pen.x = pen.x+dx
+    pen.y = pen.y+dx
+
+def rlineto(v):
+    if v.x!=0:
+        if v.y!=0:
+	    append("\t%i %i rlineto" % (v.x, v.y))
+	else:
+	    append("\t%i hlineto" % (v.x))
+    elif v.y!=0:
+	    append("\t%i vlineto" % (v.y))
+
+def closepath():
+    append("\tclosepath")
+
+history = []
+def movebase(x, y=0):
+    history.append((x,y))
+    pen.move(-x, -y)
+
+def moveback():
+    x, y = history.pop()
+    pen.move(x, y)
+
+def ellipse(rx, ry = None, half=0):
+    # rx>0 => counter-clockwise (filled)
+    # rx<0 => clockwise
+
+    if ry==None: ry = abs(rx)
+
+    dx1 = rint(k*rx)
+    dx2 = rx-dx1
+
+    dy1 = rint(k*ry)
+    dy2 = ry-dy1
+
+    rx = abs(rx)
+    moveto(0, -ry)
+    append("\t%i 0 %i %i 0 %i rrcurveto" % (+dx1, +dx2, +dy2, +dy1))
+    append("\t0 %i %i %i %i 0 rrcurveto" % (+dy1, -dx2, +dy2, -dx1))
+    if not half:
+	append("\t%i 0 %i %i 0 %i rrcurveto" % (-dx1, -dx2, -dy2, -dy1))
+	append("\t0 %i %i %i %i 0 rrcurveto" % (-dy1, +dx2, -dy2, +dx1))
+    closepath()
+    if half:
+	pen.set(0, ry)
+    else:
+	pen.set(0, -ry)
+
+circle = ellipse
+
+def rect(w, h):
+    moveto(0, 0)
+    if w>0:
+	append("\t%i hlineto" % (w))
+	append("\t%i vlineto" % (h))
+	append("\t%i hlineto" % (-w))
+	pen.set(0, h)
+    else:
+	append("\t%i vlineto" % (h))
+	append("\t%i hlineto" % (-w))
+	append("\t%i vlineto" % (-h))
+	pen.set(-w, 0)
+    closepath()
+
+def poly(p):
+    moveto(0, 0)
+    prev = vec(0, 0)
+    for q in p:
+        rlineto(vec(q)-prev)
+	prev = vec(q)
+    closepath()
+    pen.set(prev.x, prev.y)
+
+def line(w, l, a):
+    vw = pvec(w*.5, a-pi*.5)
+    vl = pvec(l, a)
+    p = vw
+    moveto(p.x, p.y)
+    p0 = p
+    #print '%%wla %i %i %.3f: %.3f %.3f' % (w, l, a, p0.x, p0.y)
+    p = p+vl
+    rlineto((p-p0).int())
+    p0 = p
+    #print '%%wla %i %i %.3f: %.3f %.3f' % (w, l, a, p0.x, p0.y)
+    p = p-vw-vw
+    rlineto((p-p0).int())
+    p0 = p
+    #print '%%wla %i %i %.3f: %.3f %.3f' % (w, l, a, p0.x, p0.y)
+    p = p-vl
+    #print '%%wla %i %i %.3f: %.3f %.3f' % (w, l, a, p.x, p.y)
+    rlineto((p-p0).int())
+    closepath()
+    pen.set(p.x, p.y)
+
+
+def begin(name, code, hsb, w):
+    global first, count, history
+    history = []
+    pen.set(0, 0)
+    append("""\
+/uni%04X { %% %s
+	%i %i hsbw""" % (code+0xE000, name, hsb, w))
+    i = len(encoding)
+    while i<code:
+	encoding.append('dup %i /.notdef put' % (i,))
+	i = i+1
+    encoding.append('dup %i /uni%04X put' % (code, code+0xE000))
+    count = count + 1
+    first = 1
+
+
+def end():
+    append("""\
+	endchar
+} ND""")
+
+
+
+########################################
+
+r = 400
+s = 375
+hsb = 200	# horizontal side bearing
+hsb2 = 30
+over = 10	# overshoot
+width = 2*r+2*over+2*hsb2
+
+########################################
+begin('play', 0x01, hsb, width)
+poly((  (s,r),
+	(0, 2*r),))
+end()
+
+
+########################################
+w=150
+begin('pause', 0x02, hsb, width)
+rect(w, 2*r)
+movebase(2*w)
+rect(w, 2*r)
+end()
+
+
+########################################
+begin('stop', 0x03, hsb, width)
+rect(665, 720)
+end()
+
+
+########################################
+begin('rewind', 0x04, hsb/2, width)
+movebase(2*s+15)
+poly((  (0, 2*r),
+	(-s, r),))
+movebase(-s-15)
+poly((  (0, 2*r),
+	(-s, r),))
+end()
+
+
+########################################
+begin('fast forward', 0x05, hsb/2, width)
+poly((  (s,r),
+	(0, 2*r),))
+movebase(s+15)
+poly((  (s,r),
+	(0, 2*r),))
+end()
+
+
+########################################
+begin('clock', 0x06, hsb2, width)
+movebase(r, r)
+circle(r+over)
+wc = 65
+r0 = r-3*wc
+n = 4
+movebase(-wc/2, -wc/2)
+rect(-wc, wc)
+moveback()
+for i in range(n):
+    a = i*2*pi/n
+    v = pvec(r0, a)
+    movebase(v.x, v.y)
+    line(-wc, r-r0, a)
+    moveback()
+hh = 11
+mm = 8
+line(-50, r*.5, pi/2-2*pi*(hh+mm/60.)/12)
+line(-40, r*.9, pi/2-2*pi*mm/60.)
+end()
+
+
+########################################
+begin('contrast', 0x07, hsb2, width)
+movebase(r, r)
+circle(r+over)
+circle(-(r+over-80), half=1)
+end()
+
+
+########################################
+begin('saturation', 0x08, hsb2, width)
+movebase(r, r)
+circle(r+over)
+circle(-(r+over-80))
+
+v = pvec(160, pi/2)
+movebase(v.x, v.y)
+circle(80)
+moveback()
+
+v = pvec(160, pi/2+pi*2/3)
+movebase(v.x, v.y)
+circle(80)
+moveback()
+
+v = pvec(160, pi/2-pi*2/3)
+movebase(v.x, v.y)
+circle(80)
+end()
+
+
+########################################
+begin('volume', 0x09, 0, 1000)
+poly((  (1000, 0),
+	(0, 500),))
+end()
+
+
+########################################
+begin('brightness', 0x0A, hsb2, width)
+movebase(r, r)
+circle(150)
+circle(-100)
+
+rb = 375
+wb = 50
+l = 140
+n = 8
+for i in range(n):
+    a = i*2*pi/n
+    v = pvec(l, a)
+    movebase(v.x, v.y)
+    line(wb, rb-l, a)
+    moveback()
+end()
+
+
+########################################
+begin('hue', 0x0B, hsb2, width)
+movebase(r, r)
+circle(r+over)
+ellipse(-(322), 166)
+movebase(0, 280)
+circle(-(60))
+end()
+
+
+########################################
+begin('progress [', 0x10, (334-182)/2, 334)
+poly((  (182, 0),
+	(182, 90),
+	(145, 90),
+	(145, 550),
+	(182, 550),
+	(182, 640),
+	(0, 640),
+))
+end()
+
+
+########################################
+begin('progress |', 0x11, (334-166)/2, 334)
+rect(166, 640)
+end()
+
+
+########################################
+begin('progress ]', 0x12, (334-182)/2, 334)
+poly((  (182, 0),
+	(182, 640),
+	(0, 640),
+	(0, 550),
+	(37, 550),
+	(37, 90),
+	(0, 90),
+))
+end()
+
+
+########################################
+begin('progress .', 0x13, (334-130)/2, 334)
+movebase(0, (640-130)/2)
+rect(130, 130)
+end()
+
+
+
+########################################
+print """\
+%!PS-AdobeFont-1.0: OSD 1.00
+%%CreationDate: Sun Jul 22 12:38:28 2001
+%
+%%EndComments
+12 dict begin
+/FontInfo 9 dict dup begin
+/version (Version 1.00) readonly def
+/Notice () readonly def
+/FullName (OSD) readonly def
+/FamilyName (OSD) readonly def
+/Weight (Regular) readonly def
+/ItalicAngle 0.000000 def
+/isFixedPitch false def
+/UnderlinePosition -133 def
+/UnderlineThickness 49 def
+end readonly def
+/FontName /OSD def
+/PaintType 0 def
+/StrokeWidth 0 def
+/FontMatrix [0.001 0 0 0.001 0 0] def
+/FontBBox {0 -10 1000 800} readonly def
+/Encoding 256 array"""
+
+print string.join(encoding, '\n')
+i = len(encoding)
+while i<256:
+    print 'dup %i /.notdef put' % i
+    i = i+1
+
+
+print """\
+readonly def
+currentdict end
+currentfile eexec
+dup /Private 15 dict dup begin
+/RD{string currentfile exch readstring pop}executeonly def
+/ND{noaccess def}executeonly def
+/NP{noaccess put}executeonly def
+/ForceBold false def
+/BlueValues [ -15 0 717 734 693 708 630 649 593 611 658 679 780 800 ] def
+/OtherBlues [ -112 -93 -200 -178 -45 -26 -134 -116 -71 -51 ] def
+/StdHW [ 7 ] def
+/StdVW [ 8 ] def
+/StemSnapH [ 4 7 10 13 18 22 27 30 33 38 61 65 ] def
+/StemSnapV [ 5 8 11 15 18 21 25 30 33 36 52 64 ] def
+/MinFeature {16 16} def
+/password 5839 def
+/Subrs 1 array
+dup 0 {
+	return
+	} NP
+ ND
+2 index
+/CharStrings %i dict dup begin""" % count
+
+print """\
+/.notdef {
+	0 400 hsbw
+	endchar
+} ND"""
+
+print string.join(chars, '\n')
+
+
+print """\
+end
+end
+readonly put
+noaccess put
+dup/FontName get exch definefont pop
+mark currentfile closefile"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TOOLS/subfont-c/osd/osd.t1a	Mon Aug 13 18:37:10 2001 +0000
@@ -0,0 +1,589 @@
+%!PS-AdobeFont-1.0: OSD 1.00
+%%CreationDate: Sun Jul 22 12:38:28 2001
+%
+%%EndComments
+12 dict begin
+/FontInfo 9 dict dup begin
+/version (Version 1.00) readonly def
+/Notice () readonly def
+/FullName (OSD) readonly def
+/FamilyName (OSD) readonly def
+/Weight (Regular) readonly def
+/ItalicAngle 0.000000 def
+/isFixedPitch false def
+/UnderlinePosition -133 def
+/UnderlineThickness 49 def
+end readonly def
+/FontName /OSD def
+/PaintType 0 def
+/StrokeWidth 0 def
+/FontMatrix [0.001 0 0 0.001 0 0] def
+/FontBBox {0 -10 1000 800} readonly def
+/Encoding 256 array
+dup 0 /.notdef put
+dup 1 /uniE001 put
+dup 2 /uniE002 put
+dup 3 /uniE003 put
+dup 4 /uniE004 put
+dup 5 /uniE005 put
+dup 6 /uniE006 put
+dup 7 /uniE007 put
+dup 8 /uniE008 put
+dup 9 /uniE009 put
+dup 10 /uniE00A put
+dup 11 /uniE00B put
+dup 12 /.notdef put
+dup 13 /.notdef put
+dup 14 /.notdef put
+dup 15 /.notdef put
+dup 16 /uniE010 put
+dup 17 /uniE011 put
+dup 18 /uniE012 put
+dup 19 /uniE013 put
+dup 20 /.notdef put
+dup 21 /.notdef put
+dup 22 /.notdef put
+dup 23 /.notdef put
+dup 24 /.notdef put
+dup 25 /.notdef put
+dup 26 /.notdef put
+dup 27 /.notdef put
+dup 28 /.notdef put
+dup 29 /.notdef put
+dup 30 /.notdef put
+dup 31 /.notdef put
+dup 32 /.notdef put
+dup 33 /.notdef put
+dup 34 /.notdef put
+dup 35 /.notdef put
+dup 36 /.notdef put
+dup 37 /.notdef put
+dup 38 /.notdef put
+dup 39 /.notdef put
+dup 40 /.notdef put
+dup 41 /.notdef put
+dup 42 /.notdef put
+dup 43 /.notdef put
+dup 44 /.notdef put
+dup 45 /.notdef put
+dup 46 /.notdef put
+dup 47 /.notdef put
+dup 48 /.notdef put
+dup 49 /.notdef put
+dup 50 /.notdef put
+dup 51 /.notdef put
+dup 52 /.notdef put
+dup 53 /.notdef put
+dup 54 /.notdef put
+dup 55 /.notdef put
+dup 56 /.notdef put
+dup 57 /.notdef put
+dup 58 /.notdef put
+dup 59 /.notdef put
+dup 60 /.notdef put
+dup 61 /.notdef put
+dup 62 /.notdef put
+dup 63 /.notdef put
+dup 64 /.notdef put
+dup 65 /.notdef put
+dup 66 /.notdef put
+dup 67 /.notdef put
+dup 68 /.notdef put
+dup 69 /.notdef put
+dup 70 /.notdef put
+dup 71 /.notdef put
+dup 72 /.notdef put
+dup 73 /.notdef put
+dup 74 /.notdef put
+dup 75 /.notdef put
+dup 76 /.notdef put
+dup 77 /.notdef put
+dup 78 /.notdef put
+dup 79 /.notdef put
+dup 80 /.notdef put
+dup 81 /.notdef put
+dup 82 /.notdef put
+dup 83 /.notdef put
+dup 84 /.notdef put
+dup 85 /.notdef put
+dup 86 /.notdef put
+dup 87 /.notdef put
+dup 88 /.notdef put
+dup 89 /.notdef put
+dup 90 /.notdef put
+dup 91 /.notdef put
+dup 92 /.notdef put
+dup 93 /.notdef put
+dup 94 /.notdef put
+dup 95 /.notdef put
+dup 96 /.notdef put
+dup 97 /.notdef put
+dup 98 /.notdef put
+dup 99 /.notdef put
+dup 100 /.notdef put
+dup 101 /.notdef put
+dup 102 /.notdef put
+dup 103 /.notdef put
+dup 104 /.notdef put
+dup 105 /.notdef put
+dup 106 /.notdef put
+dup 107 /.notdef put
+dup 108 /.notdef put
+dup 109 /.notdef put
+dup 110 /.notdef put
+dup 111 /.notdef put
+dup 112 /.notdef put
+dup 113 /.notdef put
+dup 114 /.notdef put
+dup 115 /.notdef put
+dup 116 /.notdef put
+dup 117 /.notdef put
+dup 118 /.notdef put
+dup 119 /.notdef put
+dup 120 /.notdef put
+dup 121 /.notdef put
+dup 122 /.notdef put
+dup 123 /.notdef put
+dup 124 /.notdef put
+dup 125 /.notdef put
+dup 126 /.notdef put
+dup 127 /.notdef put
+dup 128 /.notdef put
+dup 129 /.notdef put
+dup 130 /.notdef put
+dup 131 /.notdef put
+dup 132 /.notdef put
+dup 133 /.notdef put
+dup 134 /.notdef put
+dup 135 /.notdef put
+dup 136 /.notdef put
+dup 137 /.notdef put
+dup 138 /.notdef put
+dup 139 /.notdef put
+dup 140 /.notdef put
+dup 141 /.notdef put
+dup 142 /.notdef put
+dup 143 /.notdef put
+dup 144 /.notdef put
+dup 145 /.notdef put
+dup 146 /.notdef put
+dup 147 /.notdef put
+dup 148 /.notdef put
+dup 149 /.notdef put
+dup 150 /.notdef put
+dup 151 /.notdef put
+dup 152 /.notdef put
+dup 153 /.notdef put
+dup 154 /.notdef put
+dup 155 /.notdef put
+dup 156 /.notdef put
+dup 157 /.notdef put
+dup 158 /.notdef put
+dup 159 /.notdef put
+dup 160 /.notdef put
+dup 161 /.notdef put
+dup 162 /.notdef put
+dup 163 /.notdef put
+dup 164 /.notdef put
+dup 165 /.notdef put
+dup 166 /.notdef put
+dup 167 /.notdef put
+dup 168 /.notdef put
+dup 169 /.notdef put
+dup 170 /.notdef put
+dup 171 /.notdef put
+dup 172 /.notdef put
+dup 173 /.notdef put
+dup 174 /.notdef put
+dup 175 /.notdef put
+dup 176 /.notdef put
+dup 177 /.notdef put
+dup 178 /.notdef put
+dup 179 /.notdef put
+dup 180 /.notdef put
+dup 181 /.notdef put
+dup 182 /.notdef put
+dup 183 /.notdef put
+dup 184 /.notdef put
+dup 185 /.notdef put
+dup 186 /.notdef put
+dup 187 /.notdef put
+dup 188 /.notdef put
+dup 189 /.notdef put
+dup 190 /.notdef put
+dup 191 /.notdef put
+dup 192 /.notdef put
+dup 193 /.notdef put
+dup 194 /.notdef put
+dup 195 /.notdef put
+dup 196 /.notdef put
+dup 197 /.notdef put
+dup 198 /.notdef put
+dup 199 /.notdef put
+dup 200 /.notdef put
+dup 201 /.notdef put
+dup 202 /.notdef put
+dup 203 /.notdef put
+dup 204 /.notdef put
+dup 205 /.notdef put
+dup 206 /.notdef put
+dup 207 /.notdef put
+dup 208 /.notdef put
+dup 209 /.notdef put
+dup 210 /.notdef put
+dup 211 /.notdef put
+dup 212 /.notdef put
+dup 213 /.notdef put
+dup 214 /.notdef put
+dup 215 /.notdef put
+dup 216 /.notdef put
+dup 217 /.notdef put
+dup 218 /.notdef put
+dup 219 /.notdef put
+dup 220 /.notdef put
+dup 221 /.notdef put
+dup 222 /.notdef put
+dup 223 /.notdef put
+dup 224 /.notdef put
+dup 225 /.notdef put
+dup 226 /.notdef put
+dup 227 /.notdef put
+dup 228 /.notdef put
+dup 229 /.notdef put
+dup 230 /.notdef put
+dup 231 /.notdef put
+dup 232 /.notdef put
+dup 233 /.notdef put
+dup 234 /.notdef put
+dup 235 /.notdef put
+dup 236 /.notdef put
+dup 237 /.notdef put
+dup 238 /.notdef put
+dup 239 /.notdef put
+dup 240 /.notdef put
+dup 241 /.notdef put
+dup 242 /.notdef put
+dup 243 /.notdef put
+dup 244 /.notdef put
+dup 245 /.notdef put
+dup 246 /.notdef put
+dup 247 /.notdef put
+dup 248 /.notdef put
+dup 249 /.notdef put
+dup 250 /.notdef put
+dup 251 /.notdef put
+dup 252 /.notdef put
+dup 253 /.notdef put
+dup 254 /.notdef put
+dup 255 /.notdef put
+readonly def
+currentdict end
+currentfile eexec
+dup /Private 15 dict dup begin
+/RD{string currentfile exch readstring pop}executeonly def
+/ND{noaccess def}executeonly def
+/NP{noaccess put}executeonly def
+/ForceBold false def
+/BlueValues [ -15 0 717 734 693 708 630 649 593 611 658 679 780 800 ] def
+/OtherBlues [ -112 -93 -200 -178 -45 -26 -134 -116 -71 -51 ] def
+/StdHW [ 7 ] def
+/StdVW [ 8 ] def
+/StemSnapH [ 4 7 10 13 18 22 27 30 33 38 61 65 ] def
+/StemSnapV [ 5 8 11 15 18 21 25 30 33 36 52 64 ] def
+/MinFeature {16 16} def
+/password 5839 def
+/Subrs 1 array
+dup 0 {
+	return
+	} NP
+ ND
+2 index
+/CharStrings 16 dict dup begin
+/.notdef {
+	0 400 hsbw
+	endchar
+} ND
+/uniE001 { % play
+	200 880 hsbw
+	0 hmoveto
+	375 400 rlineto
+	-375 400 rlineto
+	closepath
+	endchar
+} ND
+/uniE002 { % pause
+	200 880 hsbw
+	0 hmoveto
+	150 hlineto
+	800 vlineto
+	-150 hlineto
+	closepath
+	300 -800 rmoveto
+	150 hlineto
+	800 vlineto
+	-150 hlineto
+	closepath
+	endchar
+} ND
+/uniE003 { % stop
+	200 880 hsbw
+	0 hmoveto
+	665 hlineto
+	720 vlineto
+	-665 hlineto
+	closepath
+	endchar
+} ND
+/uniE004 { % rewind
+	100 880 hsbw
+	765 hmoveto
+	800 vlineto
+	-375 -400 rlineto
+	closepath
+	-15 -400 rmoveto
+	800 vlineto
+	-375 -400 rlineto
+	closepath
+	endchar
+} ND
+/uniE005 { % fast forward
+	100 880 hsbw
+	0 hmoveto
+	375 400 rlineto
+	-375 400 rlineto
+	closepath
+	390 -800 rmoveto
+	375 400 rlineto
+	-375 400 rlineto
+	closepath
+	endchar
+} ND
+/uniE006 { % clock
+	30 880 hsbw
+	400 -10 rmoveto
+	226 0 184 184 0 226 rrcurveto
+	0 226 -184 184 -226 0 rrcurveto
+	-226 0 -184 -184 0 -226 rrcurveto
+	0 -226 184 -184 226 0 rrcurveto
+	closepath
+	-33 377 rmoveto
+	65 vlineto
+	65 hlineto
+	-65 vlineto
+	closepath
+	173 66 rmoveto
+	195 hlineto
+	-65 vlineto
+	-195 hlineto
+	closepath
+	-238 238 rmoveto
+	195 vlineto
+	65 hlineto
+	-195 vlineto
+	closepath
+	-238 -237 rmoveto
+	-195 hlineto
+	65 vlineto
+	195 hlineto
+	closepath
+	237 -238 rmoveto
+	-195 vlineto
+	-65 hlineto
+	195 vlineto
+	closepath
+	10 194 rmoveto
+	-88 180 rlineto
+	45 22 rlineto
+	88 -180 rlineto
+	closepath
+	-36 4 rmoveto
+	268 241 rlineto
+	27 -30 rlineto
+	-268 -241 rlineto
+	closepath
+	endchar
+} ND
+/uniE007 { % contrast
+	30 880 hsbw
+	400 -10 rmoveto
+	226 0 184 184 0 226 rrcurveto
+	0 226 -184 184 -226 0 rrcurveto
+	-226 0 -184 -184 0 -226 rrcurveto
+	0 -226 184 -184 226 0 rrcurveto
+	closepath
+	80 vmoveto
+	-182 0 -148 148 0 182 rrcurveto
+	0 182 148 148 182 0 rrcurveto
+	closepath
+	endchar
+} ND
+/uniE008 { % saturation
+	30 880 hsbw
+	400 -10 rmoveto
+	226 0 184 184 0 226 rrcurveto
+	0 226 -184 184 -226 0 rrcurveto
+	-226 0 -184 -184 0 -226 rrcurveto
+	0 -226 184 -184 226 0 rrcurveto
+	closepath
+	80 vmoveto
+	-182 0 -148 148 0 182 rrcurveto
+	0 182 148 148 182 0 rrcurveto
+	182 0 148 -148 0 -182 rrcurveto
+	0 -182 -148 -148 -182 0 rrcurveto
+	closepath
+	410 vmoveto
+	44 0 36 36 0 44 rrcurveto
+	0 44 -36 36 -44 0 rrcurveto
+	-44 0 -36 -36 0 -44 rrcurveto
+	0 -44 36 -36 44 0 rrcurveto
+	closepath
+	-139 -240 rmoveto
+	44 0 36 36 0 44 rrcurveto
+	0 44 -36 36 -44 0 rrcurveto
+	-44 0 -36 -36 0 -44 rrcurveto
+	0 -44 36 -36 44 0 rrcurveto
+	closepath
+	277 hmoveto
+	44 0 36 36 0 44 rrcurveto
+	0 44 -36 36 -44 0 rrcurveto
+	-44 0 -36 -36 0 -44 rrcurveto
+	0 -44 36 -36 44 0 rrcurveto
+	closepath
+	endchar
+} ND
+/uniE009 { % volume
+	0 1000 hsbw
+	0 hmoveto
+	1000 hlineto
+	-1000 500 rlineto
+	closepath
+	endchar
+} ND
+/uniE00A { % brightness
+	30 880 hsbw
+	400 250 rmoveto
+	83 0 67 67 0 83 rrcurveto
+	0 83 -67 67 -83 0 rrcurveto
+	-83 0 -67 -67 0 -83 rrcurveto
+	0 -83 67 -67 83 0 rrcurveto
+	closepath
+	50 vmoveto
+	-55 0 -45 45 0 55 rrcurveto
+	0 55 45 45 55 0 rrcurveto
+	55 0 45 -45 0 -55 rrcurveto
+	0 -55 -45 -45 -55 0 rrcurveto
+	closepath
+	140 75 rmoveto
+	235 hlineto
+	50 vlineto
+	-235 hlineto
+	closepath
+	-23 56 rmoveto
+	166 166 rlineto
+	-35 35 rlineto
+	-166 -166 rlineto
+	closepath
+	-56 23 rmoveto
+	235 vlineto
+	-50 hlineto
+	-235 vlineto
+	closepath
+	-56 -23 rmoveto
+	-166 166 rlineto
+	-35 -35 rlineto
+	166 -166 rlineto
+	closepath
+	-23 -56 rmoveto
+	-235 hlineto
+	-50 vlineto
+	235 hlineto
+	closepath
+	23 -56 rmoveto
+	-166 -166 rlineto
+	35 -35 rlineto
+	166 166 rlineto
+	closepath
+	56 -23 rmoveto
+	-235 vlineto
+	50 hlineto
+	235 vlineto
+	closepath
+	56 23 rmoveto
+	166 -166 rlineto
+	35 35 rlineto
+	-166 166 rlineto
+	closepath
+	endchar
+} ND
+/uniE00B { % hue
+	30 880 hsbw
+	400 -10 rmoveto
+	226 0 184 184 0 226 rrcurveto
+	0 226 -184 184 -226 0 rrcurveto
+	-226 0 -184 -184 0 -226 rrcurveto
+	0 -226 184 -184 226 0 rrcurveto
+	closepath
+	244 vmoveto
+	-178 0 -144 74 0 92 rrcurveto
+	0 92 144 74 178 0 rrcurveto
+	178 0 144 -74 0 -92 rrcurveto
+	0 -92 -144 -74 -178 0 rrcurveto
+	closepath
+	386 vmoveto
+	-33 0 -27 27 0 33 rrcurveto
+	0 33 27 27 33 0 rrcurveto
+	33 0 27 -27 0 -33 rrcurveto
+	0 -33 -27 -27 -33 0 rrcurveto
+	closepath
+	endchar
+} ND
+/uniE010 { % progress [
+	76 334 hsbw
+	0 hmoveto
+	182 hlineto
+	90 vlineto
+	-37 hlineto
+	460 vlineto
+	37 hlineto
+	90 vlineto
+	-182 hlineto
+	closepath
+	endchar
+} ND
+/uniE011 { % progress |
+	84 334 hsbw
+	0 hmoveto
+	166 hlineto
+	640 vlineto
+	-166 hlineto
+	closepath
+	endchar
+} ND
+/uniE012 { % progress ]
+	76 334 hsbw
+	0 hmoveto
+	182 hlineto
+	640 vlineto
+	-182 hlineto
+	-90 vlineto
+	37 hlineto
+	-460 vlineto
+	-37 hlineto
+	closepath
+	endchar
+} ND
+/uniE013 { % progress .
+	102 334 hsbw
+	255 vmoveto
+	130 hlineto
+	130 vlineto
+	-130 hlineto
+	closepath
+	endchar
+} ND
+end
+end
+readonly put
+noaccess put
+dup/FontName get exch definefont pop
+mark currentfile closefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TOOLS/subfont-c/osd/runme	Mon Aug 13 18:37:10 2001 +0000
@@ -0,0 +1,5 @@
+#
+./gen.py > osd.t1a &&
+t1asm --pfb osd.t1a osd.pfb &&
+ftview 80 osd.pfb &> /dev/null &
+#../subfont iso-8859-2 25 osd.pfb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TOOLS/subfont-c/runme	Mon Aug 13 18:37:10 2001 +0000
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+font=arial.ttf
+encoding=iso-8859-2
+fontsize=24
+symbolssize=35
+blur=2
+outline=1.5
+
+make || exit
+
+./subfont --blur $blur --outline $outline "$encoding" $fontsize "$font" &>log || exit
+cat log
+./subfont --append --blur $blur --outline $outline encodings/osd-mplayer $symbolssize osd/osd.pfb
+
+#cp font.desc *.raw ~/.mplayer/font/
+
+exit
+
+SIZE=`awk '/^bitmap size/ {print $NF}' log`+800
+display -size $SIZE gray:$encoding-a.raw &
+display -size $SIZE gray:$encoding-b.raw &
+#convert -size $SIZE gray:$encoding-a.raw $encoding-a.png
+#convert -size $SIZE gray:$encoding-b.raw $encoding-b.png
--- a/TOOLS/subfont-c/subfont.c	Mon Aug 13 13:12:49 2001 +0000
+++ b/TOOLS/subfont-c/subfont.c	Mon Aug 13 18:37:10 2001 +0000
@@ -16,53 +16,72 @@
 #include <iconv.h>
 #include <math.h>
 #include <string.h>
+#include <libgen.h>
 
-#if 0			/* freetype 2.0.1 */
-#include <freetype/freetype.h>
-#else			/* freetype 2.0.3 */
+
+#ifndef OLD_FREETYPE2
+
 #include <ft2build.h>	
 #include FT_FREETYPE_H
+#include FT_GLYPH_H
+
+#else			/* freetype 2.0.1 */
+
+#include <freetype/freetype.h>
+#include <freetype/ftglyph.h>
+
+#endif
+
+#ifndef DEBUG
+#define DEBUG	0
 #endif
 
-#include FT_GLYPH_H
+
+//// default values
+char		*encoding = "iso-8859-1";	/* target encoding */
+char		*charmap = "ucs-4";		/* font charmap encoding, I hope ucs-4 is always big endian */
+						/* gcc 2.1.3 doesn't support ucs-4le, but supports ucs-4 (==ucs-4be) */
+int		ppem = 22;			/* font size in pixels */
+
+double		radius = 2;			/* blur radius */
+double		thickness = 1.5;		/* outline thickness */
+int		padding;
+
+char*		font_desc = "font.desc";
+//char*		font_desc = "/dev/stdout";
+
+//// constants
+int const	colors = 256;
+int const	maxcolor = 255;
+unsigned const	base = 256;
+unsigned const	first_char = 33;
+#define max_charset_size	60000
+//int const	max_charset_size = 256;
+unsigned	charset_size = 0;
+
+////
+char		*command;
+char		*font_path;
+//char		*font_metrics;
+int		append_mode = 0;
+
+unsigned char	*buffer, *abuffer;
+int		width, height;
+static FT_ULong	charset[max_charset_size];		/* characters we want to render; Unicode */
+static FT_ULong	charcodes[max_charset_size];	/* character codes in 'encoding' */
+iconv_t cd;					// iconv conversion descriptor
 
 
 
-#define f266toInt(x)	(((x)+32)>>6)		/* round fractional fixed point number to integer */
-						/* coordinates are in 26.6 pixels (i.e. 1/64th of pixels) */
-
-
-int const	test = 1;
-
-/* default values */
-char		*encoding = "iso-8859-1";	/* target encoding */
-/* gcc 2.1.3 doesn't support ucs-4le, but supports ucs-4 (==ucs-4be) */
-char		*charmap = "ucs-4";		/* ucs-4le font charmap encoding */
-int		ppem = 20;			/* font size in pixels */
-
-int const	colors = 256;
-int const	maxcolor = 255;
-int		radius = 2;			/* blur radius */
-double		minalpha = 1.0;			/* good value for minalpha is 0.5 */
-double		alpha_factor = 1.0;
+#define eprintf(...)		fprintf(stderr, __VA_ARGS__)
+#define ERROR_(msg, ...)	(eprintf("%s: error: " msg "\n", command, __VA_ARGS__), exit(1))
+#define WARNING_(msg, ...)	eprintf("%s: warning: " msg "\n", command, __VA_ARGS__)
+#define ERROR(...)		ERROR_(__VA_ARGS__, NULL)
+#define WARNING(...)		WARNING_(__VA_ARGS__, NULL)
 
-int const	first_char = 33;
-int const	charset_size = 256;
-
-char		*command;
-char		*font_path = NULL;
-/*char		*font_metrics = NULL;*/
-
-
-unsigned char	*buffer;
-unsigned char	*ebuffer; // temporary buffer for alphamap creation (edges)
-unsigned char	*abuffer;
-int		width, height;
-static FT_ULong	ustring[256];
-
-#define eprintf(...)		fprintf(stderr, __VA_ARGS__)
-#define ERROR(msg, ...)		(eprintf("%s: error: " msg "\n", command, ##__VA_ARGS__), exit(1))
-#define WARNING(msg, ...)	eprintf("%s: warning: " msg "\n", command, ##__VA_ARGS__)
+#define f266toInt(x)	(((x)+32)>>6)		// round fractional fixed point number to integer
+						// coordinates are in 26.6 pixels (i.e. 1/64th of pixels)
+#define ALIGN(x)	(((x)+7)&~7)		// 8 byte align
 
 
 
@@ -80,6 +99,7 @@
 		    buffer[drow+dp] = bitmap->buffer[srow+sp];
 }
 
+
 void write_header(FILE *f) {
     static unsigned char   header[800] = "mhwanh";
     int i;
@@ -91,6 +111,7 @@
     fwrite(header, 1, 800, f);
 }
 
+
 void write_bitmap() {
     FILE *f;
     int const max_name = 128;
@@ -98,38 +119,40 @@
 
     snprintf(name, max_name, "%s-b.raw", encoding);
     f = fopen(name, "wb");
-    if (f==NULL) ERROR("fopen failed.",NULL);
+    if (f==NULL) ERROR("fopen failed.");
     write_header(f);
     fwrite(buffer, 1, width*height, f);
     fclose(f);
 
     snprintf(name, max_name, "%s-a.raw", encoding);
     f = fopen(name, "wb");
-    if (f==NULL) ERROR("fopen failed.",NULL);
+    if (f==NULL) ERROR("fopen failed.");
     write_header(f);
     fwrite(abuffer, 1, width*height, f);
     fclose(f);
 }
 
+
 void render() {
     FT_Library	library;
     FT_Face	face;
     FT_Error	error;
     FT_GlyphSlot	slot;
-    FT_ULong	glyph_index;
-    FT_Glyph	glyphs[charset_size];
+    FT_ULong	glyph_index, character, code;
+    //FT_Glyph	glyphs[max_charset_size];
+    FT_Glyph	glyph;
     FILE	*f;
     int	const	load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
     int		pen_x, pen_xa, pen_y, ymin, ymax;
-    int		i, c;
+    int		i, uni_charmap = 1;
     int		baseline, space_advance = 20;
 
 
     /* initialize freetype */
     error = FT_Init_FreeType(&library);
-    if (error) ERROR("Init_FreeType failed.",NULL);
+    if (error) ERROR("Init_FreeType failed.");
     error = FT_New_Face(library, font_path, 0, &face);
-    if (error) ERROR("New_Face failed.",NULL);
+    if (error) ERROR("New_Face failed.");
 
     /*
     if (font_metrics) {
@@ -139,8 +162,39 @@
     */
 
 
-    if (face->charmap->encoding!=ft_encoding_unicode)
-	WARNING("Selected font has no unicode charmap. Very bad!",NULL);
+#if 0
+    /************************************************************/
+    eprintf("Font encodings:\n");
+    for (i = 0; i<face->num_charmaps; ++i)
+	eprintf("'%.4s'\n", (char*)&face->charmaps[i]->encoding);
+
+    //error = FT_Select_Charmap(face, ft_encoding_unicode);
+    //error = FT_Select_Charmap(face, ft_encoding_adobe_standard);
+    //error = FT_Select_Charmap(face, ft_encoding_adobe_custom);
+    //error = FT_Set_Charmap(face, face->charmaps[1]);
+    //if (error) WARNING("Select_Charmap failed.");
+#endif
+#if 0
+    /************************************************************/
+    if (FT_HAS_GLYPH_NAMES(face)) {
+	int const max_gname = 128;
+	char gname[max_gname];
+	for (i = 0; i<face->num_glyphs; ++i) {
+	    FT_Get_Glyph_Name(face, i, gname, max_gname);
+	    eprintf("%02x `%s'\n", i, gname);
+	}
+
+    }
+#endif
+
+
+    if (face->charmap==NULL || face->charmap->encoding!=ft_encoding_unicode) {
+	WARNING("Unicode charmap not available for this font. Very bad!");
+	uni_charmap = 0;
+	error = FT_Set_Charmap(face, face->charmaps[0]);
+	if (error) WARNING("No charmaps! Strange.");
+    }
+
 
 
     /* set size */
@@ -156,38 +210,46 @@
 		jppem = face->available_sizes[i].height;
 	    }
 	}
-	WARNING("Selected font is not scalable. Using ppem=%i", face->available_sizes[j].height);
+	WARNING("Selected font is not scalable. Using ppem=%i.", face->available_sizes[j].height);
 	error = FT_Set_Pixel_Sizes(face, face->available_sizes[j].width, face->available_sizes[j].height);
     }
-    if (error) WARNING("Set_Pixel_Sizes failed.",NULL);
+    if (error) WARNING("Set_Pixel_Sizes failed.");
 
 
     if (FT_IS_FIXED_WIDTH(face))
-	WARNING("Selected font is fixed-width.",NULL);
+	WARNING("Selected font is fixed-width.");
 
 
     /* compute space advance */
     error = FT_Load_Char(face, ' ', load_flags);
-    if (error) WARNING("spacewidth set to default.",NULL);
-    else space_advance = f266toInt(face->glyph->advance.x);	/* +32 is for rounding */
+    if (error) WARNING("spacewidth set to default.");
+    else space_advance = f266toInt(face->glyph->advance.x);
 
 
     /* create font.desc */
-    f = fopen("font.desc", "w");
-    if (f==NULL) ERROR("fopen failed.",NULL);
+    f = fopen(font_desc, append_mode ? "a":"w");
+    if (f==NULL) ERROR("fopen failed.");
 
     /* print font.desc header */
-    fprintf(f, "[info]\n");
-    fprintf(f, "name 'File generated for %s encoding using `%s%s%s' face (%s), ppem=%i'\n",
-	    encoding,
-	    face->family_name,
-	    face->style_name ? " ":"", face->style_name ? face->style_name:"",
-	    font_path,
-	    ppem);
-    fprintf(f, "descversion 1\n");
-    fprintf(f, "spacewidth %i\n",	2*radius + space_advance);
-    fprintf(f, "charspace %i\n",	-2*radius);
-    fprintf(f, "height %i\n",	f266toInt(face->size->metrics.height));
+    if (append_mode) {
+	fprintf(f, "\n\n# Subtitle font for %s encoding, face \"%s%s%s\", ppem=%i\n",
+		encoding,
+		face->family_name,
+		face->style_name ? " ":"", face->style_name ? face->style_name:"",
+		ppem);
+    } else {
+	fprintf(f, "# This file was generated with subfont for Mplayer.\n# Subfont by Artur Zaprzala <zybi@fanthom.irc.pl>.\n\n");
+	fprintf(f, "[info]\n");
+	fprintf(f, "name 'Subtitle font for %s encoding, face \"%s%s%s\", ppem=%i'\n",
+		encoding,
+		face->family_name,
+		face->style_name ? " ":"", face->style_name ? face->style_name:"",
+		ppem);
+	fprintf(f, "descversion 1\n");
+	fprintf(f, "spacewidth %i\n",	2*padding + space_advance);
+	fprintf(f, "charspace %i\n",	-2*padding);
+	fprintf(f, "height %i\n",		f266toInt(face->size->metrics.height));
+    }
     fprintf(f, "\n[files]\n");
     fprintf(f, "alpha %s-a.raw\n",	encoding);
     fprintf(f, "bitmap %s-b.raw\n",	encoding);
@@ -199,288 +261,429 @@
     pen_y = 0;
     ymin = INT_MAX;
     ymax = INT_MIN;
-    for (c= first_char, i= 0; c<charset_size; ++c, ++i) {
+    for (i= 0; i<charset_size; ++i) {
 	FT_UInt	glyph_index;
 	FT_BBox	bbox;
+	character = charset[i];
+	code = charcodes[i];
 
-	glyph_index = FT_Get_Char_Index(face, ustring[i]);
-	if (glyph_index<=0) {
-	    WARNING("Glyph for char %3i|%2X|U%04X not found.", c, c, ustring[i]);
-	    continue;
+	if (character==0)
+	    glyph_index = 0;
+	else {
+	    glyph_index = FT_Get_Char_Index(face, uni_charmap ? character:code);
+	    if (glyph_index==0) {
+		WARNING("Glyph for char 0x%02x|U+%04X|%c not found.", code, character,
+			 code<' '||code>255 ? '.':code);
+		continue;
+	    }
 	}
 
 	error = FT_Load_Glyph(face, glyph_index, load_flags);
 	if (error) {
-	    WARNING("Load_Glyph %3u|%2X (char %3i|%2X|U%04X) failed.", glyph_index, glyph_index, c, c, ustring[i]);
+	    WARNING("Load_Glyph 0x%02x (char 0x%02x|U+%04X) failed.", glyph_index, code, character);
 	    continue;
 	}
 
 	slot = face->glyph;
-	error = FT_Get_Glyph(slot, &glyphs[i]);
+	error = FT_Get_Glyph(slot, &glyph);
 
 
-	FT_Glyph_Get_CBox(glyphs[i], ft_glyph_bbox_pixels, &bbox);
+	FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_pixels, &bbox);
 	if (pen_y+bbox.yMax>ymax) {
 	    ymax = pen_y+bbox.yMax;
-	    /* eprintf("%3i: ymax %i (%c)\n", c, ymax, c); */
+	    // eprintf("%3i: ymax %i (%c)\n", code, ymax, code);
 	}
 	if (pen_y+bbox.yMin<ymin) {
 	    ymin = pen_y+bbox.yMin;
-	    /* eprintf("%3i: ymin %i (%c)\n", c, ymin, c); */
+	    // eprintf("%3i: ymin %i (%c)\n", code, ymin, code);
 	}
 
 	/* advance pen */
-	pen_xa = pen_x + f266toInt(slot->advance.x) + 2*radius;
-	/* pen_y += f266toInt(slot->advance.y);		// for vertical layout */
+	pen_xa = pen_x + f266toInt(slot->advance.x) + 2*padding;
+	// pen_y += f266toInt(slot->advance.y);		// for vertical layout
 
 	/* font.desc */
-	if (c=='\'')
-	    fprintf(f, "\"%c\" %i %i\n", c, pen_x,  pen_xa-1);
-	else
-	    fprintf(f, "'%c' %i %i\n", c, pen_x, pen_xa-1);
-	pen_x = (pen_xa+7)&~7;				/* 8 byte align */
+	fprintf(f, "0x%02x %i %i;\tU+%04X|%c\n", code, pen_x,  pen_xa-1, character, code<' '||code>255 ? '.':code);
+	pen_x = ALIGN(pen_xa);
 
     }
 
     fclose(f);
 
-    if (ymax<=ymin) ERROR("Something went wrong.",NULL);
+    if (ymax<=ymin) ERROR("Something went wrong. Use the source!");
 
 
     width = pen_x;
-    height = ymax - ymin + 2*radius;
-    baseline = ymax + radius;
+    height = ymax - ymin + 2*padding;
+    baseline = ymax + padding;
     eprintf("bitmap size: %ix%i\n", width, height);
 
     buffer = (unsigned char*)malloc(width*height);
-    ebuffer = (unsigned char*)malloc(width*height);
     abuffer = (unsigned char*)malloc(width*height);
-    if (buffer==NULL || abuffer==NULL) ERROR("malloc failed.",NULL);
+    if (buffer==NULL || abuffer==NULL) ERROR("malloc failed.");
+
+    memset(buffer, 0, width*height);
 
 
     /* render glyphs */
     pen_x = 0;
     pen_y = baseline;
-    for (c= first_char, i= 0; c<charset_size; ++c, ++i) {
+    for (i= 0; i<charset_size; ++i) {
 	FT_UInt	glyph_index;
+	character = charset[i];
+	code = charcodes[i];
 
-	glyph_index = FT_Get_Char_Index(face, ustring[i]);
-	if (glyph_index==0) continue;
+	if (character==0)
+	    glyph_index = 0;
+	else {
+	    glyph_index = FT_Get_Char_Index(face, uni_charmap ? character:code);
+	    if (glyph_index==0)
+		continue;
+	}
+
 	error = FT_Load_Glyph(face, glyph_index, load_flags);
 	if (error) {
-	    /* WARNING("Load_Glyph failed"); */
+	    // WARNING("Load_Glyph failed.");
 	    continue;
 	}
 
 	error = FT_Render_Glyph(face->glyph, ft_render_mode_normal);
-	if (error) WARNING("Render_Glyph %3i|%2X (char %3i|%2X|U%04X) failed.", glyph_index, glyph_index, c, c, ustring[i]);
+	if (error) WARNING("Render_Glyph 0x%02x (char 0x%02x|U+%04X) failed.", glyph_index, code, character);
 
 	slot = face->glyph;
 
 	paste_bitmap(&slot->bitmap,
-	    pen_x + radius + slot->bitmap_left,
+	    pen_x + padding + slot->bitmap_left,
 	    pen_y - slot->bitmap_top );
 
 	/* advance pen */
-	pen_x += f266toInt(slot->advance.x) + 2*radius;
-	/* pen_y += f266toInt(slot->advance.y);	// for vertical layout */
-	pen_x = (pen_x+7)&~7;			/* 8 byte align */
+	pen_x += f266toInt(slot->advance.x) + 2*padding;
+	// pen_y += f266toInt(slot->advance.y);	// for vertical layout
+	pen_x = ALIGN(pen_x);
     }
 
 
     error = FT_Done_FreeType(library);
-    if (error) ERROR("Done_FreeType failed.",NULL);
+    if (error) ERROR("Done_FreeType failed.");
 }
 
+
+/* decode from 'encoding' to unicode */
+FT_ULong decode_char(char c) {
+    FT_ULong o;
+    char *inbuf = &c;
+    char *outbuf = (char*)&o;
+    int inbytesleft = 1;
+    int outbytesleft = sizeof(FT_ULong);
+
+    size_t count = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+    if (count==-1) o = 0;
+
+    /* convert unicode BE -> LE */
+    o = ((o>>24)&0xff)
+      | ((o>>8)&0xff00)
+      | ((o&0xff00)<<8)
+      | ((o&0xff)<<24);
+
+    /* we don't want control characters */
+    if (o>=0x7f && o<0xa0) o = 0;
+    return o;
+}
+
+
 void prepare_charset() {
-    iconv_t cd;
-    unsigned char text[charset_size];
-    char *inbuf = text;
-    char *outbuf = (char*) ustring;
-    int inbuf_left = charset_size;
-    int outbuf_left = 4*charset_size;
-    int i;
-    size_t count;
+    FILE *f;
+    FT_ULong i;
+
+    f = fopen(encoding, "r");		// try to read custom encoding
+    if (f==NULL) {
+	int count = 0;
+	// check if ucs-4 is available
+	cd = iconv_open(charmap, charmap);
+	if (cd==(iconv_t)-1) ERROR("iconv doesn't know %s encoding. Use the source!", charmap);
+	iconv_close(cd);
+
+	cd = iconv_open(charmap, encoding);
+	if (cd==(iconv_t)-1) ERROR("Unsupported encoding `%s', use iconv --list to list character sets known on your system.", encoding);
 
-    for (i = first_char; i<charset_size; ++i) text[i-first_char] = i;
+	charset_size = 256 - first_char;
+	for (i = 0; i<charset_size; ++i) {
+	    charcodes[count] = i+first_char;
+	    charset[count] = decode_char(i+first_char);
+	    //eprintf("%04X U%04X\n", charcodes[count], charset[count]);
+	    if (charset[count]!=0) ++count;
+	}
+	charcodes[count] = charset[count] = 0; ++count;
+	charset_size = count;
 
-    /* check if ucs-4le is available */
-    cd = iconv_open(charmap, charmap);
-    if (cd==(iconv_t)-1) ERROR("iconv doesn't know %s encoding. Use the source!", charmap);
-    iconv_close(cd);
+	iconv_close(cd);
+    } else {
+	unsigned int character, code;
+	int count;
+
+	eprintf("Reading custom encoding from file '%s'.\n", encoding);
 
-    cd = iconv_open(charmap, encoding);
-    if (cd==(iconv_t)-1) ERROR("Unsupported encoding, use iconv -l to list character sets known on your system.",NULL);
-    while (1) {
-	count = iconv(cd, &inbuf, &inbuf_left, &outbuf, &outbuf_left);
-    	if (inbuf_left==0) break;
-	/* skip undefined characters */
-	inbuf+= 1;
-	inbuf_left-= 1;
-	*(FT_ULong*)outbuf = 0;
-	outbuf+=sizeof(FT_ULong);
+       	while ((count = fscanf(f, "%x%*[ \t]%x", &character, &code)) != EOF) {
+	    if (charset_size==max_charset_size) {
+		WARNING("There is no place for  more than %i characters. Use the source!", max_charset_size);
+		break;
+	    }
+	    if (count==0) ERROR("Unable to parse custom encoding file.");
+	    if (character<32) continue;	// skip control characters
+	    charset[charset_size] = character;
+	    charcodes[charset_size] = count==2 ? code : character;
+	    ++charset_size;
+	}
+	fclose(f);
+	encoding = basename(encoding);
     }
-    iconv_close(cd);
+    if (charset_size==0) ERROR("No characters to render!");
+}
+
+
+// general outline
+void outline(
+	unsigned char *s,
+	unsigned char *t,
+	int width,
+	int height,
+	int *m,
+	int r,
+	int mwidth) {
 
-    /* converting unicodes BE -> LE */
-    for (i = 0; i<256; ++i){
-	FT_ULong x=ustring[i];
-	x=  ((x>>24)&255)
-	 | (((x>>16)&255)<<8)
-	 | (((x>> 8)&255)<<16)
-	 | ((x&255)<<24);
-	ustring[i]=x;
+    int x, y, mx, my;
+    for (y = 0; y<height; ++y) {
+	for (x = 0; x<width; ++x, ++s, ++t) {
+	    unsigned max = 0;
+	    unsigned *mrow = m + r;
+	    unsigned char *srow = s -r*width;
+
+	    for (my = -r; my<=r; ++my, srow+= width, mrow+= mwidth) {
+		if (y+my < 0) continue;
+		if (y+my >= height) break;
+
+		for (mx = -r; mx<=r; ++mx) {
+		    unsigned v;
+		    if (x+mx < 0) continue;
+		    if (x+mx >= width) break;
+
+		    v = srow[mx] * mrow[mx];
+		    if (v>max) max = v;
+		}
+	    }
+	    *t = (max + base/2) / base;
+	}
     }
-
 }
 
-void blur() {
-    int const r = radius;
-    int const w = 2*r+1;	/* matrix size */
-    double const A = log(1.0/maxcolor)/((r+1)*(r+1));
-    double const B = maxcolor;
-    int sum=0;
+
+// 1 pixel outline
+void outline1(
+	unsigned char *s,
+	unsigned char *t,
+	int width,
+	int height) {
+
+    int x, y, mx, my;
+
+    for (x = 0; x<width; ++x, ++s, ++t) *t = *s;
+    for (y = 1; y<height-1; ++y) {
+	*t++ = *s++;
+	for (x = 1; x<width-1; ++x, ++s, ++t) {
+	    unsigned v = (
+		    s[-1-width]+
+		    s[-1+width]+
+		    s[+1-width]+
+		    s[+1+width]
+		)/2 + (
+		    s[-1]+
+		    s[+1]+
+		    s[-width]+
+		    s[+width]+
+		    s[0]
+		);
+	    *t = v>maxcolor ? maxcolor : v;
+	}
+	*t++ = *s++;
+    }
+    for (x = 0; x<width; ++x, ++s, ++t) *t = *s;
+}
+
 
-    int i, x, y, mx, my;
-    unsigned char *m = (unsigned char*)malloc(w*w);
+// brute-force gaussian blur
+void blur(
+	unsigned char *s,
+	unsigned char *t,
+	int width,
+	int height,
+	int *m,
+	int r,
+	int mwidth,
+	unsigned volume) {
+
+    int x, y, mx, my;
+
+    for (y = 0; y<height; ++y) {
+	for (x = 0; x<width; ++x, ++s, ++t) {
+	    unsigned sum = 0;
+	    unsigned *mrow = m + r;
+	    unsigned char *srow = s -r*width;
+
+	    for (my = -r; my<=r; ++my, srow+= width, mrow+= mwidth) {
+		if (y+my < 0) continue;
+		if (y+my >= height) break;
 
-    if (m==NULL) ERROR("malloc failed",NULL);
+		for (mx = -r; mx<=r; ++mx) {
+		    if (x+mx < 0) continue;
+		    if (x+mx >= width) break;
+
+		    sum+= srow[mx] * mrow[mx];
+		}
+	    }
+	    *t = (sum + volume/2) / volume;
+	}
+    }
+}
+
+
+void alpha() {
+    int const g_r = ceil(radius);
+    int const o_r = ceil(thickness);
+    int const g_w = 2*g_r+1;		// matrix size
+    int const o_w = 2*o_r+1;		// matrix size
+    double const A = log(1.0/base)/(radius*radius*2);
+
+    int mx, my;
+    unsigned volume = 0;		// volume under Gaussian area is exactly -pi*base/A
+
+    unsigned *gm = (unsigned*)malloc(g_w*g_w * sizeof(unsigned));
+    unsigned *om = (unsigned*)malloc(o_w*o_w * sizeof(unsigned));
+    unsigned char *tbuffer = (unsigned char*)malloc(width*height);
+    if (gm==NULL || om==NULL || tbuffer==NULL) ERROR("malloc failed.");
 
 
     /* Gaussian matrix */
-    for (my = 0; my<w; ++my) {
-	for (mx = 0; mx<w; ++mx) {
-	    m[mx+my*w] = (int)(exp(A * ((mx-r)*(mx-r)+(my-r)*(my-r))) * B + .5);
-	    sum+=m[mx+my*w];
-	    if (test) eprintf("%3i ", m[mx+my*w]);
+    for (my = 0; my<g_w; ++my) {
+	for (mx = 0; mx<g_w; ++mx) {
+	    gm[mx+my*g_w] = (unsigned)(exp(A * ((mx-g_r)*(mx-g_r)+(my-g_r)*(my-g_r))) * base + .5);
+	    volume+= gm[mx+my*g_w];
+	    if (DEBUG) eprintf("%3i ", gm[mx+my*g_w]);
 	}
-	if (test) eprintf("\n");
+	if (DEBUG) eprintf("\n");
     }
-    printf("gauss sum = %d\n",sum);
-
-    /* This is not a gaussian blur! */
-    /* And is very slow */
-    
-    // PASS-1 : build edge mask:
-    memset(ebuffer,0,width*height); // clear
-    for (y = 1; y<height-1; ++y){
-	int ay=y*width;
-	int ax;
-	for (ax = 1; ax<width-1; ++ax) {
-			    int p =
-
-			  ( (buffer[ax-1+ay-width]) +
-			    (buffer[ax-1+ay+width]) +
-			    (buffer[ax+1+ay-width]) +
-			    (buffer[ax+1+ay+width]) )/2 +
-
-			  ( (buffer[ax-1+ay]) +
-			    (buffer[ax+1+ay]) +
-			    (buffer[ax+ay-width]) +
-			    (buffer[ax+ay+width]) +
-
-			    (buffer[ax+ay]) ) ;
-			    
-			    ebuffer[ax+ay]=(p>255)?255:p;
-	}
-//	printf("\n");
+    if (DEBUG) {
+	eprintf("A= %f\n", A);
+	eprintf("volume: %i; exact: %.0f; volume/exact: %.6f\n\n", volume, -M_PI*base/A, volume/(-M_PI*base/A));
     }
 
-    // PASS-2 : blur
-    for (y = 0; y<height; ++y){
-	for (x = 0; x<width; ++x) {
-	    float max = 0;
-	    for (my = -r; my<=r; ++my){
-		int ay=y+my;
-		if(ay>0 && ay<height){
-		    int by=r+(my+r)*w;
-		    ay*=width;
-		    for (mx = -r; mx<=r; ++mx)
-			if(x+mx>0 && x+mx<width)
-			    max+=ebuffer[x+mx+ay]*m[mx+by];
-		}
-	    }
-	    max*=alpha_factor/(float)sum;
-//	    printf("%5.3f ",max);
-	    if(max>255) max=255;
-	    abuffer[x+y*width] = max;
+
+    /* outline matrix */
+    for (my = 0; my<o_w; ++my) {
+	for (mx = 0; mx<o_w; ++mx) {
+	    // antialiased circle would be perfect here, but this one is good enough
+	    double d = thickness + 1 - sqrt((mx-o_r)*(mx-o_r)+(my-o_r)*(my-o_r));
+	    om[mx+my*o_w] = d>=1 ? base : d<=0 ? 0 : (d*base + .5);
+	    if (DEBUG) eprintf("%3i ", om[mx+my*o_w]);
 	}
-//	printf("\n");
+	if (DEBUG) eprintf("\n");
     }
+    if (DEBUG) eprintf("\n");
 
-    free(m);
+
+    outline(buffer, tbuffer, width, height, om, o_r, o_w);	// solid outline
+    //outline(buffer, tbuffer, width, height, gm, g_r, g_w);	// Gaussian outline
+    //outline1(buffer, tbuffer, width, height);	// solid 1 pixel outline
+
+    blur(tbuffer, abuffer, width, height, gm, g_r, g_w, volume);
+
+    free(gm);
+    free(om);
+    free(tbuffer);
 }
 
+
 void usage() {
-    printf("Usage: %s encoding ppem font [alphaFactor [minAlpha [radius]]]\n", command);
-    printf(
+    printf("Usage: %s [--append] [--blur b] [--outline o] encoding ppem font\n", command);
+    printf("\n"
 	    "  Program creates 3 files: font.desc, <encoding>-a.raw, <encoding>-b.raw.\n"
-	    "  You should append font.desc.tail (desc for OSD characters by a'rpi & chass) to font.desc,\n"
-	    "  and copy font.desc and all *.raw files to ~/.mplayer/font/ directory.\n"
 	    "\n"
-	    "  encoding     must be 8 bit encoding, like iso-8859-2.\n"
-	    "               To list encodings available on your system use iconv -l.\n"
-	    "  ppem         Font size in pixels (e.g. 24).\n"
-	    "  font         Font file path. Any format supported by freetype library (*.ttf, *.pf?, *).\n"
-	    "  alphaFactor  Alpha map scaling factor (default is 1.0), float.\n"
-	    "  minAlpha     Alpha map minimum value (default is 1.0, max is 255), float.\n"
-	    "  radius       Alpha map blur radius (default is 6 pixels), integer.\n"
+	    "  --append         append results to existing font.desc.\n"
+	    "  --blur b         specify blur radius, float.\n"
+	    "  --outline o      specify outline thickness, float.\n"
+	    "  encoding         must be an 8 bit encoding, like iso-8859-2, or path to custom encoding file (see README).\n"
+	    "                   To list encodings available on your system use iconv --list.\n"
+	    "  ppem             Font size in pixels (e.g. 24).\n"
+	    "  font             Font file path. Any format supported by the freetype library (*.ttf, *.pfb, ...).\n"
 	    );
     exit(1);
 }
 
+
 void parse_args(int argc, char **argv) {
-    int i;
+    int i, a = 0;
     double d;
 
-    command = strrchr(argv[0], '/');
-    if (command==NULL) command = argv[0];
+    command = strrchr(argv[a], '/');
+    if (command==NULL) command = argv[a];
     else ++command;
+    ++a; --argc;
 
-    if (argc<4) usage();
+    if (argc==0) usage();
+    if (strcmp(argv[a], "--append")==0) {
+	append_mode = 1;
+	++a; --argc;
+    }
 
-    encoding = argv[1];
+
+    if (argc==0) usage();
+    if (strcmp(argv[a], "--blur")==0) {
+	++a; --argc;
+	if (argc==0) usage();
 
-    i = atoi(argv[2]);
-    if (i>1) ppem = i;
-
-    font_path = argv[3];
+	d = atof(argv[a]);
+	if (d>=0 && d<20) radius = d;
+	else WARNING("using default blur radius.");
+	++a; --argc;
+    }
 
-    if (argc>4) {
-	d = atof(argv[4]);
-	if (d>0.001 && d<1000.) alpha_factor = d;
-	else WARNING("alphaFactor set to default.",NULL);
+    if (argc==0) usage();
+    if (strcmp(argv[a], "--outline")==0) {
+	++a; --argc;
+	if (argc==0) usage();
+
+	d = atof(argv[a]);
+	if (d>=0 && d<20) thickness = d;
+	else WARNING("using default outline thickness.");
+	++a; --argc;
     }
-    if (argc>5) {
-	d = atof(argv[5]);
-	if (d>0.1 && d<=maxcolor) minalpha = d;
-	else WARNING("minAlpha set to default.",NULL);
-    }
-    if (argc>6) {
-	i = atoi(argv[6]);
-	if (i>=0 && i<20) radius = i;
-	else WARNING("radius set to default.",NULL);
-    }
+
+    if (argc<3) usage();
+
+    if (argv[a][0]!=0)
+	encoding = argv[a];
+    ++a; --argc;
+
+    i = atoi(argv[a]);
+    if (i>1) ppem = i;
+    ++a; --argc;
+
+    font_path = argv[a];
+    ++a; --argc;
 }
 
+
 int main(int argc, char **argv) {
     parse_args(argc, argv);
+    padding = ceil(radius) + ceil(thickness);
 
     prepare_charset();
     render();
-    blur();
+    alpha();
     write_bitmap();
 
     free(buffer);
     free(abuffer);
 
-    puts(
-	    "\n"
-	    "*****************************************\n"
-	    "*  Remember to run:                     *\n"
-	    "*  cat font.desc.tail >> font.desc      *\n"
-	    "*****************************************"
-	    );
-
+//    fflush(stderr);
     return 0;
 }