From acd0799ad7f63a0e4266540b5e8852230e8c1df2 Mon Sep 17 00:00:00 2001 From: Andrew Egeler Date: Wed, 1 Apr 2015 08:15:58 -0400 Subject: [PATCH 1/2] Download Cairo .dll files for windows If there are no system-installed (in $PATH) cairo .dll files installed, we download some "bundled" ones. Note that these were already hosted for use by GTK::Simple, but we re-download them here since we don't have any dependency on GTK::Simple. --- Build.pm | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ META.info | 2 +- 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 Build.pm diff --git a/Build.pm b/Build.pm new file mode 100644 index 0000000..6dfa40f --- /dev/null +++ b/Build.pm @@ -0,0 +1,72 @@ +use Panda::Builder; + +use Shell::Command; +use LWP::Simple; +use NativeCall; + +# test sub for system library +sub test() is native('libcairo-2.dll') { * } + +class Build is Panda::Builder { + method build($workdir) { + my $need-copy = False; + + # we only have .dll files bundled. Non-windows is assumed to have the library already + if $*DISTRO.is-win { + test(); + CATCH { + default { + $need-copy = True if $_.payload ~~ m:s/Cannot locate/; + } + } + } + + if $need-copy { + # to avoid a dependency (and because Digest::SHA is too slow), we do a hacked up powershell hash + # this should work all the way back to powershell v1 + my &ps-hash = -> $path { + my $fn = 'function get-sha256 { param($file);[system.bitconverter]::tostring([System.Security.Cryptography.sha256]::create().computehash([system.io.file]::openread((resolve-path $file)))) -replace \"-\",\"\" } '; + my $out = qqx/powershell -noprofile -Command "$fn get-sha256 $path"/; + $out.lines.grep({$_.chars})[*-1]; + } + say 'No system cairo library detected. Installing bundled version.'; + mkdir($workdir ~ '\blib\lib\Cairo'); + my @files = ( + "libcairo-2.dll", + "libfontconfig-1.dll", + "libfreetype-6.dll", + "libiconv-2.dll", + "liblzma-5.dll", + "libpixman-1-0.dll", + "libpng15-15.dll", + "libxml2-2.dll", + "zlib1.dll"); + my @hashes = ( + "E127BF5D01CD9B2F82501E4AD8F867CE9310CE16A33CB71D5ED3F5AB906FD318", + "1AC7BC02502D1D798662B3621B43637F33B07424C89E2E808945BD7133694EFA", + "7C54CB33D0247E3BB65974CAD1B7205590DF0E99460CF197E37B4CABDE265935", + "954B8740A7CBE3728B136D4F36229C599D1F51534137B16E48E3D7FF9C468FDC", + "CE34910B43D5E4285AECDA0E4F64A1BA06C5D53E484F0B68D219C8D8473332AB", + "A97EBE54ED31ED7D8A8317D831878CE82F3B94FE1E5A7466B78D0F0C90863302", + "40F6EDE85DB0A1E2F4BA67693B7DC8B74AFFBFAB3B92B99F6B2CEFACBBF7FF6D", + "4F1032F0D7F6F0C2046A96884FD48EC0F7C0A1E22C85E9076057756C4C48E0CB", + "5A697F89758B407EE85BAD35376546A80520E1F3092D07F1BC366A490443FAB5"); + for @files Z @hashes -> $f, $h { + say "Fetching " ~ $f; + my $blob = LWP::Simple.get('http://gtk-dlls.p6c.org/' ~ $f); + say "Writing " ~ $f; + spurt($workdir ~ '\blib\lib\Cairo\\' ~ $f, $blob); + + say "Verifying " ~ $f; + my $hash = ps-hash($workdir ~ '\blib\lib\Cairo\\' ~ $f); + if ($hash ne $h) { + die "Bad download of $f (got: $hash; expected: $h)"; + } + say ""; + } + } + else { + say 'Found system cairo library.'; + } + } +} diff --git a/META.info b/META.info index e677c4e..d0c41f5 100644 --- a/META.info +++ b/META.info @@ -3,7 +3,7 @@ "name" : "Cairo", "description" : "Cairo 2D graphics library", "version" : "v0.2", - "depends" : [ ], + "depends" : [ "LWP::Simple" ], "provides" : { "Cairo" : "lib/Cairo.pm6" }, From 0a55aef758ab3dbd9c0aa809146ae01ecae65dec Mon Sep 17 00:00:00 2001 From: Andrew Egeler Date: Wed, 1 Apr 2015 08:18:17 -0400 Subject: [PATCH 2/2] Actually use bundled .dll files if they exist We use the first 100 or so lines in the file to load everything in dependency order, but now we don't rely on anything being in $PATH --- lib/Cairo.pm6 | 225 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 165 insertions(+), 60 deletions(-) diff --git a/lib/Cairo.pm6 b/lib/Cairo.pm6 index f40c7e0..9fa918a 100644 --- a/lib/Cairo.pm6 +++ b/lib/Cairo.pm6 @@ -1,15 +1,120 @@ module Cairo; -my Str $cairolib; -BEGIN { - if $*VM.config ~~ /dll/ { - $cairolib = 'libcairo-2'; - } else { - $cairolib = 'libcairo'; +use NativeCall; + +### +# library finding stuff (mostly for windows) +### + +sub find-bundled($lib is copy) { + # if we can't find one, assume there's a system install + my $base = "lib/Cairo/$lib"; + for @*INC { + if my @files = ($_.files($base) || $_.files("blib/$base")) { + my $files = @files[0]; + my $tmp = $files{$base} || $files{"blib/$base"}; + + # copy to a temp dir + $tmp.IO.copy($*SPEC.tmpdir ~ '\\' ~ $lib); + $lib = $*SPEC.tmpdir ~ '\\' ~ $lib; + + last; + } } + + $lib; } -use NativeCall; +sub cairo-lib { + state $lib; + unless $lib { + if $*VM.config ~~ /dll/ { + try load-fontconfig-lib; + try load-freetype-lib; + try load-pixman-lib; + try load-png-lib; + try load-zlib-lib; + $lib = find-bundled('libcairo-2.dll'); + } else { + $lib = 'libcairo'; + } + } + $lib +} +sub fontconfig-lib { + state $lib; + unless $lib { + try load-freetype-lib; + try load-xml-lib; + $lib = find-bundled('libfontconfig-1.dll'); + } + $lib +} +sub freetype-lib { + state $lib; + unless $lib { + try load-zlib-lib; + $lib = find-bundled('libfreetype-6.dll'); + } + $lib +} +sub pixman-lib { + state $lib; + unless $lib { + $lib = find-bundled('libpixman-1-0.dll'); + } + $lib +} +sub png-lib { + state $lib; + unless $lib { + $lib = find-bundled('libpng15-15.dll'); + } + $lib +} +sub zlib-lib { + state $lib; + unless $lib { + $lib = find-bundled('zlib1.dll'); + } + $lib +} +sub xml-lib { + state $lib; + unless $lib { + try load-iconv-lib; + try load-lzma-lib; + $lib = find-bundled('libxml2-2.dll'); + } + $lib +} +sub iconv-lib { + state $lib; + unless $lib { + $lib = find-bundled('libiconv-2.dll'); + } + $lib +} +sub lzma-lib { + state $lib; + unless $lib { + $lib = find-bundled('liblzma-5.dll'); + } + $lib +} + +sub load-fontconfig-lib is native(&fontconfig-lib) { ... } +sub load-freetype-lib is native(&freetype-lib) { ... } +sub load-pixman-lib is native(&pixman-lib) { ... } +sub load-png-lib is native(&png-lib) { ... } +sub load-zlib-lib is native(&zlib-lib) { ... } +sub load-xml-lib is native(&xml-lib) { ... } +sub load-iconv-lib is native(&iconv-lib) { ... } +sub load-lzma-lib is native(&lzma-lib) { ... } + +### +# end of library finding +### class cairo_t is repr('CPointer') { } @@ -142,7 +247,7 @@ our enum Antialias < sub cairo_format_stride_for_width(int32 $format, int32 $width) returns int32 - is native($cairolib) + is native(&cairo-lib) {*} class Surface { @@ -150,25 +255,25 @@ class Surface { sub cairo_surface_write_to_png(cairo_surface_t $surface, Str $filename) returns int32 - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_surface_reference(cairo_surface_t $surface) returns cairo_surface_t - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_surface_destroy(cairo_surface_t $surface) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_image_surface_get_data(cairo_surface_t $surface) returns OpaquePointer - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_image_surface_get_stride(cairo_surface_t $surface) returns int32 - is native($cairolib) + is native(&cairo-lib) {*} method write_png(Str $filename) { @@ -194,7 +299,7 @@ class Surface { class RecordingSurface { sub cairo_recording_surface_create(int32 $content, cairo_rectangle_t $extents) returns cairo_surface_t - is native($cairolib) + is native(&cairo-lib) {*} method new(Content $content = CONTENT_COLOR_ALPHA) { @@ -215,12 +320,12 @@ class RecordingSurface { class Image { sub cairo_image_surface_create(int32 $format, int32 $width, int32 $height) returns cairo_surface_t - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_image_surface_create_for_data(Blob[uint8] $data, int32 $format, int32 $width, int32 $height, int32 $stride) returns cairo_surface_t - is native($cairolib) + is native(&cairo-lib) {*} multi method create(Format $format, Cool $width, Cool $height) { @@ -250,7 +355,7 @@ class Image { class Pattern { sub cairo_pattern_destroy(cairo_pattern_t $pat) - is native($cairolib) + is native(&cairo-lib) {*} has $.pattern; @@ -267,179 +372,179 @@ class Pattern { class Context { sub cairo_create(cairo_surface_t $surface) returns cairo_t - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_destroy(cairo_t $ctx) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_copy_path(cairo_t $ctx) returns cairo_path_t - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_copy_path_flat(cairo_t $ctx) returns cairo_path_t - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_append_path(cairo_t $ctx, cairo_path_t $path) returns cairo_path_t - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_push_group(cairo_t $ctx) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_pop_group(cairo_t $ctx) returns cairo_pattern_t - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_pop_group_to_source(cairo_t $ctx) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_line_to(cairo_t $context, num $x, num $y) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_move_to(cairo_t $context, num $x, num $y) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_rel_line_to(cairo_t $context, num $x, num $y) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_rel_move_to(cairo_t $context, num $x, num $y) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_curve_to(cairo_t $context, num $x1, num $y1, num $x2, num $y2, num $x3, num $y3) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_arc(cairo_t $context, num $xc, num $yc, num $radius, num $angle1, num $angle2) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_arc_negative(cairo_t $context, num $xc, num $yc, num $radius, num $angle1, num $angle2) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_close_path(cairo_t $context) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_rectangle(cairo_t $ctx, num $x, num $y, num $w, num $h) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_set_source_rgb(cairo_t $context, num $r, num $g, num $b) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_set_source_rgba(cairo_t $context, num $r, num $g, num $b, num $a) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_set_line_cap(cairo_t $context, int32 $cap) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_get_line_cap(cairo_t $context) returns int32 - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_set_line_width(cairo_t $context, num $width) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_get_line_width(cairo_t $context) returns num - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_get_operator(cairo_t $context) returns int32 - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_set_operator(cairo_t $context, int32 $op) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_get_antialias(cairo_t $context) returns int32 - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_set_antialias(cairo_t $context, int32 $op) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_set_source_surface(cairo_t $context, cairo_surface_t $surface, num $x, num $y) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_mask(cairo_t $context, cairo_pattern_t $pattern) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_mask_surface(cairo_t $context, cairo_surface_t $surface, num $sx, num $sy) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_clip(cairo_t $context) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_clip_preserve(cairo_t $context) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_fill(cairo_t $ctx) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_stroke(cairo_t $ctx) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_fill_preserve(cairo_t $ctx) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_stroke_preserve(cairo_t $ctx) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_paint(cairo_t $ctx) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_translate(cairo_t $ctx, num $tx, num $ty) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_scale(cairo_t $ctx, num $sx, num $sy) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_rotate(cairo_t $ctx, num $angle) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_save(cairo_t $ctx) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_restore(cairo_t $ctx) - is native($cairolib) + is native(&cairo-lib) {*} sub cairo_status(cairo_t $ctx) returns int32 - is native($cairolib) + is native(&cairo-lib) {*} has cairo_t $!context;