diff --git a/src/3rdparty/libuemf/uemf.c b/src/3rdparty/libuemf/uemf.c index fa7689bb6e96ff9db2066e491909f4dbfbeb59d1..f4c0bcf5b976498bfb6f62ac29da76ecf6493502 100644 --- a/src/3rdparty/libuemf/uemf.c +++ b/src/3rdparty/libuemf/uemf.c @@ -1541,6 +1541,37 @@ int drawing_size( return(0); } +/** + \brief Set up fields for an EMR_HEADER for drawing by physical size in 100th of mm and dots per millimeter. + Technically rclBounds is supposed to be the extent of the drawing within the EMF, but libUEMF has no way + of knowing this since it never actually draws anything. Instead this is set to the full drawing size. + Coordinates are inclusive inclusive, so 297 -> 0,29699. + \return 0 for success, >=1 for failure. + \param x100thmm Drawing width in 100ths of millimeter + \param y100thmm Drawing height in 100ths of millimeter + \param dpmm Dots per millimeter + \param rclBounds Drawing size structure in pixels + \param rclFrame Drawing size structure in mm +*/ +int drawing_size_100th( + const int x100thmm, + const int y100thmm, + const float dpmm, + U_RECTL *rclBounds, + U_RECTL *rclFrame + ){ + if(x100thmm < 0 || y100thmm < 0 || dpmm < 0)return(1); + rclBounds->left = 0; + rclBounds->top = 0; + rclBounds->right = U_ROUND((float) x100thmm * dpmm / 100.) - 1; // because coordinate system is 0,0 in upper left, N,M in lower right + rclBounds->bottom = U_ROUND((float) y100thmm * dpmm / 100.) - 1; + rclFrame->left = 0; + rclFrame->top = 0; + rclFrame->right = U_ROUND((float) x100thmm ) - 1; + rclFrame->bottom = U_ROUND((float) y100thmm ) - 1; + return(0); +} + /** \brief Set a U_COLORREF value from separate R,G,B values. \param red Red component diff --git a/src/3rdparty/libuemf/uemf.h b/src/3rdparty/libuemf/uemf.h index 3a51e39e296f893afa3fd00c4d47fc816e858804..da514e29831610bbecb648621be59818ddf19559 100644 --- a/src/3rdparty/libuemf/uemf.h +++ b/src/3rdparty/libuemf/uemf.h @@ -3375,7 +3375,8 @@ int DIB_to_RGBA(const char *px, const U_RGBQUAD *ct, int numCt, char *RGBA_to_RGBA(char *rgba_px, int w, int h, int sl, int st, int *ew, int *eh); int device_size(const int xmm, const int ymm, const float dpmm, U_SIZEL *szlDev, U_SIZEL *szlMm); -int drawing_size(const int xmm, const int yum, const float dpmm, U_RECTL *rclBounds, U_RECTL *rclFrame); +int drawing_size(const int xmm, const int ymm, const float dpmm, U_RECTL *rclBounds, U_RECTL *rclFrame); +int drawing_size_100th(const int x100thmm, const int y100thmm, const float dpmm, U_RECTL *rclBounds, U_RECTL *rclFrame); int emf_start(const char *name, const uint32_t initsize, const uint32_t chunksize, EMFTRACK **et); int emf_finish(EMFTRACK *et, EMFHANDLES *eht); diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp index 0fc7355206ae48937246ff4f6288cc62d2e9c080..efd79cd061e34bf2bc5e71480988de1cedfc8658 100644 --- a/src/extension/internal/emf-print.cpp +++ b/src/extension/internal/emf-print.cpp @@ -182,8 +182,8 @@ unsigned int PrintEmf::begin(Inkscape::Extension::Print *mod, SPDocument *doc) float dwInchesX = d.width(); float dwInchesY = d.height(); - // dwInchesX x dwInchesY in micrometer units, 1200 dpi/25.4 -> dpmm - (void) drawing_size((int) ceil(dwInchesX * 25.4), (int) ceil(dwInchesY * 25.4),1200.0/25.4, &rclBounds, &rclFrame); + // dwInchesX x dwInchesY in 100th of millimeter units, 1200 dpi/25.4 -> dpmm + (void) drawing_size_100th((int) ceil(dwInchesX * 25.4 * 100.), (int) ceil(dwInchesY * 25.4 * 100.),1200.0/25.4, &rclBounds, &rclFrame); // set up the reference device as 100 X A4 horizontal, (1200 dpi/25.4 -> dpmm). Extra digits maintain dpi better in EMF int MMX = 216; diff --git a/testfiles/cli_tests/CMakeLists.txt b/testfiles/cli_tests/CMakeLists.txt index 2d9f9202b567f05d2f1ce7dd0c124b79a8810459..ded28daddd2c38bc2d2ca6f437255140b22055ac 100644 --- a/testfiles/cli_tests/CMakeLists.txt +++ b/testfiles/cli_tests/CMakeLists.txt @@ -1091,6 +1091,13 @@ add_cli_test(actions-sequential-export-id-only_svg OUTPUT_FILENAME actions-sequential-export-id-only.svg REFERENCE_FILENAME export-id_export-id-only_expected.svg) +# EMF exports should be exact to a 100th of a milimeter (not increase to the next highest whole millimeter) +# https://gitlab.com/inkscape/inkscape/-/issues/8300 +add_cli_test(export-emf-100thmm + INPUT_FILENAME emf-100thmm.svg + PARAMETERS --export-type=emf --export-extension=org.inkscape.output.emf + OUTPUT_FILENAME export-emf-100thmm.emf + REFERENCE_FILENAME export-emf-100thmm_expected.emf) ########################### ### pdf input support ### diff --git a/testfiles/cli_tests/testcases/emf-100thmm.svg b/testfiles/cli_tests/testcases/emf-100thmm.svg new file mode 100644 index 0000000000000000000000000000000000000000..9f510174c2814de635022fcf0f5a54c37954aa7b --- /dev/null +++ b/testfiles/cli_tests/testcases/emf-100thmm.svg @@ -0,0 +1,45 @@ + + + + + + + + + + diff --git a/testfiles/cli_tests/testcases/export-emf-100thmm_expected.emf b/testfiles/cli_tests/testcases/export-emf-100thmm_expected.emf new file mode 100644 index 0000000000000000000000000000000000000000..65340a8577523bfbe3de1a6bcced223bf05613da Binary files /dev/null and b/testfiles/cli_tests/testcases/export-emf-100thmm_expected.emf differ