| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package SWF::Builder::Character::Font::FreeType; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
our $VERSION="0.02"; |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
#### |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
package SWF::Builder::Character::Font::Def; |
|
8
|
|
|
|
|
|
|
|
|
9
|
1
|
|
|
1
|
|
5
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
36
|
|
|
10
|
1
|
|
|
1
|
|
6
|
use utf8; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
8
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
1
|
|
|
1
|
|
20
|
use SWF::Builder::ExElement; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
67
|
|
|
13
|
1
|
|
|
1
|
|
5
|
use SWF::Builder::Shape; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
21
|
|
|
14
|
1
|
|
|
1
|
|
564
|
use Font::FreeType; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
use Carp; |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
@SWF::Builder::Character::Font::FreeType::ISA = qw/ SWF::Builder::Character::Font::Def /; |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub _init_font { |
|
20
|
|
|
|
|
|
|
my ($self, $fontfile, $fontname) = @_; |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
my $tag = $self->{_tag}; |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
my $font = Font::FreeType->new->face($fontfile, load_flags => FT_LOAD_NO_HINTING) |
|
25
|
|
|
|
|
|
|
or croak "Can't open font file '$fontfile'"; |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
if ($font->number_of_faces > 1 and $fontname and $fontname ne $font->family_name and $fontname ne $font->postscript_name) { |
|
28
|
|
|
|
|
|
|
for (my $i = 1; $i < $font->number_of_faces; $i++) { |
|
29
|
|
|
|
|
|
|
$font = Font::FreeType->new->face($fontfile, index => $i, load_flags => FT_LOAD_NO_HINTING); |
|
30
|
|
|
|
|
|
|
last if ($fontname eq $font->family_name or $fontname eq $font->postscript_name); |
|
31
|
|
|
|
|
|
|
} |
|
32
|
|
|
|
|
|
|
} |
|
33
|
|
|
|
|
|
|
$self->{_freetype} = $font; |
|
34
|
|
|
|
|
|
|
unless ($fontname ||= $font->family_name || $font->postscript_name) { |
|
35
|
|
|
|
|
|
|
($fontname) = ($fontfile =~ /.*\/([^\\\/.]+)/); |
|
36
|
|
|
|
|
|
|
} |
|
37
|
|
|
|
|
|
|
utf2bin($fontname); |
|
38
|
|
|
|
|
|
|
$tag->FontName($fontname); |
|
39
|
|
|
|
|
|
|
$font->set_char_size(72, 72, 1024, 1024); |
|
40
|
|
|
|
|
|
|
$tag->FontAscent($font->ascender); |
|
41
|
|
|
|
|
|
|
$tag->FontDescent(-$font->descender); |
|
42
|
|
|
|
|
|
|
$tag->FontLeading($font->height - $font->ascender + $font->descender); |
|
43
|
|
|
|
|
|
|
$tag->FontFlagsBold(1) if $font->is_bold; |
|
44
|
|
|
|
|
|
|
$tag->FontFlagsItalic(1) if $font->is_italic; |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
$self; |
|
47
|
|
|
|
|
|
|
} |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
sub get_fontnames { |
|
50
|
|
|
|
|
|
|
my ($self, $fontfile) = @_; |
|
51
|
|
|
|
|
|
|
my $font = Font::FreeType->new->face($fontfile) |
|
52
|
|
|
|
|
|
|
or croak "Can't open font file '$fontfile'"; |
|
53
|
|
|
|
|
|
|
my @names; |
|
54
|
|
|
|
|
|
|
for my $i (1..$font->number_of_faces) { |
|
55
|
|
|
|
|
|
|
$font = Font::FreeType->new->face($fontfile, $i); |
|
56
|
|
|
|
|
|
|
push @names, [$font->family_name, $font->postscript_name]; |
|
57
|
|
|
|
|
|
|
} |
|
58
|
|
|
|
|
|
|
return \@names; |
|
59
|
|
|
|
|
|
|
} |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
sub kern { |
|
62
|
|
|
|
|
|
|
my ($self, $code1, $code2) = @_; |
|
63
|
|
|
|
|
|
|
my $font = $self->{_freetype}; |
|
64
|
|
|
|
|
|
|
my $g1 = $font->glyph_from_char_code($code1) or return 0; |
|
65
|
|
|
|
|
|
|
my $g2 = $font->glyph_from_char_code($code2) or return 0; |
|
66
|
|
|
|
|
|
|
return $font->kerning($g1->index, $g2->index, FT_KERNING_UNFITTED ); |
|
67
|
|
|
|
|
|
|
} |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub _draw_glyph { |
|
70
|
|
|
|
|
|
|
my ($self, $c, $gshape) = @_; |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
return unless $self->{_embed}; |
|
73
|
|
|
|
|
|
|
my $g = $self->{_freetype}->glyph_from_char_code(ord $c) or return; |
|
74
|
|
|
|
|
|
|
my $gs = $gshape->transform([ScaleY=>-1]); |
|
75
|
|
|
|
|
|
|
$g->outline_decompose |
|
76
|
|
|
|
|
|
|
( move_to => sub { $gs->_moveto_twips(@_) }, |
|
77
|
|
|
|
|
|
|
line_to => sub { $gs->_lineto_twips(@_) }, |
|
78
|
|
|
|
|
|
|
conic_to => sub { my @c = splice(@_, 0, 2); $gs->_curveto_twips(@_, @c) }, |
|
79
|
|
|
|
|
|
|
cubic_to => sub { my @c = splice(@_, 0, 2); @c = map {$_/20} @_, @c; $gs->curve3to(@c) }, |
|
80
|
|
|
|
|
|
|
); |
|
81
|
|
|
|
|
|
|
return $g->horizontal_advance/20; |
|
82
|
|
|
|
|
|
|
} |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
1; |