diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index 5debb1d..5ddab2c 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -1,5 +1,3 @@ -# Workflow derived from https://github.com/r-lib/actions/tree/master/examples -# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help on: push: pull_request: @@ -17,12 +15,12 @@ jobs: matrix: config: - {os: macOS-latest, r: 'release'} - - {os: windows-latest, r: 'release'} - {os: windows-2022, r: 'devel'} - - {os: windows-2022, r: 'devel-ucrt'} - - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} - - {os: ubuntu-latest, r: 'release'} - - {os: ubuntu-latest, r: 'oldrel-1'} + - {os: windows-latest, r: '4.1'} + - {os: windows-latest, r: '3.6'} + - {os: ubuntu-20.04, r: 'devel', http-user-agent: 'release'} + - {os: ubuntu-20.04, r: 'release'} + - {os: ubuntu-18.04, r: 'oldrel-4'} env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} @@ -31,28 +29,17 @@ jobs: steps: - uses: actions/checkout@v2 - - uses: r-lib/actions/setup-pandoc@v1 + - uses: r-lib/actions/setup-pandoc@v2 - - uses: r-lib/actions/setup-r@v1 + - uses: r-lib/actions/setup-r@v2 with: r-version: ${{ matrix.config.r }} http-user-agent: ${{ matrix.config.http-user-agent }} use-public-rspm: true - - uses: r-lib/actions/setup-r-dependencies@v1 + - uses: r-lib/actions/setup-r-dependencies@v2 with: - extra-packages: rcmdcheck + extra-packages: any::rcmdcheck + needs: check - - uses: r-lib/actions/check-r-package@v1 - - - name: Show testthat output - if: always() - run: find check -name 'testthat.Rout*' -exec cat '{}' \; || true - shell: bash - - - name: Upload check results - if: failure() - uses: actions/upload-artifact@main - with: - name: ${{ runner.os }}-r${{ matrix.config.r }}-results - path: check + - uses: r-lib/actions/check-r-package@v2 diff --git a/DESCRIPTION b/DESCRIPTION index 1a663db..31c241a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: rsvg Title: Render SVG Images into PDF, PNG, (Encapsulated) PostScript, or Bitmap Arrays -Version: 2.1.2.9000 +Version: 2.1.9000 Authors@R: c( person("Jeroen", "Ooms", , "jeroen@berkeley.edu", role = c("aut", "cre"), comment = c(ORCID = "0000-0002-4035-0289")), diff --git a/NEWS b/NEWS index b0dac72..c59c176 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,6 @@ -2.1.2.9000 +2.2.0 - Add `rsvg_eps()` which converts to Encapsulated PostScript (EPS) format (@salim-b) + - Fix some deprecation warnings 2.1.2 - Windows: update to librsvg v2.48.8 diff --git a/R/rsvg.R b/R/rsvg.R index 6afb2a8..34fa69f 100644 --- a/R/rsvg.R +++ b/R/rsvg.R @@ -37,7 +37,7 @@ #' webp::write_webp(bitmap, "bitmap.webp", quality = 100) #' #' # cleanup -#' unlink(c("out.pdf", "out.png", "out.svg", "out.ps", "bitmap.webp")) +#' unlink(c("out.*", "bitmap.webp")) rsvg <- function(svg, width = NULL, height = NULL, css = NULL) { out <- rsvg_raw(svg, width = width, height = height, css = css) out <- structure(as.numeric(out)/255, dim = dim(out)) diff --git a/man/rsvg.Rd b/man/rsvg.Rd index 6d5b696..21e36c5 100644 --- a/man/rsvg.Rd +++ b/man/rsvg.Rd @@ -70,5 +70,5 @@ magick::image_read(bitmap) webp::write_webp(bitmap, "bitmap.webp", quality = 100) # cleanup -unlink(c("out.pdf", "out.png", "out.svg", "out.ps", "bitmap.webp")) +unlink(c("out.*", "bitmap.webp")) } diff --git a/src/rsvg.c b/src/rsvg.c index 1c73370..85a8853 100644 --- a/src/rsvg.c +++ b/src/rsvg.c @@ -16,13 +16,43 @@ typedef struct { size_t size; } memory; +#if LIBRSVG_CHECK_VERSION(2,52,0) +static int unit_to_px(RsvgLength x){ + double l = x.length; + switch(x.unit){ + case RSVG_UNIT_PX: + case RSVG_UNIT_PT: + return l; + case RSVG_UNIT_IN: + return 300*l; + case RSVG_UNIT_CM: + return 100*l; + default: + return 800; + } +} +#endif + +static void setup_render_handle(RsvgHandle *svg, cairo_t *cr){ +#if LIBRSVG_CHECK_VERSION(2,52,0) + GError *err = NULL; + RsvgRectangle viewport = {0.0}; + //viewport.width = width; + //viewport.height = height; + rsvg_handle_render_document(svg, cr, &viewport, &err); + if(err != NULL) + Rf_error("Failure in rsvg_handle_render_document: %s", err->message); +#else + if(!rsvg_handle_render_cairo(svg, cr)) + Rf_error("Cairo failed to render svg"); +#endif +} static SEXP write_bitmap(RsvgHandle *svg, int width, int height, double sx, double sy){ cairo_surface_t *canvas = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(canvas); cairo_scale(cr, sx, sy); - if(!rsvg_handle_render_cairo(svg, cr)) - Rf_error("Cairo failed to render svg"); + setup_render_handle(svg, cr); int stride = cairo_image_surface_get_stride(canvas); //should be equal to width * channels int size = stride * height; cairo_surface_flush(canvas); @@ -58,8 +88,7 @@ static SEXP write_png(RsvgHandle *svg, int width, int height, double sx, double cairo_surface_t *canvas = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(canvas); cairo_scale(cr, sx, sy); - if(!rsvg_handle_render_cairo(svg, cr)) - Rf_error("Cairo failed to render svg"); + setup_render_handle(svg, cr); memory mem = {NULL, 0}; cairo_surface_write_to_png_stream(canvas, write_func, &mem); cairo_surface_flush(canvas); @@ -79,8 +108,7 @@ static SEXP write_stream(RsvgHandle *svg, int width, int height, double sx, doub cairo_ps_surface_set_eps(canvas, TRUE); cairo_t *cr = cairo_create(canvas); cairo_scale(cr, sx, sy); - if(!rsvg_handle_render_cairo(svg, cr)) - Rf_error("Cairo failed to render svg"); + setup_render_handle(svg, cr); cairo_surface_show_page(canvas); cairo_surface_flush(canvas); cairo_surface_destroy(canvas); @@ -109,8 +137,24 @@ SEXP R_rsvg(SEXP data, SEXP rwidth, SEXP rheight, SEXP format, SEXP css){ Rf_warning("An external CSS file was specified but this requires at least librsvg 2.48 (you have %s)", LIBRSVG_VERSION); #endif } +#if LIBRSVG_CHECK_VERSION(2,52,0) + gboolean has_width; + RsvgLength in_width; + gboolean has_height; + RsvgLength in_height; + gboolean has_viewbox; + RsvgRectangle viewbox; + rsvg_handle_get_intrinsic_dimensions (svg, &has_width, &in_width, &has_height, &in_height, &has_viewbox, &viewbox); + double input_width = has_viewbox ? viewbox.width : (has_width ? unit_to_px(in_width) : 800); + double input_height = has_viewbox ? viewbox.height : (has_height ? unit_to_px(in_height) : 800); + //REprintf("Size: %fx%f\n", input_width, input_height); +#else RsvgDimensionData dimensions; rsvg_handle_get_dimensions(svg, &dimensions); + int input_width = dimensions.width; + int input_height = dimensions.height; + //REprintf("Size: %fx%f\n", (double)input_width, (double)input_height); +#endif //scale into the requested resolution double width; @@ -118,22 +162,22 @@ SEXP R_rsvg(SEXP data, SEXP rwidth, SEXP rheight, SEXP format, SEXP css){ double sx; double sy; if(rwidth == R_NilValue && rheight == R_NilValue){ - width = dimensions.width; - height = dimensions.height; + width = input_width; + height = input_height; sx = sy = 1; } else if(rwidth != R_NilValue && rheight != R_NilValue){ width = Rf_asInteger(rwidth); height = Rf_asInteger(rheight); - sx = width / dimensions.width; - sy = height / dimensions.height; + sx = width / input_width; + sy = height / input_height; } else if(rwidth != R_NilValue){ width = Rf_asInteger(rwidth); - sx = sy = width / dimensions.width; - height = round(dimensions.height * sy); + sx = sy = width / input_width; + height = round(input_height * sy); } else { height = Rf_asInteger(rheight); - sx = sy = height / dimensions.height; - width = round(dimensions.width * sx); + sx = sy = height / input_height; + width = round(input_width * sx); } switch(Rf_asInteger(format)){ case 0: