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