diff --git a/build/build.rb b/build/build.rb index cdc8845..b3c351f 100755 --- a/build/build.rb +++ b/build/build.rb @@ -1,7 +1,7 @@ #!/usr/bin/env ruby # $:.unshift(File.expand_path("./dopebuild", __dir__)) # require 'pry' -# require 'debug' +require 'debug' require_relative './dopebuild.rb' @@ -13,12 +13,25 @@ conf.require_lib!('freetype2') conf.require_lib!('cairo') +# To use this: +# Download prebuilt Skia binaries here: https://github.com/JetBrains/skia-pack/releases +# e.g. Skia-m132-a00c390e98-1-macos-Debug-arm64.zip +# then unzip it into under ~/Downloads/_skia +# +conf.require_lib_2!('skia', "#{ENV['HOME']}/Downloads/_skia", [ + '' +], +['out/Debug-macos-arm64'], +[ + 'skia' +]) + # include_video = (ENV['WITH_VIDEO'] == 'true') conf.build_files = [ - 'font.c', + 'font.cpp', 'layer_ext.c', - 'surface.c', + 'surface.cpp', 'window.c', 'timer.c', ] diff --git a/build/dopebuild.rb b/build/dopebuild.rb index 939f379..486fece 100644 --- a/build/dopebuild.rb +++ b/build/dopebuild.rb @@ -56,12 +56,17 @@ def generate_ninja lines << '' + cc_cpp_args = \ + if RUBY_PLATFORM =~ /darwin/ + "-fdeclspec $cflags -c $in -o $out" + else + "-fdeclspec -fPIC $cflags -c $in -o $out" + end + lines << 'rule cc' - if RUBY_PLATFORM =~ /darwin/ - lines << " command = #{bin :cc} -fdeclspec $cflags -c $in -o $out" - else - lines << " command = #{bin :cc} -fdeclspec -fPIC $cflags -c $in -o $out" - end + lines << " command = #{bin :cc} #{cc_cpp_args}" + lines << 'rule cpp' + lines << " command = #{bin :cpp} -std=c++20 #{cc_cpp_args}" lines << 'rule lcc' if RUBY_PLATFORM =~ /darwin/ @@ -76,7 +81,13 @@ def generate_ninja build_files.each do |file| ext = File.extname(file) only_file = file[0...(-ext.length)] - lines << "build out/#{only_file}.o: cc ext/#{file}" + + compiler = { + '.c' => 'cc', + '.cpp' => 'cpp', + }.fetch(ext) + + lines << "build out/#{only_file}.o: #{compiler} ext/#{file}" out_files << "out/#{only_file}.o" end @@ -95,6 +106,7 @@ def detect_bins set_bin(:pkg_config, detect_bin!('pkg-config', 'Install it via brew install pkg-config')) set_bin(:ninja, detect_bin!('ninja', 'Install it via brew install ninja')) set_bin(:cc, detect_bin_one_of!(%w(clang-15 clang gcc cc))) + set_bin(:cpp, detect_bin_one_of!(%w(clang++ g++))) end def detect_ruby @@ -156,6 +168,21 @@ def require_lib!(name) } end + def require_lib_2!(name, base_path, includes, lib_rel_paths, link_libs) + cflags = includes.map do |ri| + "-I#{File.join(base_path, ri).chomp('/')}" + end.join(' ') + + libs = lib_rel_paths.map do |lp| + "-L" + File.join(base_path, lp).chomp('/') + end + libs << link_libs.map{ |x| "-l#{x}" } + + libs = libs.join(' ') + + @libs[name.to_sym] = { cflags:, libs: } + end + private def set_bin(name, value) diff --git a/examples/gen_video/main.rb b/examples/gen_video/main.rb index 22b828f..1937f06 100755 --- a/examples/gen_video/main.rb +++ b/examples/gen_video/main.rb @@ -79,7 +79,7 @@ def draw_all(time) @particles.each do |par| @sf.identity @sf.translate(par[:x] + 32, par[:y] + 32) - @sf.rotate(par[:life] * Math::PI * 2.0) + # @sf.rotate(par[:life] * Math::PI * 2.0) @sf.blit_surface(par[:sprite], -32, -32) end @sf.identity diff --git a/ext/font.c b/ext/font.cpp similarity index 98% rename from ext/font.c rename to ext/font.cpp index ac35b52..dbc20f6 100644 --- a/ext/font.c +++ b/ext/font.cpp @@ -254,7 +254,11 @@ static VALUE t_font_size_set(VALUE self, VALUE _size) { DECLAREFONT(self); font->size = (float)NUM2DBL(_size); - FT_Set_Char_Size(font->face, 0, (int)(font->size * 64.0), 128, 128); + FT_Set_Char_Size((FT_Face)font->face, + (FT_F26Dot6)0, + (FT_F26Dot6)(font->size * 64.0), + (FT_UInt)128, + (FT_UInt)128); return Qnil; } @@ -277,6 +281,7 @@ static VALUE t_font__color_set(VALUE self, VALUE _value) { //////////////////////////////////////////////////////////////////////// +extern "C" void LAO_Font_Init() { cLayerFont = rb_define_class_under(cLayer, "Font", rb_cObject); diff --git a/ext/surface.c b/ext/surface.cpp similarity index 92% rename from ext/surface.c rename to ext/surface.cpp index 1d5840a..c793369 100644 --- a/ext/surface.c +++ b/ext/surface.cpp @@ -1,4 +1,6 @@ +// extern "C" { #include "surface.h" +// } extern VALUE cLayer; VALUE cLayerSurface; @@ -74,6 +76,15 @@ t_sfc_allocator(VALUE klass) { // return TypedData_Make_Struct(klass, struct LAO_Surface, &lao_surface_datatype, 0); } +#include "include/core/SkCanvas.h" +#include "include/core/SkGraphics.h" +#include "include/core/SkPaint.h" +#include "include/core/SkSurface.h" + +#include "include/core/SkStream.h" // for SkFILEWStream +#include "include/codec/SkEncodedImageFormat.h" // for SkEncodedImageFormat +// #include "include/core/SkImageEncoder.h" // for SkEncodeImage + static VALUE t_sfc_initialize(VALUE self, VALUE _width, VALUE _height) { DECLARESFC(self); @@ -83,6 +94,26 @@ t_sfc_initialize(VALUE self, VALUE _width, VALUE _height) { const int initialize = (width > 0 && height > 0); + SkGraphics::Init(); + // SkImageInfo imgi = SkImageInfo::Make(width, height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType); + SkImageInfo imgi = SkImageInfo::MakeN32Premul(512, 256); + // sk_sp sk_sfc = SkSurfaces::Raster(imgi); + sk_sp sk_sfc = SkSurfaces::Null(512, 256); + + SkCanvas* sk_canvas = sk_sfc->getCanvas(); + SkPaint paint; + paint.setColor(SK_ColorBLUE); + paint.setAntiAlias(true); + sk_canvas->drawCircle(128, 128, 100, paint); + + // sk_sp img = sk_sfc->makeImageSnapshot(); + // SkPixmap pixmap; + // if (img->peekPixels(&pixmap)) { + // SkFILEWStream out("circle.png"); + // SkEncodeImage(&out, pixmap, SkEncodedImageFormat::kPNG, 100); + // } + + // SDL_Surface *sfc = SDL_CreateRGBSurfaceWithFormat(0, // 512, 512, 32, SDL_PIXELFORMAT_BGRA32); @@ -141,6 +172,7 @@ t_sfc_save_png(VALUE self, VALUE file_name) { return Qtrue; } +extern "C" VALUE lao_sfc_create_borrowed(SDL_Surface *sdl_surface, cairo_surface_t *cairo_surface, cairo_t *cairo_ctx) { VALUE sfc_obj = t_sfc_allocator(cLayerSurface); @@ -380,7 +412,7 @@ t_sfc_to_rgb24(VALUE self) { const unsigned int width = cairo_image_surface_get_width(sfc->cairo_surface); const unsigned int height = cairo_image_surface_get_height(sfc->cairo_surface); - unsigned char *dest_data = malloc(width * height * 3); + unsigned char *dest_data = (unsigned char*)malloc(width * height * 3); for (unsigned int y = 0; y < height; ++y) { for (unsigned int x = 0; x < width; ++x) { @@ -532,6 +564,7 @@ t_sfc_identity(VALUE self) { //////////////////////////////////////////////////////////////////////// +extern "C" void LAO_Surface_Init() { cLayerSurface = rb_define_class_under(cLayer, "Surface", rb_cObject); diff --git a/ext/surface.h b/ext/surface.h index 060be31..22f8c42 100644 --- a/ext/surface.h +++ b/ext/surface.h @@ -14,8 +14,16 @@ struct LAO_Surface { int borrowed; }; +#ifdef __cplusplus +extern "C" { +#endif + VALUE lao_sfc_create_borrowed(SDL_Surface *sdl_surface, cairo_surface_t *cairo_surface, cairo_t *cairo_ctx); struct LAO_Surface *lao_sfc_from_value(VALUE v); +#ifdef __cplusplus +} +#endif + #endif