upgraded to 1.0b version by Artur Zaprzala <artur.zaprzala@talex.com.pl>

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@1506 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
arpi 2001-08-13 18:37:10 +00:00
parent 8632ea0526
commit 1aef871541
11 changed files with 1587 additions and 280 deletions

View File

@ -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

View File

@ -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:

View File

@ -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)
}

View File

@ -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

View File

@ -0,0 +1 @@
gunzip -c /usr/share/i18n/charmaps/EUC-KR.gz | ./charmap2enc > euc-kr

View File

@ -0,0 +1,3 @@
Requires t1utils and python.
Based on font created by chass.

441
TOOLS/subfont-c/osd/gen.py Executable file
View File

@ -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"""

589
TOOLS/subfont-c/osd/osd.t1a Normal file
View File

@ -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

5
TOOLS/subfont-c/osd/runme Executable file
View File

@ -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

24
TOOLS/subfont-c/runme Executable file
View File

@ -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

View File

@ -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>
#endif
#ifndef DEBUG
#define DEBUG 0
#endif
#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 */
//// 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;
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];
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;
FILE *f;
FT_ULong i;
for (i = first_char; i<charset_size; ++i) text[i-first_char] = 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);
/* 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 `%s', use iconv --list to list character sets known on your system.", 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);
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!");
}
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);
// general outline
void outline(
unsigned char *s,
unsigned char *t,
int width,
int height,
int *m,
int r,
int mwidth) {
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 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;
}
// 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;
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;
}
// printf("\n");
}
free(m);
/* 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]);
}
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(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];
i = atoi(argv[2]);
if (argc==0) usage();
if (strcmp(argv[a], "--blur")==0) {
++a; --argc;
if (argc==0) usage();
d = atof(argv[a]);
if (d>=0 && d<20) radius = d;
else WARNING("using default blur radius.");
++a; --argc;
}
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[3];
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>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);
}
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;
}