aboutsummaryrefslogtreecommitdiffhomepage
path: root/TOOLS/subfont-c
diff options
context:
space:
mode:
Diffstat (limited to 'TOOLS/subfont-c')
-rw-r--r--TOOLS/subfont-c/Makefile22
-rw-r--r--TOOLS/subfont-c/README81
-rwxr-xr-xTOOLS/subfont-c/encodings/charmap2enc11
-rw-r--r--TOOLS/subfont-c/encodings/osd-mplayer15
-rwxr-xr-xTOOLS/subfont-c/encodings/runme-kr1
-rw-r--r--TOOLS/subfont-c/osd/README3
-rwxr-xr-xTOOLS/subfont-c/osd/gen.py441
-rw-r--r--TOOLS/subfont-c/osd/osd.t1a589
-rwxr-xr-xTOOLS/subfont-c/osd/runme5
-rwxr-xr-xTOOLS/subfont-c/runme24
-rw-r--r--TOOLS/subfont-c/subfont.c659
11 files changed, 1579 insertions, 272 deletions
diff --git a/TOOLS/subfont-c/Makefile b/TOOLS/subfont-c/Makefile
index 10e9e26879..23d35a07d4 100644
--- a/TOOLS/subfont-c/Makefile
+++ b/TOOLS/subfont-c/Makefile
@@ -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
diff --git a/TOOLS/subfont-c/README b/TOOLS/subfont-c/README
index b80eb900f4..5989787d1a 100644
--- a/TOOLS/subfont-c/README
+++ b/TOOLS/subfont-c/README
@@ -1,41 +1,62 @@
+Usage:
+~~~~~~
+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.
+
+
About:
~~~~~~
-`subfont' program renders antialiased fonts for mplayer using freetype library.
-Should work with TrueType, Type1 and any other font supported by libfreetype.
+`subfont' program renders antialiased OSD and subtitle fonts for mplayer.
-Goals:
- - internationalization: supports any 8 bit encoding (uses iconv).
- - nice look: creates glyph `shadows' using algorithm derived from gaussian blur (slow!).
+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.
-Note:
-~~~~~
-Starting x position of each char and the bitmap width is aligned to multiple of 8
-(required for under-development MMX renderer).
+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.
-Usage:
+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:
~~~~~~
-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.
-
-
-Example:
-~~~~~~~~
-make
-./subfont iso-8859-2 20 verdana.ttf
-cat font.desc.tail >> font.desc
-cp font.desc *.raw ~/.mplayer/font/
+ + 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:
diff --git a/TOOLS/subfont-c/encodings/charmap2enc b/TOOLS/subfont-c/encodings/charmap2enc
new file mode 100755
index 0000000000..e32d7a463b
--- /dev/null
+++ b/TOOLS/subfont-c/encodings/charmap2enc
@@ -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)
+}
diff --git a/TOOLS/subfont-c/encodings/osd-mplayer b/TOOLS/subfont-c/encodings/osd-mplayer
new file mode 100644
index 0000000000..26ab043016
--- /dev/null
+++ b/TOOLS/subfont-c/encodings/osd-mplayer
@@ -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
diff --git a/TOOLS/subfont-c/encodings/runme-kr b/TOOLS/subfont-c/encodings/runme-kr
new file mode 100755
index 0000000000..df4e81e15c
--- /dev/null
+++ b/TOOLS/subfont-c/encodings/runme-kr
@@ -0,0 +1 @@
+gunzip -c /usr/share/i18n/charmaps/EUC-KR.gz | ./charmap2enc > euc-kr
diff --git a/TOOLS/subfont-c/osd/README b/TOOLS/subfont-c/osd/README
new file mode 100644
index 0000000000..9dec5e5971
--- /dev/null
+++ b/TOOLS/subfont-c/osd/README
@@ -0,0 +1,3 @@
+Requires t1utils and python.
+
+Based on font created by chass.
diff --git a/TOOLS/subfont-c/osd/gen.py b/TOOLS/subfont-c/osd/gen.py
new file mode 100755
index 0000000000..bf08fb8838
--- /dev/null
+++ b/TOOLS/subfont-c/osd/gen.py
@@ -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"""
diff --git a/TOOLS/subfont-c/osd/osd.t1a b/TOOLS/subfont-c/osd/osd.t1a
new file mode 100644
index 0000000000..11e3150a6c
--- /dev/null
+++ b/TOOLS/subfont-c/osd/osd.t1a
@@ -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
diff --git a/TOOLS/subfont-c/osd/runme b/TOOLS/subfont-c/osd/runme
new file mode 100755
index 0000000000..0565c4c8ae
--- /dev/null
+++ b/TOOLS/subfont-c/osd/runme
@@ -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
diff --git a/TOOLS/subfont-c/runme b/TOOLS/subfont-c/runme
new file mode 100755
index 0000000000..484230993c
--- /dev/null
+++ b/TOOLS/subfont-c/runme
@@ -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
diff --git a/TOOLS/subfont-c/subfont.c b/TOOLS/subfont-c/subfont.c
index b72040776d..ba572273da 100644
--- a/TOOLS/subfont-c/subfont.c
+++ b/TOOLS/subfont-c/subfont.c
@@ -16,53 +16,72 @@
#include <iconv.h>
#include <math.h>
#include <string.h>
+#include <libgen.h>
+
+
+#ifndef OLD_FREETYPE2
-#if 0 /* freetype 2.0.1 */
-#include <freetype/freetype.h>
-#else /* freetype 2.0.3 */
#include <ft2build.h>
#include FT_FREETYPE_H
-#endif
-
#include FT_GLYPH_H
+#else /* freetype 2.0.1 */
+#include <freetype/freetype.h>
+#include <freetype/ftglyph.h>
-#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) */
+#endif
+#ifndef DEBUG
+#define DEBUG 0
+#endif
-int const test = 1;
-/* default values */
+//// 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 */
+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;
-int radius = 2; /* blur radius */
-double minalpha = 1.0; /* good value for minalpha is 0.5 */
-double alpha_factor = 1.0;
-
-int const first_char = 33;
-int const charset_size = 256;
+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 = NULL;
-/*char *font_metrics = NULL;*/
-
+char *font_path;
+//char *font_metrics;
+int append_mode = 0;
-unsigned char *buffer;
-unsigned char *ebuffer; // temporary buffer for alphamap creation (edges)
-unsigned char *abuffer;
+unsigned char *buffer, *abuffer;
int width, height;
-static FT_ULong ustring[256];
+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 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_(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)
+
+#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 @@ void paste_bitmap(FT_Bitmap *bitmap, int x, int y) {
buffer[drow+dp] = bitmap->buffer[srow+sp];
}
+
void write_header(FILE *f) {
static unsigned char header[800] = "mhwanh";
int i;
@@ -91,6 +111,7 @@ void write_header(FILE *f) {
fwrite(header, 1, 800, f);
}
+
void write_bitmap() {
FILE *f;
int const max_name = 128;
@@ -98,38 +119,40 @@ void write_bitmap() {
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 @@ void render() {
*/
- 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 @@ void render() {
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 @@ void render() {
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;
-
- 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;
+ character = charset[i];
+ code = charcodes[i];
+
+ 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];
+
+ if (character==0)
+ glyph_index = 0;
+ else {
+ glyph_index = FT_Get_Char_Index(face, uni_charmap ? character:code);
+ if (glyph_index==0)
+ continue;
+ }
- glyph_index = FT_Get_Char_Index(face, ustring[i]);
- 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;
-
- for (i = first_char; i<charset_size; ++i) text[i-first_char] = i;
-
- /* 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);
-
- 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);
+ 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);
+
+ 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;
+
+ iconv_close(cd);
+ } else {
+ unsigned int character, code;
+ int count;
+
+ eprintf("Reading custom encoding from file '%s'.\n", encoding);
+
+ 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);
-
- /* 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;
+ 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) {
+
+ 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;
+ }
}
+}
+
+// 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;
}
-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;
- 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) {
- if (m==NULL) ERROR("malloc failed",NULL);
+ 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;
- /* 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 = -r; my<=r; ++my, srow+= width, mrow+= mwidth) {
+ if (y+my < 0) continue;
+ if (y+my >= height) break;
+
+ 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;
}
- if (test) 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;
+}
+
+
+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<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]);
}
-// printf("\n");
+ if (DEBUG) eprintf("\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");
+
+
+ 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(m);
+ 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();
-
- encoding = argv[1];
+ if (argc==0) usage();
+ if (strcmp(argv[a], "--append")==0) {
+ append_mode = 1;
+ ++a; --argc;
+ }
- i = atoi(argv[2]);
- if (i>1) ppem = i;
- font_path = argv[3];
+ if (argc==0) usage();
+ if (strcmp(argv[a], "--blur")==0) {
+ ++a; --argc;
+ if (argc==0) usage();
- if (argc>4) {
- d = atof(argv[4]);
- if (d>0.001 && d<1000.) alpha_factor = d;
- else WARNING("alphaFactor set to default.",NULL);
+ d = atof(argv[a]);
+ if (d>=0 && d<20) radius = d;
+ else WARNING("using default blur radius.");
+ ++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==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<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;
}