From 50c753810ceba61bc57ef881057e80bd144deed8 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Sat, 25 Sep 2010 05:06:23 +0000 Subject: [PATCH] Move freetype 2 support into its own module lots of other changes in support of that --- FT2/FT2.pm | 227 ++++++++++++++++ FT2/FT2.xs | 357 +++++++++++++++++++++++++ FT2/Makefile.PL | 185 +++++++++++++ FT2/fontfiles/ExistenceTest.afm | 21 ++ FT2/fontfiles/ExistenceTest.pfb | Bin 0 -> 3186 bytes FT2/fontfiles/ExistenceTest.ttf | Bin 0 -> 1948 bytes FT2/fontfiles/ImUgly.ttf | Bin 0 -> 49104 bytes {fontfiles => FT2/fontfiles}/MMOne.pfb | Bin FT2/fontfiles/NameTest.ttf | Bin 0 -> 1820 bytes FT2/fontfiles/dodge.ttf | Bin 0 -> 11032 bytes freetyp2.c => FT2/freetyp2.c | 31 ++- FT2/imft2.h | 47 ++++ t/t38ft2font.t => FT2/t/t10ft2.t | 46 ++-- FT2/typemap | 1 + Imager.pm | 10 +- Imager.xs | 344 ------------------------ MANIFEST | 18 +- Makefile.PL | 312 ++++++++++----------- apidocs.perl | 2 +- fills.c | 92 ++++--- filters.im | 6 +- imager.h | 40 --- imageri.h | 6 + imdatatypes.h | 18 +- imext.c | 9 +- imext.h | 11 + imexttypes.h | 14 + imio.h | 7 - imperl.h | 4 - imrender.h | 23 +- io.c | 19 +- iolayer.c | 1 + lib/Imager/APIRef.pod | 96 ++++++- lib/Imager/Font.pm | 32 +-- lib/Imager/Font/FreeType2.pm | 179 +------------ paste.im | 2 + polygon.c | 1 + quant.c | 1 + regmach.c | 1 + render.im | 216 ++++++++++----- rendert.h | 10 +- t/x20spell.t | 2 + typemap | 1 - 43 files changed, 1442 insertions(+), 950 deletions(-) create mode 100644 FT2/FT2.pm create mode 100644 FT2/FT2.xs create mode 100644 FT2/Makefile.PL create mode 100644 FT2/fontfiles/ExistenceTest.afm create mode 100644 FT2/fontfiles/ExistenceTest.pfb create mode 100644 FT2/fontfiles/ExistenceTest.ttf create mode 100644 FT2/fontfiles/ImUgly.ttf rename {fontfiles => FT2/fontfiles}/MMOne.pfb (100%) create mode 100644 FT2/fontfiles/NameTest.ttf create mode 100644 FT2/fontfiles/dodge.ttf rename freetyp2.c => FT2/freetyp2.c (98%) create mode 100644 FT2/imft2.h rename t/t38ft2font.t => FT2/t/t10ft2.t (93%) create mode 100644 FT2/typemap diff --git a/FT2/FT2.pm b/FT2/FT2.pm new file mode 100644 index 00000000..118522ae --- /dev/null +++ b/FT2/FT2.pm @@ -0,0 +1,227 @@ +package Imager::Font::FT2; +use strict; +use Imager; +use vars qw($VERSION @ISA); +@ISA = qw(Imager::Font); + +BEGIN { + $VERSION = "0.77"; + + eval { + require XSLoader; + XSLoader::load('Imager::Font::FT2', $VERSION); + 1; + } or do { + require DynaLoader; + push @ISA, 'DynaLoader'; + bootstrap Imager::Font::FT2 $VERSION; + }; +} + +*_first = \&Imager::Font::_first; + +sub new { + my $class = shift; + my %hsh=(color=>Imager::Color->new(255,0,0,0), + size=>15, + @_); + + unless ($hsh{file}) { + $Imager::ERRSTR = "No font file specified"; + return; + } + unless (-e $hsh{file}) { + $Imager::ERRSTR = "Font file $hsh{file} not found"; + return; + } + unless ($Imager::formats{ft2}) { + $Imager::ERRSTR = "Freetype2 not supported in this build"; + return; + } + my $id = i_ft2_new($hsh{file}, $hsh{'index'} || 0); + unless ($id) { # the low-level code may miss some error handling + $Imager::ERRSTR = Imager::_error_as_msg(); + return; + } + return bless { + id => $id, + aa => $hsh{aa} || 0, + file => $hsh{file}, + type => 't1', + size => $hsh{size}, + color => $hsh{color}, + utf8 => $hsh{utf8}, + vlayout => $hsh{vlayout}, + }, $class; +} + +sub _draw { + my $self = shift; + my %input = @_; + if (exists $input{channel}) { + i_ft2_cp($self->{id}, $input{image}{IMG}, $input{'x'}, $input{'y'}, + $input{channel}, $input{size}, $input{sizew} || 0, + $input{string}, , $input{align}, $input{aa}, $input{vlayout}, + $input{utf8}); + } else { + i_ft2_text($self->{id}, $input{image}{IMG}, + $input{'x'}, $input{'y'}, + $input{color}, $input{size}, $input{sizew} || 0, + $input{string}, $input{align}, $input{aa}, $input{vlayout}, + $input{utf8}); + } +} + +sub _bounding_box { + my $self = shift; + my %input = @_; + + return i_ft2_bbox($self->{id}, $input{size}, $input{sizew}, $input{string}, + $input{utf8}); +} + +sub dpi { + my $self = shift; + my @old = i_ft2_getdpi($self->{id}); + if (@_) { + my %hsh = @_; + my $result; + unless ($hsh{xdpi} && $hsh{ydpi}) { + if ($hsh{dpi}) { + $hsh{xdpi} = $hsh{ydpi} = $hsh{dpi}; + } + else { + $Imager::ERRSTR = "dpi method requires xdpi and ydpi or just dpi"; + return; + } + i_ft2_setdpi($self->{id}, $hsh{xdpi}, $hsh{ydpi}) or return; + } + } + + return @old; +} + +sub hinting { + my ($self, %opts) = @_; + + i_ft2_sethinting($self->{id}, $opts{hinting} || 0); +} + +sub _transform { + my $self = shift; + + my %hsh = @_; + my $matrix = $hsh{matrix} or return undef; + + return i_ft2_settransform($self->{id}, $matrix) +} + +sub utf8 { + return 1; +} + +# check if the font has the characters in the given string +sub has_chars { + my ($self, %hsh) = @_; + + unless (defined $hsh{string} && length $hsh{string}) { + $Imager::ERRSTR = "No string supplied to \$font->has_chars()"; + return; + } + return i_ft2_has_chars($self->{id}, $hsh{string}, + _first($hsh{'utf8'}, $self->{utf8}, 0)); +} + +sub face_name { + my ($self) = @_; + + i_ft2_face_name($self->{id}); +} + +sub can_glyph_names { + i_ft2_can_do_glyph_names(); +} + +sub glyph_names { + my ($self, %input) = @_; + + my $string = $input{string}; + defined $string + or return Imager->_set_error("no string parameter passed to glyph_names"); + my $utf8 = _first($input{utf8}, 0); + my $reliable_only = _first($input{reliable_only}, 1); + + my @names = i_ft2_glyph_name($self->{id}, $string, $utf8, $reliable_only); + @names or return Imager->_set_error(Imager->_error_as_msg); + + return @names if wantarray; + return pop @names; +} + +sub is_mm { + my ($self) = @_; + + i_ft2_is_multiple_master($self->{id}); +} + +sub mm_axes { + my ($self) = @_; + + my ($num_axis, $num_design, @axes) = + i_ft2_get_multiple_masters($self->{id}) + or return Imager->_set_error(Imager->_error_as_msg); + + return @axes; +} + +sub set_mm_coords { + my ($self, %opts) = @_; + + $opts{coords} + or return Imager->_set_error("Missing coords parameter"); + ref($opts{coords}) && $opts{coords} =~ /ARRAY\(0x[\da-f]+\)$/ + or return Imager->_set_error("coords parameter must be an ARRAY ref"); + + i_ft2_set_mm_coords($self->{id}, @{$opts{coords}}) + or return Imager->_set_error(Imager->_error_as_msg); + + return 1; +} +1; + +__END__ + +=head1 NAME + +Imager::Font::FT2 - font support using FreeType 2 + +=head1 SYNOPSIS + + use Imager; + + my $img = Imager->new; + my $font = Imager::Font->new(file => "foo.ttf", type => "ft2"); + + $img->string(... font => $font); + +=head1 DESCRIPTION + +This provides font support on FreeType 2. + +=head1 CAVEATS + +Unfortunately, older versions of Imager would install +C even if FreeType 2 wasn't available, and if +no font was created would succeed in loading the module. This means +that an existing C could cause a probe success for +supported font files, so I've renamed it. + +=head1 AUTHOR + +Tony Cook + +=head1 SEE ALSO + +Imager, Imager::Font. + +=cut diff --git a/FT2/FT2.xs b/FT2/FT2.xs new file mode 100644 index 00000000..4bd18013 --- /dev/null +++ b/FT2/FT2.xs @@ -0,0 +1,357 @@ +#define PERL_NO_GET_CONTEXT +#ifdef __cplusplus +extern "C" { +#endif +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" +#include "imext.h" +#include "imperl.h" +#include "imft2.h" + +DEFINE_IMAGER_CALLBACKS; + +MODULE = Imager::Font::FT2 PACKAGE = Imager::Font::FT2x PREFIX=FT2_ + +#define FT2_DESTROY(font) i_ft2_destroy(font) + +void +FT2_DESTROY(font) + Imager::Font::FT2x font + +int +FT2_CLONE_SKIP(...) + CODE: + RETVAL = 1; + OUTPUT: + RETVAL + +MODULE = Imager::Font::FT2 PACKAGE = Imager::Font::FT2 + +Imager::Font::FT2x +i_ft2_new(name, index) + char *name + int index + +undef_int +i_ft2_setdpi(font, xdpi, ydpi) + Imager::Font::FT2x font + int xdpi + int ydpi + +void +i_ft2_getdpi(font) + Imager::Font::FT2x font + PREINIT: + int xdpi, ydpi; + CODE: + if (i_ft2_getdpi(font, &xdpi, &ydpi)) { + EXTEND(SP, 2); + PUSHs(sv_2mortal(newSViv(xdpi))); + PUSHs(sv_2mortal(newSViv(ydpi))); + } + +undef_int +i_ft2_sethinting(font, hinting) + Imager::Font::FT2x font + int hinting + +undef_int +i_ft2_settransform(font, matrix) + Imager::Font::FT2x font + PREINIT: + double matrix[6]; + int len; + AV *av; + SV *sv1; + int i; + CODE: + if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV) + croak("i_ft2_settransform: parameter 2 must be an array ref\n"); + av=(AV*)SvRV(ST(1)); + len=av_len(av)+1; + if (len > 6) + len = 6; + for (i = 0; i < len; ++i) { + sv1=(*(av_fetch(av,i,0))); + matrix[i] = SvNV(sv1); + } + for (; i < 6; ++i) + matrix[i] = 0; + RETVAL = i_ft2_settransform(font, matrix); + OUTPUT: + RETVAL + +void +i_ft2_bbox(font, cheight, cwidth, text_sv, utf8) + Imager::Font::FT2x font + double cheight + double cwidth + SV *text_sv + int utf8 + PREINIT: + int bbox[BOUNDING_BOX_COUNT]; + int i; + char *text; + STRLEN text_len; + int rc; + PPCODE: + text = SvPV(text_sv, text_len); +#ifdef SvUTF8 + if (SvUTF8(text_sv)) + utf8 = 1; +#endif + rc = i_ft2_bbox(font, cheight, cwidth, text, text_len, bbox, utf8); + if (rc) { + EXTEND(SP, rc); + for (i = 0; i < rc; ++i) + PUSHs(sv_2mortal(newSViv(bbox[i]))); + } + +void +i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8) + Imager::Font::FT2x font + double cheight + double cwidth + char *text + int vlayout + int utf8 + PREINIT: + int bbox[8]; + int i; + PPCODE: +#ifdef SvUTF8 + if (SvUTF8(ST(3))) + utf8 = 1; +#endif + if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout, + utf8, bbox)) { + EXTEND(SP, 8); + for (i = 0; i < 8; ++i) + PUSHs(sv_2mortal(newSViv(bbox[i]))); + } + +undef_int +i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8) + Imager::Font::FT2x font + Imager::ImgRaw im + int tx + int ty + Imager::Color cl + double cheight + double cwidth + int align + int aa + int vlayout + int utf8 + PREINIT: + char *text; + STRLEN len; + CODE: +#ifdef SvUTF8 + if (SvUTF8(ST(7))) { + utf8 = 1; + } +#endif + text = SvPV(ST(7), len); + RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, + len, align, aa, vlayout, utf8); + OUTPUT: + RETVAL + +undef_int +i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text_sv, align, aa, vlayout, utf8) + Imager::Font::FT2x font + Imager::ImgRaw im + int tx + int ty + int channel + double cheight + double cwidth + SV *text_sv + int align + int aa + int vlayout + int utf8 + PREINIT: + char const *text; + STRLEN len; + CODE: +#ifdef SvUTF8 + if (SvUTF8(ST(7))) + utf8 = 1; +#endif + text = SvPV(text_sv, len); + RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text, + len, align, aa, vlayout, 1); + OUTPUT: + RETVAL + +void +ft2_transform_box(font, x0, x1, x2, x3) + Imager::Font::FT2x font + int x0 + int x1 + int x2 + int x3 + PREINIT: + int box[4]; + PPCODE: + box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3; + ft2_transform_box(font, box); + EXTEND(SP, 4); + PUSHs(sv_2mortal(newSViv(box[0]))); + PUSHs(sv_2mortal(newSViv(box[1]))); + PUSHs(sv_2mortal(newSViv(box[2]))); + PUSHs(sv_2mortal(newSViv(box[3]))); + +void +i_ft2_has_chars(handle, text_sv, utf8) + Imager::Font::FT2x handle + SV *text_sv + int utf8 + PREINIT: + char *text; + STRLEN len; + char *work; + int count; + int i; + PPCODE: +#ifdef SvUTF8 + if (SvUTF8(text_sv)) + utf8 = 1; +#endif + text = SvPV(text_sv, len); + work = mymalloc(len); + count = i_ft2_has_chars(handle, text, len, utf8, work); + if (GIMME_V == G_ARRAY) { + EXTEND(SP, count); + for (i = 0; i < count; ++i) { + PUSHs(sv_2mortal(newSViv(work[i]))); + } + } + else { + EXTEND(SP, 1); + PUSHs(sv_2mortal(newSVpv(work, count))); + } + myfree(work); + +void +i_ft2_face_name(handle) + Imager::Font::FT2x handle + PREINIT: + char name[255]; + int len; + PPCODE: + len = i_ft2_face_name(handle, name, sizeof(name)); + if (len) { + EXTEND(SP, 1); + PUSHs(sv_2mortal(newSVpv(name, 0))); + } + +undef_int +i_ft2_can_face_name() + +void +i_ft2_glyph_name(handle, text_sv, utf8 = 0, reliable_only = 1) + Imager::Font::FT2x handle + SV *text_sv + int utf8 + int reliable_only + PREINIT: + char const *text; + STRLEN work_len; + size_t len; + char name[255]; + PPCODE: +#ifdef SvUTF8 + if (SvUTF8(text_sv)) + utf8 = 1; +#endif + text = SvPV(text_sv, work_len); + len = work_len; + while (len) { + unsigned long ch; + if (utf8) { + ch = i_utf8_advance(&text, &len); + if (ch == ~0UL) { + i_push_error(0, "invalid UTF8 character"); + break; + } + } + else { + ch = *text++; + --len; + } + EXTEND(SP, 1); + if (i_ft2_glyph_name(handle, ch, name, sizeof(name), + reliable_only)) { + PUSHs(sv_2mortal(newSVpv(name, 0))); + } + else { + PUSHs(&PL_sv_undef); + } + } + +int +i_ft2_can_do_glyph_names() + +int +i_ft2_face_has_glyph_names(handle) + Imager::Font::FT2x handle + +int +i_ft2_is_multiple_master(handle) + Imager::Font::FT2x handle + +void +i_ft2_get_multiple_masters(handle) + Imager::Font::FT2x handle + PREINIT: + i_font_mm mm; + int i; + PPCODE: + if (i_ft2_get_multiple_masters(handle, &mm)) { + EXTEND(SP, 2+mm.num_axis); + PUSHs(sv_2mortal(newSViv(mm.num_axis))); + PUSHs(sv_2mortal(newSViv(mm.num_designs))); + for (i = 0; i < mm.num_axis; ++i) { + AV *av = newAV(); + SV *sv; + av_extend(av, 3); + sv = newSVpv(mm.axis[i].name, strlen(mm.axis[i].name)); + SvREFCNT_inc(sv); + av_store(av, 0, sv); + sv = newSViv(mm.axis[i].minimum); + SvREFCNT_inc(sv); + av_store(av, 1, sv); + sv = newSViv(mm.axis[i].maximum); + SvREFCNT_inc(sv); + av_store(av, 2, sv); + PUSHs(newRV_noinc((SV *)av)); + } + } + +undef_int +i_ft2_set_mm_coords(handle, ...) + Imager::Font::FT2x handle + PROTOTYPE: DISABLE + PREINIT: + long *coords; + int ix_coords, i; + CODE: + /* T_ARRAY handling by xsubpp seems to be busted in 5.6.1, so + transfer the array manually */ + ix_coords = items-1; + coords = mymalloc(sizeof(long) * ix_coords); + for (i = 0; i < ix_coords; ++i) { + coords[i] = (long)SvIV(ST(1+i)); + } + RETVAL = i_ft2_set_mm_coords(handle, ix_coords, coords); + myfree(coords); + OUTPUT: + RETVAL + + +BOOT: + PERL_INITIALIZE_IMAGER_CALLBACKS; diff --git a/FT2/Makefile.PL b/FT2/Makefile.PL new file mode 100644 index 00000000..fc191364 --- /dev/null +++ b/FT2/Makefile.PL @@ -0,0 +1,185 @@ +#!perl -w +use strict; +use ExtUtils::MakeMaker qw(WriteMakefile WriteEmptyMakefile); +use Getopt::Long; +use Config; + +my $verbose = $ENV{IM_VERBOSE}; +my @libpaths; +my @incpaths; + +GetOptions("incpath=s", \@incpaths, + "libpath=s" => \@libpaths, + "verbose|v" => \$verbose); + +our $BUILDING_IMAGER; + +$DB::single = 1; + +my $MM_ver = eval $ExtUtils::MakeMaker::VERSION; + +my %opts = + ( + NAME => 'Imager::Font::FT2', + VERSION_FROM => 'FT2.pm', + OBJECT => 'FT2.o freetyp2.o', + clean => { FILES => 'testout' }, + ); + +my @inc; +if ($BUILDING_IMAGER) { + push @inc, "-I.."; + unshift @INC, "../lib"; +} +else { + unshift @INC, "inc"; + print "FreeType 2: building independently\n"; + require Imager::ExtUtils; + push @inc, Imager::ExtUtils->includes; + $opts{TYPEMAPS} = [ Imager::ExtUtils->typemap ]; + + # Imager required configure through use + my @Imager_req = ( Imager => "0.77" ); + if ($MM_ver >= 6.46) { + $opts{META_MERGE} = + { + configure_requires => + { + @Imager_req, + }, + build_requires => + { + @Imager_req, + "Test::More" => "0.47", + }, + resources => + { + homepage => "http://imager.perl.org/", + repository => + { + url => "http://imager.perl.org/svn/trunk/Imager-Font-FT2", + web => "http://imager.perl.org/svnweb/public/browse/trunk/Imager-Font-FT2", + type => "svn", + }, + }, + }; + $opts{PREREQ_PM} = + { + @Imager_req, + }; + } +} + +require Imager::Probe; + +my %probe = + ( + name => "FreeType 2", + code => \&freetype2_probe_ftconfig, + inccheck => + sub { -e File::Spec->catfile($_[0], "freetype/ftbitmap.h") }, + libbase => "freetype", + testcode => _ft2_test_code(), + testcodeheaders => [ "stdio.h", "string.h", "ft2build.h" ], + incpath => join($Config{path_sep}, @incpaths), + libpath => join($Config{path_sep}, @libpaths), + alternatives => + [ + { + incsuffix => "freetype2", + }, + { + incsuffix => "freetype", + }, + ], + ); + +my $probe_res = Imager::Probe->probe(\%probe); +if ($probe_res) { + push @inc, $probe_res->{INC}; + $opts{LIBS} = $probe_res->{LIBS}; + + $opts{INC} = "@inc"; + + if ($MM_ver > 6.06) { + $opts{AUTHOR} = 'Tony Cook '; + $opts{ABSTRACT} = 'FreeType 2 font driver for Imager'; + } + + WriteMakefile(%opts); +} +else { + if ($BUILDING_IMAGER) { + WriteEmptyMakefile(%opts); + } + else { + # fail in good way + die "OS unsupported: FreeType 2 headers/libraries not found\n"; + } +} + +sub _ft2_test_code { + return <<'CODE'; +return 0; +CODE +} + +sub is_exe { + my ($name) = @_; + + my @exe_suffix = $Config{_exe}; + if ($^O eq 'MSWin32') { + push @exe_suffix, qw/.bat .cmd/; + } + + for my $dir (File::Spec->path) { + for my $suffix (@exe_suffix) { + -x catfile($dir, "$name$suffix") + and return 1; + } + } + + return; +} + +# probes for freetype2 by trying to run freetype-config +sub freetype2_probe_ftconfig { + my ($req) = @_; + + is_exe('freetype-config') or return; + + my $cflags = `freetype-config --cflags` + and !$? or return; + chomp $cflags; + + my $lflags = `freetype-config --libs` + and !$? or return; + chomp $lflags; + + # before 2.1.5 freetype-config --cflags could output + # the -I options in the wrong order, causing a conflict with + # freetype1.x installed with the same --prefix + # + # can happen iff: + # - both -Iprefix/include and -Iprefix/include/freetype2 are in cflags + # in that order + # - freetype 1.x headers are in prefix/include/freetype + my @incdirs = map substr($_, 2), grep /^-I/, split ' ', $cflags; + if (@incdirs == 2 + && $incdirs[1] eq "$incdirs[0]/freetype2" + && -e "$incdirs[0]/freetype/freetype.h" + && -e "$incdirs[0]/freetype/fterrid.h") { + print "** freetype-config provided -I options out of order, correcting\n" + if $verbose; + $cflags = join(' ', grep(!/-I/, split ' ', $cflags), + map "-I$_", reverse @incdirs); + } + + print "$req->{name}: configured via freetype-config\n"; + + return + { + INC => $cflags, + LIBS => $lflags, + }; +} diff --git a/FT2/fontfiles/ExistenceTest.afm b/FT2/fontfiles/ExistenceTest.afm new file mode 100644 index 00000000..5200705a --- /dev/null +++ b/FT2/fontfiles/ExistenceTest.afm @@ -0,0 +1,21 @@ +StartFontMetrics 2.0 +Comment Generated by pfaedit +Comment Creation Date: Thu Jul 20 21:57:23 2006 +FontName ExistenceTest +FullName ExistenceTest +FamilyName ExistenceTest +Weight Medium +Notice (Created by Tony Cook,,, with PfaEdit 1.0 (http://pfaedit.sf.net)) +ItalicAngle 0 +IsFixedPitch false +UnderlinePosition -100 +UnderlineThickness 50 +Version 001.000 +EncodingScheme AdobeStandardEncoding +FontBBox -60 -55 819 775 +StartCharMetrics 3 +C 0 ; WX 487 ; N uniFFFD ; B 72 87 414 396 ; +C 33 ; WX 310 ; N exclam ; B 51 0 207 738 ; +C 47 ; WX 761 ; N slash ; B -60 -55 819 775 ; +EndCharMetrics +EndFontMetrics diff --git a/FT2/fontfiles/ExistenceTest.pfb b/FT2/fontfiles/ExistenceTest.pfb new file mode 100644 index 0000000000000000000000000000000000000000..88863ad502d7f6f0a2fbd5364633b0c16ee2f3c2 GIT binary patch literal 3186 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 PHzNP+brSi{qM_|?acwo) literal 0 HcmV?d00001 diff --git a/FT2/fontfiles/ImUgly.ttf b/FT2/fontfiles/ImUgly.ttf new file mode 100644 index 0000000000000000000000000000000000000000..eb073931ef25538bdd5dfedb88a0b7e89070b3d5 GIT binary patch literal 49104 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 EZ>Vqc1^@s6 literal 0 HcmV?d00001 diff --git a/FT2/fontfiles/dodge.ttf b/FT2/fontfiles/dodge.ttf new file mode 100644 index 0000000000000000000000000000000000000000..132b95b530ce24abca98963d52a0c46311008269 GIT binary patch literal 11032 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 literal 0 HcmV?d00001 diff --git a/freetyp2.c b/FT2/freetyp2.c similarity index 98% rename from freetyp2.c rename to FT2/freetyp2.c index 5076040d..8d034f9d 100644 --- a/freetyp2.c +++ b/FT2/freetyp2.c @@ -34,8 +34,10 @@ Truetype, Type1 and Windows FNT. =cut */ -#include "imager.h" +#include "imext.h" +#include "imft2.h" #include +#include #include #include FT_FREETYPE_H #ifdef FT_MULTIPLE_MASTERS_H @@ -50,6 +52,9 @@ static void ft2_push_message(int code); static int ft2_initialized = 0; static FT_Library library; +static int i_min(int a, int b); +static int i_max(int a, int b); + /* =item i_ft2_init(void) @@ -650,7 +655,7 @@ i_ft2_text(FT2_Fonthandle *handle, i_img *im, int tx, int ty, const i_color *cl, char last_mode = ft_pixel_mode_none; int last_grays = -1; int loadFlags = FT_LOAD_DEFAULT; - i_render render; + i_render *render; mm_log((1, "i_ft2_text(handle %p, im %p, tx %d, ty %d, cl %p, cheight %f, cwidth %f, text %p, len %d, align %d, aa %d)\n", handle, im, tx, ty, cl, cheight, cwidth, text, align, aa)); @@ -670,7 +675,7 @@ i_ft2_text(FT2_Fonthandle *handle, i_img *im, int tx, int ty, const i_color *cl, return 0; if (aa) - i_render_init(&render, im, bbox[BBOX_POS_WIDTH] - bbox[BBOX_NEG_WIDTH]); + render = i_render_new(im, bbox[BBOX_POS_WIDTH] - bbox[BBOX_NEG_WIDTH]); if (!align) { /* this may need adjustment */ @@ -698,7 +703,7 @@ i_ft2_text(FT2_Fonthandle *handle, i_img *im, int tx, int ty, const i_color *cl, i_push_errorf(0, "loading glyph for character \\x%02x (glyph 0x%04X)", c, index); if (aa) - i_render_done(&render); + i_render_delete(render); return 0; } slot = handle->face->glyph; @@ -710,7 +715,7 @@ i_ft2_text(FT2_Fonthandle *handle, i_img *im, int tx, int ty, const i_color *cl, ft2_push_message(error); i_push_errorf(0, "rendering glyph 0x%04X (character \\x%02X)"); if (aa) - i_render_done(&render); + i_render_delete(render); return 0; } if (slot->bitmap.pixel_mode == ft_pixel_mode_mono) { @@ -749,7 +754,7 @@ i_ft2_text(FT2_Fonthandle *handle, i_img *im, int tx, int ty, const i_color *cl, for (x = 0; x < slot->bitmap.width; ++x) bmp[x] = map[bmp[x]]; } - i_render_color(&render, tx + slot->bitmap_left, ty-slot->bitmap_top+y, + i_render_color(render, tx + slot->bitmap_left, ty-slot->bitmap_top+y, slot->bitmap.width, bmp, cl); bmp += slot->bitmap.pitch; } @@ -761,7 +766,7 @@ i_ft2_text(FT2_Fonthandle *handle, i_img *im, int tx, int ty, const i_color *cl, } if (aa) - i_render_done(&render); + i_render_delete(render); return 1; } @@ -804,7 +809,7 @@ i_ft2_cp(FT2_Fonthandle *handle, i_img *im, int tx, int ty, int channel, if (!i_ft2_bbox_r(handle, cheight, cwidth, text, len, vlayout, utf8, bbox)) return 0; - work = i_img_empty_ch(NULL, bbox[2]-bbox[0]+1, bbox[3]-bbox[1]+1, 1); + work = i_img_8_new(bbox[2]-bbox[0]+1, bbox[3]-bbox[1]+1, 1); cl.channel[0] = 255; if (!i_ft2_text(handle, work, -bbox[0], -bbox[1], &cl, cheight, cwidth, text, len, 1, aa, vlayout, utf8)) @@ -1129,6 +1134,16 @@ i_ft2_set_mm_coords(FT2_Fonthandle *handle, int coord_count, const long *coords) #endif } +static int +i_min(int a, int b) { + return a < b ? a : b; +} + +static int +i_max(int a, int b) { + return a > b ? a : b; +} + /* =back diff --git a/FT2/imft2.h b/FT2/imft2.h new file mode 100644 index 00000000..b283c628 --- /dev/null +++ b/FT2/imft2.h @@ -0,0 +1,47 @@ +#ifndef IMAGER_FT2_H +#define IMAGER_FT2_H + +#include "imdatatypes.h" + +typedef struct FT2_Fonthandle FT2_Fonthandle; + +typedef FT2_Fonthandle* Imager__Font__FT2x; + +extern int i_ft2_init(void); +extern FT2_Fonthandle * i_ft2_new(const char *name, int index); +extern void i_ft2_destroy(FT2_Fonthandle *handle); +extern int i_ft2_setdpi(FT2_Fonthandle *handle, int xdpi, int ydpi); +extern int i_ft2_getdpi(FT2_Fonthandle *handle, int *xdpi, int *ydpi); +extern int i_ft2_settransform(FT2_Fonthandle *handle, const double *matrix); +extern int i_ft2_sethinting(FT2_Fonthandle *handle, int hinting); +extern int i_ft2_bbox(FT2_Fonthandle *handle, double cheight, double cwidth, + char const *text, size_t len, int *bbox, int utf8); +extern int i_ft2_bbox_r(FT2_Fonthandle *handle, double cheight, double cwidth, + char const *text, size_t len, int vlayout, int utf8, int *bbox); +extern int i_ft2_text(FT2_Fonthandle *handle, i_img *im, int tx, int ty, + const i_color *cl, double cheight, double cwidth, + char const *text, size_t len, int align, int aa, + int vlayout, int utf8); +extern int i_ft2_cp(FT2_Fonthandle *handle, i_img *im, int tx, int ty, + int channel, double cheight, double cwidth, + char const *text, size_t len, int align, int aa, + int vlayout, int utf8); +extern int i_ft2_has_chars(FT2_Fonthandle *handle, char const *text, size_t len, + int utf8, char *work); +extern int i_ft2_face_name(FT2_Fonthandle *handle, char *name_buf, + size_t name_buf_size); +extern int i_ft2_can_face_name(void); +extern int i_ft2_glyph_name(FT2_Fonthandle *handle, unsigned long ch, + char *name_buf, size_t name_buf_size, + int reliable_only); +extern int i_ft2_can_do_glyph_names(void); +extern int i_ft2_face_has_glyph_names(FT2_Fonthandle *handle); + +extern int i_ft2_get_multiple_masters(FT2_Fonthandle *handle, + i_font_mm *mm); +extern int +i_ft2_is_multiple_master(FT2_Fonthandle *handle); +extern int +i_ft2_set_mm_coords(FT2_Fonthandle *handle, int coord_count, const long *coords); +#endif + diff --git a/t/t38ft2font.t b/FT2/t/t10ft2.t similarity index 93% rename from t/t38ft2font.t rename to FT2/t/t10ft2.t index 85f8ed6b..e8546ebb 100644 --- a/t/t38ft2font.t +++ b/FT2/t/t10ft2.t @@ -2,19 +2,13 @@ use strict; use Test::More tests => 189; use Cwd qw(getcwd abs_path); -++$|; -# Before `make install' is performed this script should be runnable with -# `make test'. After `make install' it should work as `perl test.pl' -######################### We start with some black magic to print on failure. - -# Change 1..1 below to 1..last_test_to_print . -# (It may become useful if the test is moved to ./t subdirectory.) - -BEGIN { use_ok(Imager => ':all') } +use Imager qw(:all); use Imager::Test qw(diff_text_with_nul is_color3); +-d "testout" or mkdir "testout"; + init_log("testout/t38ft2font.log",2); my $deffont = "fontfiles/dodge.ttf"; @@ -23,10 +17,8 @@ my @base_color = (64, 255, 64); SKIP: { - i_has_format("ft2") or skip("no freetype2 library found", 188); + ok($Imager::formats{ft2}, "ft2 should be in %formats"); - print "# has ft2\n"; - my $fontname=$ENV{'TTFONTTEST'} || $deffont; -f $fontname or skip("cannot find fontfile $fontname", 188); @@ -35,17 +27,17 @@ SKIP: my $bgcolor=i_color_new(255,0,0,0); my $overlay=Imager::ImgRaw::new(200,70,3); - my $ttraw=Imager::Font::FreeType2::i_ft2_new($fontname, 0); + my $ttraw=Imager::Font::FT2::i_ft2_new($fontname, 0); $ttraw or print Imager::_error_as_msg(),"\n"; ok($ttraw, "loaded raw font"); - my @bbox=Imager::Font::FreeType2::i_ft2_bbox($ttraw, 50.0, 0, 'XMCLH', 0); + my @bbox=Imager::Font::FT2::i_ft2_bbox($ttraw, 50.0, 0, 'XMCLH', 0); print "#bbox @bbox\n"; is(@bbox, 8, "i_ft2_bbox() returns 8 values"); - ok(Imager::Font::FreeType2::i_ft2_cp($ttraw,$overlay,5,50,1,50.0,50, 'XMCLH',1,1, 0, 0), "drawn to channel"); + ok(Imager::Font::FT2::i_ft2_cp($ttraw,$overlay,5,50,1,50.0,50, 'XMCLH',1,1, 0, 0), "drawn to channel"); i_line($overlay,0,50,100,50,$bgcolor,1); open(FH,">testout/t38ft2font.ppm") || die "cannot open testout/t38ft2font.ppm\n"; @@ -58,9 +50,9 @@ SKIP: my $backgr=Imager::ImgRaw::new(500,300,3); # i_tt_set_aa(2); - ok(Imager::Font::FreeType2::i_ft2_text($ttraw,$backgr,100,150,NC(255, 64, 64),200.0,50, 'MAW',1,1,0, 0), "drew MAW"); - Imager::Font::FreeType2::i_ft2_settransform($ttraw, [0.9659, 0.2588, 0, -0.2588, 0.9659, 0 ]); - ok(Imager::Font::FreeType2::i_ft2_text($ttraw,$backgr,100,150,NC(0, 128, 0),200.0,50, 'MAW',0,1, 0, 0), "drew rotated MAW"); + ok(Imager::Font::FT2::i_ft2_text($ttraw,$backgr,100,150,NC(255, 64, 64),200.0,50, 'MAW',1,1,0, 0), "drew MAW"); + Imager::Font::FT2::i_ft2_settransform($ttraw, [0.9659, 0.2588, 0, -0.2588, 0.9659, 0 ]); + ok(Imager::Font::FT2::i_ft2_text($ttraw,$backgr,100,150,NC(0, 128, 0),200.0,50, 'MAW',0,1, 0, 0), "drew rotated MAW"); i_line($backgr, 0,150, 499, 150, NC(0, 0, 255),1); open(FH,">testout/t38ft2font2.ppm") || die "cannot open testout/t38ft2font.ppm\n"; @@ -228,8 +220,10 @@ SKIP: type=>'ft2'); SKIP: { - ok($exfont, "loaded existence font") or - skip("couldn't load test font", 11); + ok($exfont, "loaded existence font") + or diag(Imager->errstr); + $exfont + or skip("couldn't load test font", 11); # the test font is known to have a shorter advance width for that char my @bbox = $exfont->bounding_box(string=>"/", size=>100); @@ -255,8 +249,8 @@ SKIP: # name tests # make sure the number of tests on each branch match - if (Imager::Font::FreeType2::i_ft2_can_face_name()) { - my $facename = Imager::Font::FreeType2::i_ft2_face_name($exfont->{id}); + if (Imager::Font::FT2::i_ft2_can_face_name()) { + my $facename = Imager::Font::FT2::i_ft2_face_name($exfont->{id}); print "# face name '$facename'\n"; is($facename, 'ExistenceTest', "test face name"); $facename = $exfont->face_name; @@ -264,7 +258,7 @@ SKIP: } else { # make sure we get the error we expect - my $facename = Imager::Font::FreeType2::i_ft2_face_name($exfont->{id}); + my $facename = Imager::Font::FT2::i_ft2_face_name($exfont->{id}); my ($msg) = Imager::_error_as_msg(); ok(!defined($facename), "test face name not supported"); print "# $msg\n"; @@ -274,7 +268,7 @@ SKIP: SKIP: { - Imager::Font::FreeType2->can_glyph_names + Imager::Font::FT2->can_glyph_names or skip("FT2 compiled without glyph names support", 9); # FT2 considers POST tables in TTF fonts unreliable, so use @@ -286,7 +280,7 @@ SKIP: ok($exfont, "load Type 1 via FT2") or skip("couldn't load type 1 with FT2", 8); my @glyph_names = - Imager::Font::FreeType2::i_ft2_glyph_name($exfont->{id}, "!J/"); + Imager::Font::FT2::i_ft2_glyph_name($exfont->{id}, "!J/"); #use Data::Dumper; #print Dumper \@glyph_names; is($glyph_names[0], 'exclam', "check exclam name"); @@ -331,7 +325,7 @@ SKIP: } # check that error codes are translated correctly - my $errfont = Imager::Font->new(file=>"t/t38ft2font.t", type=>"ft2"); + my $errfont = Imager::Font->new(file=>"t/t10ft2.t", type=>"ft2"); is($errfont, undef, "new font vs non font"); cmp_ok(Imager->errstr, '=~', qr/unknown file format/, "check error message"); diff --git a/FT2/typemap b/FT2/typemap new file mode 100644 index 00000000..385fb650 --- /dev/null +++ b/FT2/typemap @@ -0,0 +1 @@ +Imager::Font::FT2x T_PTROBJ diff --git a/Imager.pm b/Imager.pm index 7349469e..c6bd71a4 100644 --- a/Imager.pm +++ b/Imager.pm @@ -1,7 +1,7 @@ package Imager; use strict; -use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR $fontstate %OPCODES $I2P $FORMATGUESS $warn_obsolete); +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR %OPCODES $I2P $FORMATGUESS $warn_obsolete); use IO::File; use Imager::Color; @@ -175,18 +175,14 @@ my %format_classes = tiff => "Imager::File::TIFF", jpeg => "Imager::File::JPEG", w32 => "Imager::Font::W32", + ft2 => "Imager::Font::FT2", ); tie %formats, "Imager::FORMATS", \%formats_low, \%format_classes; BEGIN { - Imager::Font::__init(); for(i_list_formats()) { $formats_low{$_}++; } - if (!$formats_low{'t1'} and !$formats_low{'tt'} - && !$formats_low{'ft2'} && !$formats_low{'w32'}) { - $fontstate='no font support'; - } %OPCODES=(Add=>[0],Sub=>[1],Mult=>[2],Div=>[3],Parm=>[4],'sin'=>[5],'cos'=>[6],'x'=>[4,0],'y'=>[4,1]); $DEBUG=0; @@ -3907,8 +3903,6 @@ sub _check { sub FETCH { my ($self, $key) = @_; - $DB::single = 1; - exists $self->[IX_FORMATS]{$key} and return $self->[IX_FORMATS]{$key}; $self->[IX_CLASSES]{$key} or return undef; diff --git a/Imager.xs b/Imager.xs index 734a3078..970d7df6 100644 --- a/Imager.xs +++ b/Imager.xs @@ -3809,350 +3809,6 @@ i_tags_count(im) RETVAL -#ifdef HAVE_FT2 - -MODULE = Imager PACKAGE = Imager::Font::FT2 PREFIX=FT2_ - -#define FT2_DESTROY(font) i_ft2_destroy(font) - -void -FT2_DESTROY(font) - Imager::Font::FT2 font - -int -FT2_CLONE_SKIP(...) - CODE: - RETVAL = 1; - OUTPUT: - RETVAL - -MODULE = Imager PACKAGE = Imager::Font::FreeType2 - -Imager::Font::FT2 -i_ft2_new(name, index) - char *name - int index - -undef_int -i_ft2_setdpi(font, xdpi, ydpi) - Imager::Font::FT2 font - int xdpi - int ydpi - -void -i_ft2_getdpi(font) - Imager::Font::FT2 font - PREINIT: - int xdpi, ydpi; - CODE: - if (i_ft2_getdpi(font, &xdpi, &ydpi)) { - EXTEND(SP, 2); - PUSHs(sv_2mortal(newSViv(xdpi))); - PUSHs(sv_2mortal(newSViv(ydpi))); - } - -undef_int -i_ft2_sethinting(font, hinting) - Imager::Font::FT2 font - int hinting - -undef_int -i_ft2_settransform(font, matrix) - Imager::Font::FT2 font - PREINIT: - double matrix[6]; - int len; - AV *av; - SV *sv1; - int i; - CODE: - if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV) - croak("i_ft2_settransform: parameter 2 must be an array ref\n"); - av=(AV*)SvRV(ST(1)); - len=av_len(av)+1; - if (len > 6) - len = 6; - for (i = 0; i < len; ++i) { - sv1=(*(av_fetch(av,i,0))); - matrix[i] = SvNV(sv1); - } - for (; i < 6; ++i) - matrix[i] = 0; - RETVAL = i_ft2_settransform(font, matrix); - OUTPUT: - RETVAL - -void -i_ft2_bbox(font, cheight, cwidth, text_sv, utf8) - Imager::Font::FT2 font - double cheight - double cwidth - SV *text_sv - int utf8 - PREINIT: - int bbox[BOUNDING_BOX_COUNT]; - int i; - char *text; - STRLEN text_len; - int rc; - PPCODE: - text = SvPV(text_sv, text_len); -#ifdef SvUTF8 - if (SvUTF8(text_sv)) - utf8 = 1; -#endif - rc = i_ft2_bbox(font, cheight, cwidth, text, text_len, bbox, utf8); - if (rc) { - EXTEND(SP, rc); - for (i = 0; i < rc; ++i) - PUSHs(sv_2mortal(newSViv(bbox[i]))); - } - -void -i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8) - Imager::Font::FT2 font - double cheight - double cwidth - char *text - int vlayout - int utf8 - PREINIT: - int bbox[8]; - int i; - PPCODE: -#ifdef SvUTF8 - if (SvUTF8(ST(3))) - utf8 = 1; -#endif - if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout, - utf8, bbox)) { - EXTEND(SP, 8); - for (i = 0; i < 8; ++i) - PUSHs(sv_2mortal(newSViv(bbox[i]))); - } - -undef_int -i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8) - Imager::Font::FT2 font - Imager::ImgRaw im - int tx - int ty - Imager::Color cl - double cheight - double cwidth - int align - int aa - int vlayout - int utf8 - PREINIT: - char *text; - STRLEN len; - CODE: -#ifdef SvUTF8 - if (SvUTF8(ST(7))) { - utf8 = 1; - } -#endif - text = SvPV(ST(7), len); - RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, - len, align, aa, vlayout, utf8); - OUTPUT: - RETVAL - -undef_int -i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text_sv, align, aa, vlayout, utf8) - Imager::Font::FT2 font - Imager::ImgRaw im - int tx - int ty - int channel - double cheight - double cwidth - SV *text_sv - int align - int aa - int vlayout - int utf8 - PREINIT: - char const *text; - STRLEN len; - CODE: -#ifdef SvUTF8 - if (SvUTF8(ST(7))) - utf8 = 1; -#endif - text = SvPV(text_sv, len); - RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text, - len, align, aa, vlayout, 1); - OUTPUT: - RETVAL - -void -ft2_transform_box(font, x0, x1, x2, x3) - Imager::Font::FT2 font - int x0 - int x1 - int x2 - int x3 - PREINIT: - int box[4]; - PPCODE: - box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3; - ft2_transform_box(font, box); - EXTEND(SP, 4); - PUSHs(sv_2mortal(newSViv(box[0]))); - PUSHs(sv_2mortal(newSViv(box[1]))); - PUSHs(sv_2mortal(newSViv(box[2]))); - PUSHs(sv_2mortal(newSViv(box[3]))); - -void -i_ft2_has_chars(handle, text_sv, utf8) - Imager::Font::FT2 handle - SV *text_sv - int utf8 - PREINIT: - char *text; - STRLEN len; - char *work; - int count; - int i; - PPCODE: -#ifdef SvUTF8 - if (SvUTF8(text_sv)) - utf8 = 1; -#endif - text = SvPV(text_sv, len); - work = mymalloc(len); - count = i_ft2_has_chars(handle, text, len, utf8, work); - if (GIMME_V == G_ARRAY) { - EXTEND(SP, count); - for (i = 0; i < count; ++i) { - PUSHs(sv_2mortal(newSViv(work[i]))); - } - } - else { - EXTEND(SP, 1); - PUSHs(sv_2mortal(newSVpv(work, count))); - } - myfree(work); - -void -i_ft2_face_name(handle) - Imager::Font::FT2 handle - PREINIT: - char name[255]; - int len; - PPCODE: - len = i_ft2_face_name(handle, name, sizeof(name)); - if (len) { - EXTEND(SP, 1); - PUSHs(sv_2mortal(newSVpv(name, 0))); - } - -undef_int -i_ft2_can_face_name() - -void -i_ft2_glyph_name(handle, text_sv, utf8 = 0, reliable_only = 1) - Imager::Font::FT2 handle - SV *text_sv - int utf8 - int reliable_only - PREINIT: - char const *text; - STRLEN work_len; - size_t len; - char name[255]; - PPCODE: -#ifdef SvUTF8 - if (SvUTF8(text_sv)) - utf8 = 1; -#endif - text = SvPV(text_sv, work_len); - len = work_len; - while (len) { - unsigned long ch; - if (utf8) { - ch = i_utf8_advance(&text, &len); - if (ch == ~0UL) { - i_push_error(0, "invalid UTF8 character"); - break; - } - } - else { - ch = *text++; - --len; - } - EXTEND(SP, 1); - if (i_ft2_glyph_name(handle, ch, name, sizeof(name), - reliable_only)) { - PUSHs(sv_2mortal(newSVpv(name, 0))); - } - else { - PUSHs(&PL_sv_undef); - } - } - -int -i_ft2_can_do_glyph_names() - -int -i_ft2_face_has_glyph_names(handle) - Imager::Font::FT2 handle - -int -i_ft2_is_multiple_master(handle) - Imager::Font::FT2 handle - -void -i_ft2_get_multiple_masters(handle) - Imager::Font::FT2 handle - PREINIT: - i_font_mm mm; - int i; - PPCODE: - if (i_ft2_get_multiple_masters(handle, &mm)) { - EXTEND(SP, 2+mm.num_axis); - PUSHs(sv_2mortal(newSViv(mm.num_axis))); - PUSHs(sv_2mortal(newSViv(mm.num_designs))); - for (i = 0; i < mm.num_axis; ++i) { - AV *av = newAV(); - SV *sv; - av_extend(av, 3); - sv = newSVpv(mm.axis[i].name, strlen(mm.axis[i].name)); - SvREFCNT_inc(sv); - av_store(av, 0, sv); - sv = newSViv(mm.axis[i].minimum); - SvREFCNT_inc(sv); - av_store(av, 1, sv); - sv = newSViv(mm.axis[i].maximum); - SvREFCNT_inc(sv); - av_store(av, 2, sv); - PUSHs(newRV_noinc((SV *)av)); - } - } - -undef_int -i_ft2_set_mm_coords(handle, ...) - Imager::Font::FT2 handle - PROTOTYPE: DISABLE - PREINIT: - long *coords; - int ix_coords, i; - CODE: - /* T_ARRAY handling by xsubpp seems to be busted in 5.6.1, so - transfer the array manually */ - ix_coords = items-1; - coords = mymalloc(sizeof(long) * ix_coords); - for (i = 0; i < ix_coords; ++i) { - coords[i] = (long)SvIV(ST(1+i)); - } - RETVAL = i_ft2_set_mm_coords(handle, ix_coords, coords); - myfree(coords); - OUTPUT: - RETVAL - -#endif MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_ diff --git a/MANIFEST b/MANIFEST index 1663c43f..dc9d06ef 100644 --- a/MANIFEST +++ b/MANIFEST @@ -9,6 +9,19 @@ DynTest/DynTest.xs DynTest/Makefile.PL DynTest/linstretch.c DynTest/t/t00dyntest.t +FT2/Makefile.PL +FT2/FT2.pm +FT2/FT2.xs +FT2/freetyp2.c Implements freetype2 font support +FT2/fontfiles/dodge.ttf +FT2/fontfiles/ExistenceTest.afm +FT2/fontfiles/ExistenceTest.pfb +FT2/fontfiles/ExistenceTest.ttf +FT2/fontfiles/ImUgly.ttf +FT2/fontfiles/MMOne.pfb multiple master test font +FT2/fontfiles/NameTest.ttf +FT2/imft2.h +FT2/typemap Flines/Flines.pm Flines/Flines.xs Flines/Makefile.PL @@ -192,14 +205,12 @@ fontfiles/ExistenceTest.afm please edit ExistenceTest.sfd in CVS fontfiles/ExistenceTest.pfb to change these files, edited and fontfiles/ExistenceTest.ttf generated using pfaedit fontfiles/ImUgly.ttf -fontfiles/MMOne.pfb multiple master test font -fontfiles/NameTest.ttf test glyph_names() - see t38ft2font.t +fontfiles/NameTest.ttf test glyph_names() - see FT2/t/t10ft2.t fontfiles/SpaceTest.afm fontfiles/SpaceTest.pfb test bounding box with spaces in t30t1font.t fontfiles/dcr10.afm fontfiles/dcr10.pfb fontfiles/dodge.ttf -freetyp2.c Implements freetype2 font support gaussian.im hlines.c Manage sets of horizontal line segments image.c @@ -329,7 +340,6 @@ t/t21draw.t Basic drawing tests t/t30t1font.t t/t35ttfont.t t/t36oofont.t -t/t38ft2font.t Tests freetype2 support t/t40scale.t t/t50basicoo.t t/t55trans.t diff --git a/Makefile.PL b/Makefile.PL index 7ddb5dd4..8b9a8db1 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -641,25 +641,25 @@ are alot of badly designed fonts out there.} # This currently only works on under normal Win32 and cygwin. # DOCS # }; - $formats{'freetype2'} = - { - order=>'29', - def=>'HAVE_FT2', - # we always use a probe function - #inccheck=>sub { -e catfile($_[0], 'ft2build.h') }, - #libcheck=>sub { $_[0] eq "libfreetype$aext" or $_[0] eq "libfreetype.$lext" }, - libfiles=>'-lfreetype', - objfiles=>'freetyp2.o', - docs=>< - [ - \&freetype2_probe_ftconfig, - \&freetype2_probe_scan - ], - }; +# $formats{'freetype2'} = +# { +# order=>'29', +# def=>'HAVE_FT2', +# # we always use a probe function +# #inccheck=>sub { -e catfile($_[0], 'ft2build.h') }, +# #libcheck=>sub { $_[0] eq "libfreetype$aext" or $_[0] eq "libfreetype.$lext" }, +# libfiles=>'-lfreetype', +# objfiles=>'freetyp2.o', +# docs=>< +# [ +# \&freetype2_probe_ftconfig, +# \&freetype2_probe_scan +# ], +# }; # Make fix indent for (keys %formats) { $formats{$_}->{docs} =~ s/^\s+/ /mg; } @@ -726,17 +726,17 @@ EOS close CONFIG; } -# use pkg-config to probe for libraries -# works around the junk that pkg-config dumps on FreeBSD -sub _pkg_probe { - my ($pkg) = @_; +# # use pkg-config to probe for libraries +# # works around the junk that pkg-config dumps on FreeBSD +# sub _pkg_probe { +# my ($pkg) = @_; - is_exe('pkg-config') or return; +# is_exe('pkg-config') or return; - my $redir = $^O eq 'MSWin32' ? '' : '2>/dev/null'; +# my $redir = $^O eq 'MSWin32' ? '' : '2>/dev/null'; - !system("pkg-config $pkg --exists $redir"); -} +# !system("pkg-config $pkg --exists $redir"); +# } # probes for freetype1 by scanning @incs for the includes and # @libs for the libs. This is done separately because freetype's headers @@ -787,111 +787,111 @@ sub freetype1_probe { } # probes for freetype2 by trying to run freetype-config -sub freetype2_probe_ftconfig { - my ($frm, $frmkey) = @_; - - is_exe('freetype-config') or return; - - my $cflags = `freetype-config --cflags` - and !$? or return; - chomp $cflags; - - my $lflags = `freetype-config --libs` - and !$? or return; - chomp $lflags; - - # before 2.1.5 freetype-config --cflags could output - # the -I options in the wrong order, causing a conflict with - # freetype1.x installed with the same --prefix - # - # can happen iff: - # - both -Iprefix/include and -Iprefix/include/freetype2 are in cflags - # in that order - # - freetype 1.x headers are in prefix/include/freetype - my @incdirs = map substr($_, 2), grep /^-I/, split ' ', $cflags; - if (@incdirs == 2 - && $incdirs[1] eq "$incdirs[0]/freetype2" - && -e "$incdirs[0]/freetype/freetype.h" - && -e "$incdirs[0]/freetype/fterrid.h") { - print "** freetype-config provided -I options out of order, correcting\n" - if $VERBOSE; - $cflags = join(' ', grep(!/-I/, split ' ', $cflags), - map "-I$_", reverse @incdirs); - } - $frm->{cflags} = $cflags; - $frm->{lflags} = $lflags; +# sub freetype2_probe_ftconfig { +# my ($frm, $frmkey) = @_; + +# is_exe('freetype-config') or return; + +# my $cflags = `freetype-config --cflags` +# and !$? or return; +# chomp $cflags; + +# my $lflags = `freetype-config --libs` +# and !$? or return; +# chomp $lflags; + +# # before 2.1.5 freetype-config --cflags could output +# # the -I options in the wrong order, causing a conflict with +# # freetype1.x installed with the same --prefix +# # +# # can happen iff: +# # - both -Iprefix/include and -Iprefix/include/freetype2 are in cflags +# # in that order +# # - freetype 1.x headers are in prefix/include/freetype +# my @incdirs = map substr($_, 2), grep /^-I/, split ' ', $cflags; +# if (@incdirs == 2 +# && $incdirs[1] eq "$incdirs[0]/freetype2" +# && -e "$incdirs[0]/freetype/freetype.h" +# && -e "$incdirs[0]/freetype/fterrid.h") { +# print "** freetype-config provided -I options out of order, correcting\n" +# if $VERBOSE; +# $cflags = join(' ', grep(!/-I/, split ' ', $cflags), +# map "-I$_", reverse @incdirs); +# } +# $frm->{cflags} = $cflags; +# $frm->{lflags} = $lflags; - printf "%10s: configured via freetype-config\n", $frmkey; +# printf "%10s: configured via freetype-config\n", $frmkey; - return 1; -} +# return 1; +# } # attempt to probe for freetype2 by scanning directories # we can't use the normal scan since we need to find the directory # containing most of the includes -sub freetype2_probe_scan { - my ($frm, $frmkey) = @_; - - my $found_inc; - my $found_inc2; - INCS: - for my $inc (@incs) { - my $path = File::Spec->catfile($inc, 'ft2build.h'); - -e $path or next; - - # try to find what it's including - my $ftheader; - open FT2BUILD, "< $path" - or next; - while () { - if (m!^\s*\#\s*include\s+<([\w/.]+)>! - || m!^\s*\#\s*include\s+"([\w/.]+)"!) { - $ftheader = $1; - last; - } - } - close FT2BUILD; - $ftheader - or next; - # non-Unix installs put this directly under the same directory in - # theory - if (-e File::Spec->catfile($inc, $ftheader)) { - $found_inc = $inc; - last INCS; - } - for my $subdir (qw/freetype2 freetype/) { - $path = File::Spec->catfile($inc, $subdir, 'fterrors.h'); - -e $path and next; +# sub freetype2_probe_scan { +# my ($frm, $frmkey) = @_; + +# my $found_inc; +# my $found_inc2; +# INCS: +# for my $inc (@incs) { +# my $path = File::Spec->catfile($inc, 'ft2build.h'); +# -e $path or next; + +# # try to find what it's including +# my $ftheader; +# open FT2BUILD, "< $path" +# or next; +# while () { +# if (m!^\s*\#\s*include\s+<([\w/.]+)>! +# || m!^\s*\#\s*include\s+"([\w/.]+)"!) { +# $ftheader = $1; +# last; +# } +# } +# close FT2BUILD; +# $ftheader +# or next; +# # non-Unix installs put this directly under the same directory in +# # theory +# if (-e File::Spec->catfile($inc, $ftheader)) { +# $found_inc = $inc; +# last INCS; +# } +# for my $subdir (qw/freetype2 freetype/) { +# $path = File::Spec->catfile($inc, $subdir, 'fterrors.h'); +# -e $path and next; - $found_inc = $inc; - $found_inc2 = File::Spec->catdir($inc, $subdir); - last INCS; - } - } +# $found_inc = $inc; +# $found_inc2 = File::Spec->catdir($inc, $subdir); +# last INCS; +# } +# } - my $found_lib; - LIBS: - for my $lib (@libs) { - my $a_path = File::Spec->catfile($lib, "libfreetype$aext"); - my $l_path = File::Spec->catfile($lib, "libfreetype.$lext"); - if (-e $a_path || -e $l_path) { - $found_lib = $lib; - last LIBS; - } - } +# my $found_lib; +# LIBS: +# for my $lib (@libs) { +# my $a_path = File::Spec->catfile($lib, "libfreetype$aext"); +# my $l_path = File::Spec->catfile($lib, "libfreetype.$lext"); +# if (-e $a_path || -e $l_path) { +# $found_lib = $lib; +# last LIBS; +# } +# } - printf("%10s: includes %s - libraries %s\n", $frmkey, - ($found_inc ? 'found' : 'not found'), - ($found_lib ? 'found' : 'not found')); +# printf("%10s: includes %s - libraries %s\n", $frmkey, +# ($found_inc ? 'found' : 'not found'), +# ($found_lib ? 'found' : 'not found')); - return unless $found_inc && $found_lib; +# return unless $found_inc && $found_lib; - $frm->{cflags} = _make_I($found_inc); - $frm->{cflags} .= " " . _make_I($found_inc2) if $found_inc2; - $frm->{libfiles} = "-lfreetype"; +# $frm->{cflags} = _make_I($found_inc); +# $frm->{cflags} .= " " . _make_I($found_inc2) if $found_inc2; +# $frm->{libfiles} = "-lfreetype"; - return 1; -} +# return 1; +# } sub _make_I { my ($inc_dir) = @_; @@ -903,57 +903,57 @@ sub _make_I { } # probes for libpng via pkg-config -sub png_probe { - my ($frm, $frmkey) = @_; +# sub png_probe { +# my ($frm, $frmkey) = @_; - is_exe('pkg-config') or return; +# is_exe('pkg-config') or return; - my $config; - for my $check_conf (qw(libpng libpng12 libpng10)) { - if (_pkg_probe($check_conf)) { - $config = $check_conf; - last; - } - } - $config or return; +# my $config; +# for my $check_conf (qw(libpng libpng12 libpng10)) { +# if (_pkg_probe($check_conf)) { +# $config = $check_conf; +# last; +# } +# } +# $config or return; - my $cflags = `pkg-config $config --cflags` - and !$? or return; +# my $cflags = `pkg-config $config --cflags` +# and !$? or return; - my $lflags = `pkg-config $config --libs` - and !$? or return; +# my $lflags = `pkg-config $config --libs` +# and !$? or return; - chomp $cflags; - chomp $lflags; - $frm->{cflags} = $cflags; - $frm->{lflags} = $lflags; +# chomp $cflags; +# chomp $lflags; +# $frm->{cflags} = $cflags; +# $frm->{lflags} = $lflags; - printf "%10s: configured via `pkg-config $config ...`\n", $frmkey; +# printf "%10s: configured via `pkg-config $config ...`\n", $frmkey; - return 1; -} +# return 1; +# } sub catfile { return File::Spec->catfile(@_); } -sub is_exe { - my ($name) = @_; +# sub is_exe { +# my ($name) = @_; - my @exe_suffix = $Config{_exe}; - if ($^O eq 'MSWin32') { - push @exe_suffix, qw/.bat .cmd/; - } +# my @exe_suffix = $Config{_exe}; +# if ($^O eq 'MSWin32') { +# push @exe_suffix, qw/.bat .cmd/; +# } - for my $dir (File::Spec->path) { - for my $suffix (@exe_suffix) { - -x catfile($dir, "$name$suffix") - and return 1; - } - } +# for my $dir (File::Spec->path) { +# for my $suffix (@exe_suffix) { +# -x catfile($dir, "$name$suffix") +# and return 1; +# } +# } - return; -} +# return; +# } sub usage { print STDERR <base; } -static void fill_opacity(i_fill_t *fill, int x, int y, int width, int channels, - i_color *data); -static void fill_opacityf(i_fill_t *fill, int x, int y, int width, int channels, - i_fcolor *data); +static void fill_opacity(i_fill_t *fill, i_img_dim x, i_img_dim y, + i_img_dim width, int channels, i_color *data); +static void fill_opacityf(i_fill_t *fill, i_img_dim x, i_img_dim y, + i_img_dim width, int channels, i_fcolor *data); struct i_fill_opacity_t { i_fill_t base; @@ -587,8 +587,8 @@ The 8-bit sample fill function for non-combining solid fills. =cut */ static void -fill_solid(i_fill_t *fill, int x, int y, int width, int channels, - i_color *data) { +fill_solid(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width, + int channels, i_color *data) { i_color c = T_SOLID_FILL(fill)->c; i_adapt_colors(channels > 2 ? 4 : 2, 4, &c, 1); while (width-- > 0) { @@ -604,8 +604,8 @@ The floating sample fill function for non-combining solid fills. =cut */ static void -fill_solidf(i_fill_t *fill, int x, int y, int width, int channels, - i_fcolor *data) { +fill_solidf(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width, + int channels, i_fcolor *data) { i_fcolor c = T_SOLID_FILL(fill)->fc; i_adapt_fcolors(channels > 2 ? 4 : 2, 4, &c, 1); while (width-- > 0) { @@ -686,8 +686,9 @@ The 8-bit sample fill function for hatched fills. =cut */ -static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels, - i_color *data) { +static void +fill_hatch(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width, + int channels, i_color *data) { i_fill_hatch_t *f = (i_fill_hatch_t *)fill; int byte = f->hatch[(y + f->dy) & 7]; int xpos = (x + f->dx) & 7; @@ -719,8 +720,9 @@ The floating sample fill function for hatched fills. =back */ -static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels, - i_fcolor *data) { +static void +fill_hatchf(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width, + int channels, i_fcolor *data) { i_fill_hatch_t *f = (i_fill_hatch_t *)fill; int byte = f->hatch[(y + f->dy) & 7]; int xpos = (x + f->dx) & 7; @@ -793,10 +795,11 @@ static i_fcolor interp_i_fcolor(i_fcolor before, i_fcolor after, double pos, =cut */ -static void fill_image(i_fill_t *fill, int x, int y, int width, int channels, - i_color *data) { +static void +fill_image(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width, + int channels, i_color *data) { struct i_fill_image_t *f = (struct i_fill_image_t *)fill; - int i = 0; + i_img_dim i = 0; i_color *out = data; int want_channels = channels > 2 ? 4 : 2; @@ -809,7 +812,7 @@ static void fill_image(i_fill_t *fill, int x, int y, int width, int channels, double iy = floor(ry / f->src->ysize); i_color c[2][2]; i_color c2[2]; - int dy; + i_img_dim dy; if (f->xoff) { rx += iy * f->xoff; @@ -841,10 +844,10 @@ static void fill_image(i_fill_t *fill, int x, int y, int width, int channels, /* the easy way */ /* this should be possible to optimize to use i_glin() */ while (i < width) { - int rx = x+i; - int ry = y; - int ix = rx / f->src->xsize; - int iy = ry / f->src->ysize; + i_img_dim rx = x+i; + i_img_dim ry = y; + i_img_dim ix = rx / f->src->xsize; + i_img_dim iy = ry / f->src->ysize; if (f->xoff) { rx += iy * f->xoff; @@ -870,10 +873,11 @@ static void fill_image(i_fill_t *fill, int x, int y, int width, int channels, =cut */ -static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels, - i_fcolor *data) { +static void +fill_imagef(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width, + int channels, i_fcolor *data) { struct i_fill_image_t *f = (struct i_fill_image_t *)fill; - int i = 0; + i_img_dim i = 0; int want_channels = channels > 2 ? 4 : 2; if (f->has_matrix) { @@ -886,7 +890,7 @@ static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels, double iy = floor(ry / f->src->ysize); i_fcolor c[2][2]; i_fcolor c2[2]; - int dy; + i_img_dim dy; if (f->xoff) { rx += iy * f->xoff; @@ -919,10 +923,10 @@ static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels, /* the easy way */ /* this should be possible to optimize to use i_glin() */ while (i < width) { - int rx = x+i; - int ry = y; - int ix = rx / f->src->xsize; - int iy = ry / f->src->ysize; + i_img_dim rx = x+i; + i_img_dim ry = y; + i_img_dim ix = rx / f->src->xsize; + i_img_dim iy = ry / f->src->ysize; if (f->xoff) { rx += iy * f->xoff; @@ -944,8 +948,8 @@ static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels, } static void -fill_opacity(i_fill_t *fill, int x, int y, int width, int channels, - i_color *data) { +fill_opacity(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width, + int channels, i_color *data) { struct i_fill_opacity_t *f = (struct i_fill_opacity_t *)fill; int alpha_chan = channels > 2 ? 3 : 1; i_color *datap = data; @@ -963,8 +967,8 @@ fill_opacity(i_fill_t *fill, int x, int y, int width, int channels, } } static void -fill_opacityf(i_fill_t *fill, int x, int y, int width, int channels, - i_fcolor *data) { +fill_opacityf(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width, + int channels, i_fcolor *data) { struct i_fill_opacity_t *f = (struct i_fill_opacity_t *)fill; int alpha_chan = channels > 2 ? 3 : 1; i_fcolor *datap = data; diff --git a/filters.im b/filters.im index b27514e0..9ebb0af7 100644 --- a/filters.im +++ b/filters.im @@ -1729,7 +1729,7 @@ typedef struct { } i_fill_fountain_t; static void -fill_fountf(i_fill_t *fill, int x, int y, int width, int channels, +fill_fountf(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width, int channels, i_fcolor *data); static void fount_fill_destroy(i_fill_t *fill); @@ -2367,8 +2367,8 @@ The fill function for fountain fills. =cut */ static void -fill_fountf(i_fill_t *fill, int x, int y, int width, int channels, - i_fcolor *data) { +fill_fountf(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width, + int channels, i_fcolor *data) { i_fill_fountain_t *f = (i_fill_fountain_t *)fill; while (width--) { diff --git a/imager.h b/imager.h index a58c8023..89adcf46 100644 --- a/imager.h +++ b/imager.h @@ -257,46 +257,6 @@ int i_tt_glyph_name(TT_Fonthandle *handle, unsigned long ch, char *name_buf, #endif /* End of freetype headers */ -#ifdef HAVE_FT2 - -extern int i_ft2_init(void); -extern FT2_Fonthandle * i_ft2_new(const char *name, int index); -extern void i_ft2_destroy(FT2_Fonthandle *handle); -extern int i_ft2_setdpi(FT2_Fonthandle *handle, int xdpi, int ydpi); -extern int i_ft2_getdpi(FT2_Fonthandle *handle, int *xdpi, int *ydpi); -extern int i_ft2_settransform(FT2_Fonthandle *handle, const double *matrix); -extern int i_ft2_sethinting(FT2_Fonthandle *handle, int hinting); -extern int i_ft2_bbox(FT2_Fonthandle *handle, double cheight, double cwidth, - char const *text, size_t len, int *bbox, int utf8); -extern int i_ft2_bbox_r(FT2_Fonthandle *handle, double cheight, double cwidth, - char const *text, size_t len, int vlayout, int utf8, int *bbox); -extern int i_ft2_text(FT2_Fonthandle *handle, i_img *im, int tx, int ty, - const i_color *cl, double cheight, double cwidth, - char const *text, size_t len, int align, int aa, - int vlayout, int utf8); -extern int i_ft2_cp(FT2_Fonthandle *handle, i_img *im, int tx, int ty, - int channel, double cheight, double cwidth, - char const *text, size_t len, int align, int aa, - int vlayout, int utf8); -extern int i_ft2_has_chars(FT2_Fonthandle *handle, char const *text, size_t len, - int utf8, char *work); -extern int i_ft2_face_name(FT2_Fonthandle *handle, char *name_buf, - size_t name_buf_size); -extern int i_ft2_can_face_name(void); -extern int i_ft2_glyph_name(FT2_Fonthandle *handle, unsigned long ch, - char *name_buf, size_t name_buf_size, - int reliable_only); -extern int i_ft2_can_do_glyph_names(void); -extern int i_ft2_face_has_glyph_names(FT2_Fonthandle *handle); - -extern int i_ft2_get_multiple_masters(FT2_Fonthandle *handle, - i_font_mm *mm); -extern int -i_ft2_is_multiple_master(FT2_Fonthandle *handle); -extern int -i_ft2_set_mm_coords(FT2_Fonthandle *handle, int coord_count, const long *coords); -#endif - /* functions for reading and writing formats */ /* general reader callback diff --git a/imageri.h b/imageri.h index e01df468..36d6ed91 100644 --- a/imageri.h +++ b/imageri.h @@ -108,4 +108,10 @@ extern void im_assert_fail(char const *, int, char const *); #define im_assert(x) (void)(0) #endif +i_img_dim i_minx(i_img_dim a, i_img_dim b); +i_img_dim i_maxx(i_img_dim x, i_img_dim y); + +#define i_min(a, b) i_minx((a), (b)) +#define i_max(a, b) i_maxx((a), (b)) + #endif diff --git a/imdatatypes.h b/imdatatypes.h index 7b6e6591..7866d7b2 100644 --- a/imdatatypes.h +++ b/imdatatypes.h @@ -1,6 +1,7 @@ #ifndef _DATATYPES_H_ #define _DATATYPES_H_ +#include #include "imconfig.h" #include "imio.h" @@ -173,6 +174,7 @@ May be larger than int on some platforms. =cut */ + typedef int i_img_dim; /* @@ -413,10 +415,10 @@ enum bounding_box_index_t { struct i_fill_tag; typedef void (*i_fill_with_color_f) - (struct i_fill_tag *fill, int x, int y, int width, int channels, +(struct i_fill_tag *fill, i_img_dim x, i_img_dim y, i_img_dim width, int channels, i_color *data); typedef void (*i_fill_with_fcolor_f) - (struct i_fill_tag *fill, int x, int y, int width, int channels, + (struct i_fill_tag *fill, i_img_dim x, i_img_dim y, i_img_dim width, int channels, i_fcolor *data); typedef void (*i_fill_destroy_f)(struct i_fill_tag *fill); @@ -430,9 +432,9 @@ typedef void (*i_fill_destroy_f)(struct i_fill_tag *fill); */ typedef void (*i_fill_combine_f)(i_color *out, i_color *in, int channels, - int count); + i_img_dim count); typedef void (*i_fill_combinef_f)(i_fcolor *out, i_fcolor *in, int channels, - int count); + i_img_dim count); /* fountain fill types */ typedef enum { @@ -558,12 +560,6 @@ typedef struct TT_Fonthandle_ TT_Fonthandle; #endif -#ifdef HAVE_FT2 - -typedef struct FT2_Fonthandle FT2_Fonthandle; - -#endif - /* transparency handling for quantized output */ typedef enum i_transp_tag { tr_none, /* ignore any alpha channel */ @@ -713,7 +709,7 @@ enum { #include "iolayert.h" -#include "rendert.h" +typedef struct i_render_tag i_render; #endif diff --git a/imext.c b/imext.c index 8a67b48b..ed5c4169 100644 --- a/imext.c +++ b/imext.c @@ -1,5 +1,6 @@ #include "imexttypes.h" #include "imager.h" +#include "imio.h" /* DON'T ADD CASTS TO THESE @@ -124,7 +125,13 @@ im_ext_funcs imager_function_table = i_gsampf_bg, i_get_file_background, i_get_file_backgroundf, - i_utf8_advance + i_utf8_advance, + i_render_new, + i_render_delete, + i_render_color, + i_render_fill, + i_render_line, + i_render_linef }; /* in general these functions aren't called by Imager internally, but diff --git a/imext.h b/imext.h index c9d6f469..9c55b4b8 100644 --- a/imext.h +++ b/imext.h @@ -221,4 +221,15 @@ extern im_ext_funcs *imager_function_ext_table; #define i_utf8_advance(p, s) ((im_extt->f_i_utf8_advance)((p), (s))) +#define i_render_new(im, width) ((im_extt->f_i_render_new)((im), (width))) +#define i_render_delete(r) ((im_extt->f_i_render_delete)(r)) +#define i_render_color(r, x, y, width, src, color) \ + ((im_extt->f_i_render_color)((r), (x), (y), (width), (src), (color))) +#define i_render_fill(r, x, y, width, src, fill) \ + ((im_extt->f_i_render_fill)((r), (x), (y), (width), (src), (fill))) +#define i_render_line(r, x, y, width, src, line, combine) \ + ((im_extt->f_i_render_line)((r), (x), (y), (width), (src), (line), (combine))) +#define i_render_linef(r, x, y, width, src, line, combine) \ + ((im_extt->f_i_render_linef)((r), (x), (y), (width), (src), (line), (combine))) + #endif diff --git a/imexttypes.h b/imexttypes.h index a0d01728..f1561d42 100644 --- a/imexttypes.h +++ b/imexttypes.h @@ -165,6 +165,20 @@ typedef struct { void (*f_i_get_file_background)(i_img *im, i_color *bg); void (*f_i_get_file_backgroundf)(i_img *im, i_fcolor *bg); unsigned long (*f_i_utf8_advance)(char const **p, size_t *len); + i_render *(*f_i_render_new)(i_img *im, i_img_dim width); + void (*f_i_render_delete)(i_render *r); + void (*f_i_render_color)(i_render *r, i_img_dim x, i_img_dim y, + i_img_dim width, unsigned char const *src, + i_color const *color); + void (*f_i_render_fill)(i_render *r, i_img_dim x, i_img_dim y, + i_img_dim width, unsigned char const *src, + i_fill_t *fill); + void (*f_i_render_line)(i_render *r, i_img_dim x, i_img_dim y, + i_img_dim width, const i_sample_t *src, + i_color *line, i_fill_combine_f combine); + void (*f_i_render_linef)(i_render *r, i_img_dim x, i_img_dim y, + i_img_dim width, const double *src, + i_fcolor *line, i_fill_combinef_f combine); /* IMAGER_API_LEVEL 6 functions will be added here */ } im_ext_funcs; diff --git a/imio.h b/imio.h index 557097b4..6d5cea4f 100644 --- a/imio.h +++ b/imio.h @@ -17,8 +17,6 @@ void i_mempool_extend(i_mempool *mp); void *i_mempool_alloc(i_mempool *mp, size_t size); void i_mempool_destroy(i_mempool *mp); - - #ifdef _MSC_VER #undef min #undef max @@ -26,9 +24,4 @@ void i_mempool_destroy(i_mempool *mp); extern unsigned long i_utf8_advance(char const **p, size_t *len); -/* XXX Shouldn't these go away? */ - -int i_min(int a,int b); -int i_max(int x,int y); - #endif diff --git a/imperl.h b/imperl.h index fad1d66c..94033475 100644 --- a/imperl.h +++ b/imperl.h @@ -19,10 +19,6 @@ typedef i_img * Imager; typedef TT_Fonthandle* Imager__Font__TT; #endif -#ifdef HAVE_FT2 -typedef FT2_Fonthandle* Imager__Font__FT2; -#endif - /* for the fill objects Since a fill object may later have dependent images, (or fills!) we need perl wrappers - oh well diff --git a/imrender.h b/imrender.h index 9ded0223..69760ece 100644 --- a/imrender.h +++ b/imrender.h @@ -4,20 +4,25 @@ #include "rendert.h" extern void -i_render_init(i_render *r, i_img *im, int width); +i_render_init(i_render *r, i_img *im, i_img_dim width); extern void i_render_done(i_render *r); extern void -i_render_color(i_render *r, int x, int y, int width, unsigned char const *src, - i_color const *color); +i_render_color(i_render *r, i_img_dim x, i_img_dim y, i_img_dim width, + unsigned char const *src, i_color const *color); extern void -i_render_fill(i_render *r, int x, int y, int width, unsigned char const *src, - i_fill_t *fill); +i_render_fill(i_render *r, i_img_dim x, i_img_dim y, i_img_dim width, + unsigned char const *src, i_fill_t *fill); extern void -i_render_line(i_render *r, int x, int y, int width, const i_sample_t *src, - i_color *line, i_fill_combine_f combine); +i_render_line(i_render *r, i_img_dim x, i_img_dim y, i_img_dim width, + const i_sample_t *src, i_color *line, i_fill_combine_f combine); extern void -i_render_linef(i_render *r, int x, int y, int width, const double *src, - i_fcolor *line, i_fill_combinef_f combine); +i_render_linef(i_render *r, i_img_dim x, i_img_dim y, i_img_dim width, + const double *src, i_fcolor *line, i_fill_combinef_f combine); + +extern i_render * +i_render_new(i_img *im, i_img_dim width); +extern void +i_render_delete(i_render *r); #endif diff --git a/io.c b/io.c index 4576bf9e..df00421c 100644 --- a/io.c +++ b/io.c @@ -1,4 +1,5 @@ #include "imager.h" +#include "imageri.h" #include #ifndef _MSC_VER #include @@ -320,13 +321,13 @@ i_mempool_destroy(i_mempool *mp) { #undef min #undef max -int -i_min(int a,int b) { +i_img_dim +i_minx(i_img_dim a, i_img_dim b) { if (ab) return a; else return b; } @@ -345,16 +346,16 @@ struct utf8_size utf8_sizes[] = }; /* -=item utf8_advance(char **p, int *len) +=item i_utf8_advance(char **p, size_t *len) -Retreive a UTF8 character from the stream. +Retrieve a C character from the stream. Modifies *p and *len to indicate the consumed characters. -This doesn't support the extended UTF8 encoding used by later versions -of Perl. +This doesn't support the extended C encoding used by later +versions of Perl. -This doesn't check that the UTF8 charecter is using the shortest +This doesn't check that the C character is using the shortest possible representation. =cut diff --git a/iolayer.c b/iolayer.c index 0072abb2..5f499762 100644 --- a/iolayer.c +++ b/iolayer.c @@ -9,6 +9,7 @@ #endif #include #include +#include "imageri.h" #define IOL_DEB(x) diff --git a/lib/Imager/APIRef.pod b/lib/Imager/APIRef.pod index 4f2f571f..c9e5b480 100644 --- a/lib/Imager/APIRef.pod +++ b/lib/Imager/APIRef.pod @@ -14,6 +14,8 @@ Imager::APIRef - Imager's C API - reference. color.rgba.r = 255; color.rgba.g = 0; color.rgba.b = 255; + # Blit tools + # Data Types i_img *img; i_color black; @@ -90,6 +92,67 @@ Imager::APIRef - Imager's C API - reference. =head1 DESCRIPTION +=head2 Blit tools + +=over + +=item i_render_color(r, x, y, width, source, color) + +Render the given color with the coverage specified by C to +C. + +Renders in normal combine mode. + + +=for comment +From: File render.im + +=item i_render_delete(r) + +Release an C object. + + +=for comment +From: File render.im + +=item i_render_fill(r, x, y, width, source, fill) + +Render the given fill with the coverage in C through +C. + + +=for comment +From: File render.im + +=item i_render_line(r, x, y, width, source, fill) + +Render the given fill with the coverage in C through +C. + + +=for comment +From: File render.im + +=item i_render_linef(r, x, y, width, source, fill) + +Render the given fill with the coverage in C through +C. + + +=for comment +From: File render.im + +=item i_render_new(im, width) + +Allocate a new C object and initialize it. + + +=for comment +From: File render.im + + +=back + =head2 Data Types =over @@ -471,6 +534,19 @@ channel_count) =for comment From: File imext.c +=item i_gsamp_bg(im, l, r, y, samples, out_channels, background) + + +Like C but applies the source image color over a supplied +background color. + +This is intended for output to image formats that don't support alpha +channels. + + +=for comment +From: File paste.im + =item i_gsampf(im, left, right, y, samples, channels, channel_count) @@ -1515,21 +1591,25 @@ From: File tags.c =back +=head2 Uncategorized functions -=head1 UNDOCUMENTED +=over -The following API functions are undocumented so far, hopefully this -will change: +=item i_utf8_advance(char **p, size_t *len) -=over +Retrieve a C character from the stream. -=item * +Modifies *p and *len to indicate the consumed characters. -B +This doesn't support the extended C encoding used by later +versions of Perl. + +This doesn't check that the C character is using the shortest +possible representation. -=item * -B +=for comment +From: File io.c diff --git a/lib/Imager/Font.pm b/lib/Imager/Font.pm index 53b150fd..92c121b9 100644 --- a/lib/Imager/Font.pm +++ b/lib/Imager/Font.pm @@ -26,8 +26,8 @@ my %drivers = description => 'T1Lib', }, ft2=>{ - class=>'Imager::Font::FreeType2', - module=>'Imager/Font/FreeType2.pm', + class=>'Imager::Font::FT2', + module=>'Imager/Font/FT2.pm', files=>'.*\.(pfa|pfb|otf|ttf|fon|fnt|dfont|pcf(\.gz)?)$', description => 'FreeType 2.x', }, @@ -46,21 +46,6 @@ my %drivers = # this currently should only contain file based types, don't add w32 my @priority = qw(t1 tt ft2 ifs); -# when Imager::Font is loaded, Imager.xs has not been bootstrapped yet -# this function is called from Imager.pm to finish initialization -sub __init { - @priority = grep Imager::i_has_format($_), @priority; - for my $driver_name (grep Imager::i_has_format($_), keys %drivers) { - $drivers{$driver_name}{enabled} = 1; - } -} - -# search method -# 1. start by checking if file is the parameter -# 1a. if so qualify path and compare to the cache. -# 2a. if in cache - take it's id from there and increment count. -# - sub new { my $class = shift; my $self = {}; @@ -75,7 +60,18 @@ sub new { $file = $hsh{'file'}; $type = $hsh{'type'}; - if (!defined($type) or !$drivers{$type} or !$drivers{$type}{enabled}) { + if (defined $type) { + unless ($drivers{$type}) { + Imager->_set_error("Unknown font type $type"); + return; + } + + unless ($Imager::formats{$type}) { + Imager->_set_error("The $type {$drivers{$type}) font driver is not installed"); + return; + } + } + else { for my $drv (@priority) { undef $type; my $re = $drivers{$drv}{files} or next; diff --git a/lib/Imager/Font/FreeType2.pm b/lib/Imager/Font/FreeType2.pm index beac6372..279dfadd 100644 --- a/lib/Imager/Font/FreeType2.pm +++ b/lib/Imager/Font/FreeType2.pm @@ -1,180 +1,11 @@ package Imager::Font::FreeType2; use strict; -use Imager::Color; +use Imager::Font::FT2; use vars qw(@ISA $VERSION); -@ISA = qw(Imager::Font); - -$VERSION = "1.014"; - -*_first = \&Imager::Font::_first; - -sub new { - my $class = shift; - my %hsh=(color=>Imager::Color->new(255,0,0,0), - size=>15, - @_); - - unless ($hsh{file}) { - $Imager::ERRSTR = "No font file specified"; - return; - } - unless (-e $hsh{file}) { - $Imager::ERRSTR = "Font file $hsh{file} not found"; - return; - } - unless ($Imager::formats{ft2}) { - $Imager::ERRSTR = "Freetype2 not supported in this build"; - return; - } - my $id = i_ft2_new($hsh{file}, $hsh{'index'} || 0); - unless ($id) { # the low-level code may miss some error handling - $Imager::ERRSTR = Imager::_error_as_msg(); - return; - } - return bless { - id => $id, - aa => $hsh{aa} || 0, - file => $hsh{file}, - type => 't1', - size => $hsh{size}, - color => $hsh{color}, - utf8 => $hsh{utf8}, - vlayout => $hsh{vlayout}, - }, $class; -} - -sub _draw { - my $self = shift; - my %input = @_; - if (exists $input{channel}) { - i_ft2_cp($self->{id}, $input{image}{IMG}, $input{'x'}, $input{'y'}, - $input{channel}, $input{size}, $input{sizew} || 0, - $input{string}, , $input{align}, $input{aa}, $input{vlayout}, - $input{utf8}); - } else { - i_ft2_text($self->{id}, $input{image}{IMG}, - $input{'x'}, $input{'y'}, - $input{color}, $input{size}, $input{sizew} || 0, - $input{string}, $input{align}, $input{aa}, $input{vlayout}, - $input{utf8}); - } -} - -sub _bounding_box { - my $self = shift; - my %input = @_; - - return i_ft2_bbox($self->{id}, $input{size}, $input{sizew}, $input{string}, - $input{utf8}); -} - -sub dpi { - my $self = shift; - my @old = i_ft2_getdpi($self->{id}); - if (@_) { - my %hsh = @_; - my $result; - unless ($hsh{xdpi} && $hsh{ydpi}) { - if ($hsh{dpi}) { - $hsh{xdpi} = $hsh{ydpi} = $hsh{dpi}; - } - else { - $Imager::ERRSTR = "dpi method requires xdpi and ydpi or just dpi"; - return; - } - i_ft2_setdpi($self->{id}, $hsh{xdpi}, $hsh{ydpi}) or return; - } - } - - return @old; -} - -sub hinting { - my ($self, %opts) = @_; - - i_ft2_sethinting($self->{id}, $opts{hinting} || 0); -} - -sub _transform { - my $self = shift; - - my %hsh = @_; - my $matrix = $hsh{matrix} or return undef; - - return i_ft2_settransform($self->{id}, $matrix) -} - -sub utf8 { - return 1; -} - -# check if the font has the characters in the given string -sub has_chars { - my ($self, %hsh) = @_; - - unless (defined $hsh{string} && length $hsh{string}) { - $Imager::ERRSTR = "No string supplied to \$font->has_chars()"; - return; - } - return i_ft2_has_chars($self->{id}, $hsh{string}, - _first($hsh{'utf8'}, $self->{utf8}, 0)); -} - -sub face_name { - my ($self) = @_; - - i_ft2_face_name($self->{id}); -} - -sub can_glyph_names { - i_ft2_can_do_glyph_names(); -} - -sub glyph_names { - my ($self, %input) = @_; - - my $string = $input{string}; - defined $string - or return Imager->_set_error("no string parameter passed to glyph_names"); - my $utf8 = _first($input{utf8}, 0); - my $reliable_only = _first($input{reliable_only}, 1); - - my @names = i_ft2_glyph_name($self->{id}, $string, $utf8, $reliable_only); - @names or return Imager->_set_error(Imager->_error_as_msg); - - return @names if wantarray; - return pop @names; -} - -sub is_mm { - my ($self) = @_; - - i_ft2_is_multiple_master($self->{id}); -} - -sub mm_axes { - my ($self) = @_; - - my ($num_axis, $num_design, @axes) = - i_ft2_get_multiple_masters($self->{id}) - or return Imager->_set_error(Imager->_error_as_msg); - - return @axes; -} - -sub set_mm_coords { - my ($self, %opts) = @_; - - $opts{coords} - or return Imager->_set_error("Missing coords parameter"); - ref($opts{coords}) && $opts{coords} =~ /ARRAY\(0x[\da-f]+\)$/ - or return Imager->_set_error("coords parameter must be an ARRAY ref"); - - i_ft2_set_mm_coords($self->{id}, @{$opts{coords}}) - or return Imager->_set_error(Imager->_error_as_msg); - - return 1; -} +@ISA = qw(Imager::Font::FT2); + +$VERSION = "1.020"; + 1; diff --git a/paste.im b/paste.im index 6c440cec..6bc58a74 100644 --- a/paste.im +++ b/paste.im @@ -339,6 +339,8 @@ background color. This is intended for output to image formats that don't support alpha channels. +=cut + =item i_gsampf_bg(im, l, r, y, samples, out_channels, background) =category Drawing diff --git a/polygon.c b/polygon.c index 511cf7a3..a426b583 100644 --- a/polygon.c +++ b/polygon.c @@ -2,6 +2,7 @@ #include "draw.h" #include "log.h" #include "imrender.h" +#include "imageri.h" #define IMTRUNC(x) ((int)((x)*16)) diff --git a/quant.c b/quant.c index 13096ccc..ca4e34e5 100644 --- a/quant.c +++ b/quant.c @@ -3,6 +3,7 @@ 8-bit (or bigger indexed) png files at some point */ #include "imager.h" +#include "imageri.h" static void makemap_addi(i_quantize *, i_img **imgs, int count); static void makemap_mediancut(i_quantize *, i_img **imgs, int count); diff --git a/regmach.c b/regmach.c index c7fe613b..fa6578ee 100644 --- a/regmach.c +++ b/regmach.c @@ -1,5 +1,6 @@ #include "regmach.h" #include +#include "imageri.h" /*#define DEBUG*/ #ifdef DEBUG diff --git a/render.im b/render.im index 44fef994..08129142 100644 --- a/render.im +++ b/render.im @@ -5,7 +5,7 @@ Render utilities #define RENDER_MAGIC 0x765AE -typedef void (*render_color_f)(i_render *, int, int, int, unsigned char const *src, i_color const *color); +typedef void (*render_color_f)(i_render *, i_img_dim, i_img_dim, i_img_dim, unsigned char const *src, i_color const *color); #define i_has_alpha(channels) ((channels) == 2 || (channels) == 4) @@ -13,8 +13,8 @@ typedef void (*render_color_f)(i_render *, int, int, int, unsigned char const *s #code -static void IM_SUFFIX(render_color_alpha)(i_render *r, int x, int y, int width, unsigned char const *src, i_color const *color); -static void IM_SUFFIX(render_color_13)(i_render *r, int x, int y, int width, unsigned char const *src, i_color const *color); +static void IM_SUFFIX(render_color_alpha)(i_render *r, i_img_dim x, i_img_dim y, i_img_dim width, unsigned char const *src, i_color const *color); +static void IM_SUFFIX(render_color_13)(i_render *r, i_img_dim x, i_img_dim y, i_img_dim width, unsigned char const *src, i_color const *color); static render_color_f IM_SUFFIX(render_color_tab)[] = { @@ -25,18 +25,51 @@ static render_color_f IM_SUFFIX(render_color_tab)[] = IM_SUFFIX(render_color_alpha), }; -static void IM_SUFFIX(combine_line_noalpha)(IM_COLOR *out, IM_COLOR const *in, int channels, int count); -static void IM_SUFFIX(combine_line_alpha)(IM_COLOR *out, IM_COLOR const *in, int channels, int count); +static void IM_SUFFIX(combine_line_noalpha)(IM_COLOR *out, IM_COLOR const *in, int channels, i_img_dim count); +static void IM_SUFFIX(combine_line_alpha)(IM_COLOR *out, IM_COLOR const *in, int channels, i_img_dim count); /* the copy variant copies the source alpha to the the output alpha channel */ -static void IM_SUFFIX(combine_line_alpha_na)(IM_COLOR *out, IM_COLOR const *in, int channels, int count); +static void IM_SUFFIX(combine_line_alpha_na)(IM_COLOR *out, IM_COLOR const *in, int channels, i_img_dim count); -static void IM_SUFFIX(combine_line)(IM_COLOR *out, IM_COLOR const *in, int channels, int count); -static void IM_SUFFIX(combine_line_na)(IM_COLOR *out, IM_COLOR const *in, int channels, int count); +static void IM_SUFFIX(combine_line)(IM_COLOR *out, IM_COLOR const *in, int channels, i_img_dim count); +static void IM_SUFFIX(combine_line_na)(IM_COLOR *out, IM_COLOR const *in, int channels, i_img_dim count); #/code +/* +=item i_render_new(im, width) +=category Blit tools + +Allocate a new C object and initialize it. + +=cut +*/ + +i_render * +i_render_new(i_img *im, i_img_dim width) { + i_render *r = mymalloc(sizeof(i_render)); + + i_render_init(r, im, width); + + return r; +} + +/* +=item i_render_delete(r) +=category Blit tools + +Release an C object. + +=cut +*/ + void -i_render_init(i_render *r, i_img *im, int width) { +i_render_delete(i_render *r) { + i_render_done(r); + myfree(r); +} + +void +i_render_init(i_render *r, i_img *im, i_img_dim width) { r->magic = RENDER_MAGIC; r->im = im; r->line_width = width; @@ -61,9 +94,9 @@ i_render_done(i_render *r) { } static void -alloc_line(i_render *r, int width, int eight_bit) { +alloc_line(i_render *r, i_img_dim width, i_img_dim eight_bit) { if (width > r->line_width) { - int new_width = r->line_width * 2; + i_img_dim new_width = r->line_width * 2; if (new_width < width) new_width = width; @@ -111,9 +144,9 @@ alloc_line(i_render *r, int width, int eight_bit) { } static void -alloc_fill_line(i_render *r, int width, int eight_bit) { +alloc_fill_line(i_render *r, i_img_dim width, int eight_bit) { if (width > r->fill_width) { - int new_width = r->fill_width * 2; + i_img_dim new_width = r->fill_width * 2; if (new_width < width) new_width = width; @@ -160,9 +193,21 @@ alloc_fill_line(i_render *r, int width, int eight_bit) { } } +/* +=item i_render_color(r, x, y, width, source, color) +=category Blit tools + +Render the given color with the coverage specified by C to +C. + +Renders in normal combine mode. + +=cut +*/ + void -i_render_color(i_render *r, int x, int y, int width, unsigned char const *src, - i_color const *color) { +i_render_color(i_render *r, i_img_dim x, i_img_dim y, i_img_dim width, + unsigned char const *src, i_color const *color) { i_img *im = r->im; if (y < 0 || y >= im->ysize) return; @@ -198,9 +243,19 @@ i_render_color(i_render *r, int x, int y, int width, unsigned char const *src, #/code } +/* +=item i_render_fill(r, x, y, width, source, fill) +=category Blit tools + +Render the given fill with the coverage in C through +C. + +=cut +*/ + void -i_render_fill(i_render *r, int x, int y, int width, unsigned char const *src, - i_fill_t *fill) { +i_render_fill(i_render *r, i_img_dim x, i_img_dim y, i_img_dim width, + unsigned char const *src, i_fill_t *fill) { i_img *im = r->im; int fill_channels = im->channels; @@ -245,7 +300,7 @@ i_render_fill(i_render *r, int x, int y, int width, unsigned char const *src, if (src) { unsigned char const *srcc = src; IM_COLOR *fillc = r->IM_SUFFIX(fill_line); - int work_width = width; + i_img_dim work_width = width; while (work_width) { if (*srcc == 0) { fillc->channel[fill_channels-1] = 0; @@ -264,7 +319,7 @@ i_render_fill(i_render *r, int x, int y, int width, unsigned char const *src, } else { if (src) { - int work_width = width; + i_img_dim work_width = width; IM_COLOR *srcc = r->IM_SUFFIX(fill_line); IM_COLOR *destc = r->IM_SUFFIX(line); int ch; @@ -299,8 +354,8 @@ i_render_fill(i_render *r, int x, int y, int width, unsigned char const *src, } static void -dump_src(const char *note, unsigned char const *src, int width) { - int i; +dump_src(const char *note, unsigned char const *src, i_img_dim width) { + i_img_dim i; printf("%s - %p/%d\n", note, src, width); for (i = 0; i < width; ++i) { printf("%02x ", src[i]); @@ -310,9 +365,28 @@ dump_src(const char *note, unsigned char const *src, int width) { #code +/* +=item i_render_line(r, x, y, width, source, fill) +=category Blit tools + +Render the given fill with the coverage in C through +C. + +=cut + +=item i_render_linef(r, x, y, width, source, fill) +=category Blit tools + +Render the given fill with the coverage in C through +C. + +=cut +*/ + void -IM_RENDER_LINE(i_render *r, int x, int y, int width, const IM_SAMPLE_T *src, - IM_COLOR *line, IM_FILL_COMBINE_F combine) { +IM_RENDER_LINE(i_render *r, i_img_dim x, i_img_dim y, i_img_dim width, + const IM_SAMPLE_T *src, IM_COLOR *line, + IM_FILL_COMBINE_F combine) { i_img *im = r->im; int src_chans = im->channels; @@ -339,7 +413,7 @@ IM_RENDER_LINE(i_render *r, int x, int y, int width, const IM_SAMPLE_T *src, if (combine) { if (src) { - int work_width = width; + i_img_dim work_width = width; IM_COLOR *linep = line; const IM_SAMPLE_T *srcp = src; int alpha_chan = src_chans - 1; @@ -364,7 +438,7 @@ IM_RENDER_LINE(i_render *r, int x, int y, int width, const IM_SAMPLE_T *src, } else { if (src) { - int work_width = width; + i_img_dim work_width = width; IM_COLOR *srcc = line; IM_COLOR *destc = r->IM_SUFFIX(line); @@ -398,12 +472,13 @@ IM_RENDER_LINE(i_render *r, int x, int y, int width, const IM_SAMPLE_T *src, static void -IM_SUFFIX(render_color_13)(i_render *r, int x, int y, int width, - unsigned char const *src, i_color const *color) { +IM_SUFFIX(render_color_13)(i_render *r, i_img_dim x, i_img_dim y, + i_img_dim width, unsigned char const *src, + i_color const *color) { i_img *im = r->im; IM_COLOR *linep = r->IM_SUFFIX(line); int ch, channels = im->channels; - int fetch_offset; + i_img_dim fetch_offset; #undef STORE_COLOR #ifdef IM_EIGHT_BIT #define STORE_COLOR (*color) @@ -445,12 +520,13 @@ IM_SUFFIX(render_color_13)(i_render *r, int x, int y, int width, static void -IM_SUFFIX(render_color_alpha)(i_render *r, int x, int y, int width, - unsigned char const *src, i_color const *color) { +IM_SUFFIX(render_color_alpha)(i_render *r, i_img_dim x, i_img_dim y, + i_img_dim width, unsigned char const *src, + i_color const *color) { IM_COLOR *linep = r->IM_SUFFIX(line); int ch; int alpha_channel = r->im->channels - 1; - int fetch_offset; + i_img_dim fetch_offset; #undef STORE_COLOR #ifdef IM_EIGHT_BIT #define STORE_COLOR (*color) @@ -505,7 +581,7 @@ IM_SUFFIX(render_color_alpha)(i_render *r, int x, int y, int width, static void IM_SUFFIX(combine_line_alpha)(IM_COLOR *out, IM_COLOR const *in, - int channels, int count) { + int channels, i_img_dim count) { int ch; int alpha_channel = channels - 1; @@ -542,7 +618,7 @@ IM_SUFFIX(combine_line_alpha)(IM_COLOR *out, IM_COLOR const *in, static void IM_SUFFIX(combine_line_noalpha) - (IM_COLOR *out, IM_COLOR const *in, int channels, int count) { + (IM_COLOR *out, IM_COLOR const *in, int channels, i_img_dim count) { int ch; while (count) { @@ -577,7 +653,7 @@ IM_SUFFIX(combine_line_noalpha) static void IM_SUFFIX(combine_line_alpha_na)(IM_COLOR *out, IM_COLOR const *in, - int channels, int count) { + int channels, i_img_dim count) { int ch; int alpha_channel = channels - 1; @@ -605,7 +681,7 @@ IM_SUFFIX(combine_line_alpha_na)(IM_COLOR *out, IM_COLOR const *in, } static void -IM_SUFFIX(combine_line)(IM_COLOR *out, IM_COLOR const *in, int channels, int count) { +IM_SUFFIX(combine_line)(IM_COLOR *out, IM_COLOR const *in, int channels, i_img_dim count) { if (channels == 2 || channels == 4) IM_SUFFIX(combine_line_alpha)(out, in, channels, count); else @@ -613,25 +689,25 @@ IM_SUFFIX(combine_line)(IM_COLOR *out, IM_COLOR const *in, int channels, int cou } static void -IM_SUFFIX(combine_line_na)(IM_COLOR *out, IM_COLOR const *in, int channels, int count) { +IM_SUFFIX(combine_line_na)(IM_COLOR *out, IM_COLOR const *in, int channels, i_img_dim count) { if (channels == 2 || channels == 4) IM_SUFFIX(combine_line_alpha_na)(out, in, channels, count); else IM_SUFFIX(combine_line_noalpha)(out, in, channels, count); } -static void IM_SUFFIX(combine_alphablend)(IM_COLOR *, IM_COLOR *, int, int); -static void IM_SUFFIX(combine_mult)(IM_COLOR *, IM_COLOR *, int, int); -static void IM_SUFFIX(combine_dissolve)(IM_COLOR *, IM_COLOR *, int, int); -static void IM_SUFFIX(combine_add)(IM_COLOR *, IM_COLOR *, int, int); -static void IM_SUFFIX(combine_subtract)(IM_COLOR *, IM_COLOR *, int, int); -static void IM_SUFFIX(combine_diff)(IM_COLOR *, IM_COLOR *, int, int); -static void IM_SUFFIX(combine_darken)(IM_COLOR *, IM_COLOR *, int, int); -static void IM_SUFFIX(combine_lighten)(IM_COLOR *, IM_COLOR *, int, int); -static void IM_SUFFIX(combine_hue)(IM_COLOR *, IM_COLOR *, int, int); -static void IM_SUFFIX(combine_sat)(IM_COLOR *, IM_COLOR *, int, int); -static void IM_SUFFIX(combine_value)(IM_COLOR *, IM_COLOR *, int, int); -static void IM_SUFFIX(combine_color)(IM_COLOR *, IM_COLOR *, int, int); +static void IM_SUFFIX(combine_alphablend)(IM_COLOR *, IM_COLOR *, int, i_img_dim); +static void IM_SUFFIX(combine_mult)(IM_COLOR *, IM_COLOR *, int, i_img_dim); +static void IM_SUFFIX(combine_dissolve)(IM_COLOR *, IM_COLOR *, int, i_img_dim); +static void IM_SUFFIX(combine_add)(IM_COLOR *, IM_COLOR *, int, i_img_dim); +static void IM_SUFFIX(combine_subtract)(IM_COLOR *, IM_COLOR *, int, i_img_dim); +static void IM_SUFFIX(combine_diff)(IM_COLOR *, IM_COLOR *, int, i_img_dim); +static void IM_SUFFIX(combine_darken)(IM_COLOR *, IM_COLOR *, int, i_img_dim); +static void IM_SUFFIX(combine_lighten)(IM_COLOR *, IM_COLOR *, int, i_img_dim); +static void IM_SUFFIX(combine_hue)(IM_COLOR *, IM_COLOR *, int, i_img_dim); +static void IM_SUFFIX(combine_sat)(IM_COLOR *, IM_COLOR *, int, i_img_dim); +static void IM_SUFFIX(combine_value)(IM_COLOR *, IM_COLOR *, int, i_img_dim); +static void IM_SUFFIX(combine_color)(IM_COLOR *, IM_COLOR *, int, i_img_dim); static const IM_FILL_COMBINE_F IM_SUFFIX(combines)[] = { @@ -688,7 +764,7 @@ void i_get_combine(int combine, i_fill_combine_f *color_func, static void -IM_SUFFIX(combine_alphablend)(IM_COLOR *out, IM_COLOR *in, int channels, int count) { +IM_SUFFIX(combine_alphablend)(IM_COLOR *out, IM_COLOR *in, int channels, i_img_dim count) { IM_SUFFIX(combine_line)(out, in, channels, count); } @@ -702,11 +778,11 @@ When Da=1 Dc' = Sc.Sa.Dc + Dc.(1 - Sa) */ static void -IM_SUFFIX(combine_mult)(IM_COLOR *out, IM_COLOR *in, int channels, int count) { +IM_SUFFIX(combine_mult)(IM_COLOR *out, IM_COLOR *in, int channels, i_img_dim count) { int ch; IM_COLOR *inp = in; IM_COLOR *outp = out; - int work_count = count; + i_img_dim work_count = count; int color_channels = i_color_channels(channels); if (i_has_alpha(channels)) { @@ -751,7 +827,7 @@ IM_SUFFIX(combine_mult)(IM_COLOR *out, IM_COLOR *in, int channels, int count) { } static void -IM_SUFFIX(combine_dissolve)(IM_COLOR *out, IM_COLOR *in, int channels, int count) { +IM_SUFFIX(combine_dissolve)(IM_COLOR *out, IM_COLOR *in, int channels, i_img_dim count) { int color_channels = i_color_channels(channels); int ch; @@ -788,10 +864,10 @@ Da' = Sa.Da + Da.Sa + Sa.(1 - Da) + Da.(1 - Sa) */ static void -IM_SUFFIX(combine_add)(IM_COLOR *out, IM_COLOR *in, int channels, int count) { +IM_SUFFIX(combine_add)(IM_COLOR *out, IM_COLOR *in, int channels, i_img_dim count) { int ch; int color_channels = i_color_channels(channels); - int work_count = count; + i_img_dim work_count = count; IM_COLOR *inp = in; IM_COLOR *outp = out; @@ -843,11 +919,11 @@ IM_SUFFIX(combine_add)(IM_COLOR *out, IM_COLOR *in, int channels, int count) { channel to apply that to the target. */ static void -IM_SUFFIX(combine_subtract)(IM_COLOR *out, IM_COLOR *in, int channels, int count) { +IM_SUFFIX(combine_subtract)(IM_COLOR *out, IM_COLOR *in, int channels, i_img_dim count) { int ch; IM_COLOR const *inp = in; IM_COLOR *outp = out; - int work_count = count; + i_img_dim work_count = count; int color_channels = i_color_channels(channels); if (i_has_alpha(channels)) { @@ -901,11 +977,11 @@ Dca' = abs(Dca.Sa - Sca.Da) + Sca.(1 - Da) + Dca.(1 - Sa) Da' = Sa + Da - Sa.Da */ static void -IM_SUFFIX(combine_diff)(IM_COLOR *out, IM_COLOR *in, int channels, int count) { +IM_SUFFIX(combine_diff)(IM_COLOR *out, IM_COLOR *in, int channels, i_img_dim count) { int ch; IM_COLOR const *inp = in; IM_COLOR *outp = out; - int work_count = count; + i_img_dim work_count = count; int color_channels = i_color_channels(channels); if (i_has_alpha(channels)) { @@ -969,11 +1045,11 @@ IM_SUFFIX(combine_diff)(IM_COLOR *out, IM_COLOR *in, int channels, int count) { */ static void IM_SUFFIX(combine_darken)(IM_COLOR *out, IM_COLOR *in, int channels, - int count) { + i_img_dim count) { int ch; IM_COLOR const *inp = in; IM_COLOR *outp = out; - int work_count = count; + i_img_dim work_count = count; int color_channels = i_color_channels(channels); if (i_has_alpha(channels)) { @@ -1024,11 +1100,11 @@ IM_SUFFIX(combine_darken)(IM_COLOR *out, IM_COLOR *in, int channels, } static void -IM_SUFFIX(combine_lighten)(IM_COLOR *out, IM_COLOR *in, int channels, int count) { +IM_SUFFIX(combine_lighten)(IM_COLOR *out, IM_COLOR *in, int channels, i_img_dim count) { int ch; IM_COLOR const *inp = in; IM_COLOR *outp = out; - int work_count = count; + i_img_dim work_count = count; int color_channels = i_color_channels(channels); if (i_has_alpha(channels)) { @@ -1087,11 +1163,11 @@ IM_SUFFIX(combine_lighten)(IM_COLOR *out, IM_COLOR *in, int channels, int count) #endif static void -IM_SUFFIX(combine_hue)(IM_COLOR *out, IM_COLOR *in, int channels, int count) { +IM_SUFFIX(combine_hue)(IM_COLOR *out, IM_COLOR *in, int channels, i_img_dim count) { if (channels > 2) { IM_COLOR *inp = in; IM_COLOR const *outp = out; - int work_count = count; + i_img_dim work_count = count; if (i_has_alpha(channels)) { while (work_count--) { @@ -1148,11 +1224,11 @@ IM_SUFFIX(combine_hue)(IM_COLOR *out, IM_COLOR *in, int channels, int count) { } static void -IM_SUFFIX(combine_sat)(IM_COLOR *out, IM_COLOR *in, int channels, int count) { +IM_SUFFIX(combine_sat)(IM_COLOR *out, IM_COLOR *in, int channels, i_img_dim count) { if (channels > 2) { IM_COLOR *inp = in; IM_COLOR const *outp = out; - int work_count = count; + i_img_dim work_count = count; while (work_count--) { IM_COLOR c = *inp; @@ -1171,11 +1247,11 @@ IM_SUFFIX(combine_sat)(IM_COLOR *out, IM_COLOR *in, int channels, int count) { } static void -IM_SUFFIX(combine_value)(IM_COLOR *out, IM_COLOR *in, int channels, int count) { +IM_SUFFIX(combine_value)(IM_COLOR *out, IM_COLOR *in, int channels, i_img_dim count) { if (channels > 2) { IM_COLOR *inp = in; IM_COLOR const *outp = out; - int work_count = count; + i_img_dim work_count = count; while (work_count--) { IM_COLOR c = *inp; @@ -1196,11 +1272,11 @@ IM_SUFFIX(combine_value)(IM_COLOR *out, IM_COLOR *in, int channels, int count) { } static void -IM_SUFFIX(combine_color)(IM_COLOR *out, IM_COLOR *in, int channels, int count) { +IM_SUFFIX(combine_color)(IM_COLOR *out, IM_COLOR *in, int channels, i_img_dim count) { if (channels > 2) { IM_COLOR *inp = in; IM_COLOR const *outp = out; - int work_count = count; + i_img_dim work_count = count; while (work_count--) { IM_COLOR c = *inp; diff --git a/rendert.h b/rendert.h index 2eb79a25..3aa2470a 100644 --- a/rendert.h +++ b/rendert.h @@ -1,17 +1,19 @@ #ifndef IMAGER_RENDERT_H #define IMAGER_RENDERT_H -typedef struct { +#include "imdatatypes.h" + +struct i_render_tag { int magic; i_img *im; - int line_width; + i_img_dim line_width; i_color *line_8; i_fcolor *line_double; - int fill_width; + i_img_dim fill_width; i_color *fill_line_8; i_fcolor *fill_line_double; -} i_render; +}; #endif diff --git a/t/x20spell.t b/t/x20spell.t index 9ff84e09..cf7f141f 100644 --- a/t/x20spell.t +++ b/t/x20spell.t @@ -44,6 +44,8 @@ RGBA postfix infix unary +Uncategorized +Blit /; local %Pod::Wordlist::Wordlist = %Pod::Wordlist::Wordlist; diff --git a/typemap b/typemap index 28159ad7..74d5ae71 100644 --- a/typemap +++ b/typemap @@ -4,7 +4,6 @@ Imager::Color::Float T_PTROBJ Imager::ImgRaw T_IMAGER_IMAGE Imager::Font::TT T_PTROBJ Imager::IO T_PTROBJ -Imager::Font::FT2 T_PTROBJ Imager::FillHandle T_PTROBJ Imager::Internal::Hlines T_PTROBJ const char * T_PV -- 2.39.2