Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WASM module and NPM library (javascript bindings) #892

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ on:
pull_request:
branches:
- '*'
workflow_dispatch:
branches:
- '*'

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
Expand Down Expand Up @@ -293,3 +296,17 @@ jobs:
- run: ninja
- run: copy libredwg.dll test\unit-testing\
- run: ctest . --output-on-failure
wasm:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: checkout
uses: actions/checkout@v3
with:
fetch-depth: 1
submodules: recursive
- name: Setup Emscripten toolchain
uses: mymindstorm/setup-emsdk@v13
- run: ./autogen.sh
- run: emconfigure ./configure --enable-libconvert-only --disable-bindings --disable-shared
- run: emmake make -j
8 changes: 6 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
cmake_minimum_required(VERSION 2.8...3.27)
project(libredwg C)
# Supported options -DLIBREDWG_LIBONLY=On
# -DLIBREDWG_LIBCONVERTONLY=On
# -DLIBREDWG_DISABLE_WRITE=On
# -DLIBREDWG_DISABLE_JSON=On
# -DENABLE_MIMALLOC=On
Expand Down Expand Up @@ -29,6 +30,7 @@ string(STRIP "${NL_PACKAGE_VERSION}" PACKAGE_VERSION)

option(BUILD_SHARED_LIBS "shared libredwg library" ON)
option(LIBREDWG_LIBONLY "only the libredwg library" OFF)
option(LIBREDWG_LIBCONVERTONLY "only the libredwg pure file format conversion library" OFF)
option(LIBREDWG_DISABLE_WRITE "no libredwg write support" OFF)
option(DISABLE_WERROR "no -Werror" OFF)
option(ENABLE_LTO "IPO/LTO Link Time Optimizations (default ON)" ON)
Expand Down Expand Up @@ -283,7 +285,9 @@ target_include_directories(${redwg} PUBLIC

link_libraries(${redwg} ${LIBS} ${CMAKE_THREAD_LIBS_INIT})

if(NOT LIBREDWG_LIBONLY)
if(LIBREDWG_LIBCONVERTONLY)
add_library(convert programs/convert.c)
elseif(NOT LIBREDWG_LIBONLY)
if(NOT HAVE_GETOPT_H)
set(getopt_c programs/getopt.c)
endif(NOT HAVE_GETOPT_H)
Expand Down Expand Up @@ -311,7 +315,7 @@ if(NOT LIBREDWG_LIBONLY)
#target_include_directories(dwggrep PUBLIC pcre2)
endif(HAVE_PCRE2_H)

endif(NOT LIBREDWG_LIBONLY)
endif(LIBREDWG_LIBCONVERTONLY)

if(ipo_supported)
message(STATUS "IPO / LTO enabled")
Expand Down
56 changes: 56 additions & 0 deletions bindings/js/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
These are the (initial) Javascript bindings for GNU LibreDWG.
You can convert between DWG, DXF, DXFB (binary) and JSON and output GeoJSON.
You can output multiple files after reading a single file.
It is based on WASM (emscripten).

Please wait for the official release before using this in production.

GNU LibreDWG is a free C library to handle DWG files. It aims to be a free replacement for the OpenDWG libraries. DWG is the native file format of AutoCAD.

LibreDWG is based on LibDWG, originally written by Felipe Castro.

LibreDWG is in beta development stage. Not all planned features are yet completed, but the API should stay mostly stable. At the moment our decoder (i.e. reader) is done, just some very advanced R2010+ and pre-R13 entities fail to read and are skipped over. The writer is good enough for R2000. Among the example applications we wrote using LibreDWG is a reader (from dwg, dxf, json), a writer (convert from dwg, dxf, json or add from scratch), a rewriter (i.e. saveas), an initial SVG and Postscript conversion, converters from and to DXF and JSON, dwggrep to search for text, and dwglayer to print the list of layers.

More information: https://www.gnu.org/software/libredwg/

Usage:

```js
import { convert } from 'libredwg'

let input = /* ... obtain a DWG ArrayBuffer using upload, fetch or IndexedDB */

/*
* Available inputs/outputs (case sensitive): dwg, dxf, dxfb, json, jsonString
* jsonString is json as a string, without the cost of internal (de)serialization
* Available DWG/DXF/DXFB versions: [TODO], true = detect / don't care, falsy = no export
* Available log levels: falsy: none, 1/error, 2/warn, 3/info, 4/trace, 5/insane, 9/all
* [TODO buffer sizes including log]
*
* default:
* {
* input: <required>
* from: { dwg: true }, // detect
* json: true,
* level: 'warn'
* }
*/
const res = convert({input, from: { dwg: 'R_2000' }, json: true, dxfb: 'R_2004', level: 'warn'})

/* Result:
* {
* error: 'INVALIDDWG',
* log: '...',
* }
* or:
* {
* log: '...',
* json: {...}
* dxfb: <ArrayBuffer>
* }
* [TODO list of codes]
*/
console.log('result', res)
```

Later versions might add the actual API, native node.js, streams, promises and Typescript.
4 changes: 4 additions & 0 deletions bindings/js/index.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
exports.convert = (args) => {
const { input, from, to } = args;
console.log("from cjs", args);
};
4 changes: 4 additions & 0 deletions bindings/js/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export function convert(args) {
const { input, from, to } = args;
console.log("from mjs", args);
}
21 changes: 21 additions & 0 deletions bindings/js/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "libredwg",
"version": "0.0.0-dev.0",
"description": "GNU LibreDWG is a free library to handle DWG/DXF files",
"main": "index.js",
"repository": "git://fr-an-k/libredwg.git",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's just a test through my fork and reservation of the library name, of course I will transfer ownership if desired. I just need auto updates in my production environment.

Copy link
Contributor

@rurban rurban Dec 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a valid Url mostly. The domain is missing

"author": "Frank van Leeuwen",
"keywords": [
"DWG",
"DXF",
"DXFB"
],
"license": "ISC",
"private": false,
"exports": {
".": {
"require": "./index.cjs",
"import": "./index.mjs"
}
}
}
9 changes: 9 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,15 @@ AS_IF([test x$enable_bindings = xno],
AC_MSG_RESULT([yes]),
AC_MSG_RESULT([no (default)]))

dnl --enable-libconvert-only
AC_MSG_CHECKING([for --enable-libconvert-only])
AC_ARG_ENABLE([libconvert-only],AS_HELP_STRING([--enable-libconvert-only],[
Build only the library for pure file format conversion (default: no).]),
[libconvert_only=yes
AC_MSG_RESULT([yes])],
AC_MSG_RESULT([no (default)]))
AM_CONDITIONAL([LIBCONVERTONLY], [test x$libconvert_only = xyes])

dnl --enable-check-less
AC_MSG_CHECKING([for --enable-check-less])
AC_ARG_ENABLE([check-less],AS_HELP_STRING([--enable-check-less],[
Expand Down
134 changes: 134 additions & 0 deletions programs/convert.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*****************************************************************************/
/* LibreDWG - free implementation of the DWG file format */
/* */
/* Copyright (C) 2018-2023 Free Software Foundation, Inc. */
/* */
/* This library is free software, licensed under the terms of the GNU */
/* General Public License as published by the Free Software Foundation, */
/* either version 3 of the License, or (at your option) any later version. */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/*****************************************************************************/

/* convert.c: simple API to read/write any format.
* Single read, multiple write supported.
* You should call done() once you're done.
*
* written by Frank van Leeuwen
*/

#include "dwg.h"
#include "decode.h"
#ifndef DISABLE_JSON
# include "in_json.h"
# include "out_json.h"
#endif
#ifndef DISABLE_DXF
# include "in_dxf.h"
# include "out_dxf.h"
#endif

Dwg_Data dwg;
int readError = DWG_ERR_IOERROR;

EXPORT
void done() {
if (!readError)
dwg_free(&dwg);
}

EXPORT
void read(unsigned char* buf, size_t size, const char* type, unsigned char level) {
Bit_Chain dat = EMPTY_CHAIN (0);
dat.chain = buf;
dat.size = size;
dat.opts = level & DWG_OPTS_LOGLEVEL;
memset (&dwg, 0, sizeof (Dwg_Data));

if (!readError)
done();

int error = 0;
if (!strcmp(type, "dwg")) {
error = dwg_decode (&dat, &dwg);
if (error)
dwg_free(&dwg);
}
#ifndef DISABLE_DXF
else if (!strcmp(type, "dxf")) {
error = dwg_read_dxf (&dat, &dwg);
}
else if (!strcmp(type, "dxfb")) {
error = dwg_read_dxfb (&dat, &dwg);
}
#endif
#ifndef DISABLE_JSON
else if (!strcmp(type, "json")) {
error = dwg_read_json (&dat, &dwg);
}
#endif
else if (!strcmp(type, "geojson")) {
error = DWG_ERR_NOTYETSUPPORTED;
}
else if (!strcmp(type, "yaml")) {
error = DWG_ERR_NOTYETSUPPORTED;
}
else if (!strcmp(type, "xml")) {
error = DWG_ERR_NOTYETSUPPORTED;
}
else {
error = DWG_ERR_INVALIDTYPE;
}
readError = error;
return error;
}

EXPORT
void write(unsigned char* buf, size_t size, const char* type, const char* version, int level, bool minimal) {
Bit_Chain dat = EMPTY_CHAIN (0);
dat.chain = buf;
dat.size = size;
dat.opts = (level & DWG_OPTS_LOGLEVEL) | (minimal ? DWG_OPTS_MINIMAL : 0);

if (readError)
return DWG_ERR_IOERROR;
if (version && *version)
dwg.header.version = dwg_version_as(version);
if (dwg.header.version == R_INVALID) {
return DWG_ERR_INVALIDTYPE;
}

int error = 0;
if (!type) {
error = DWG_ERR_INVALIDTYPE;
}
else if (!strcmp(type, "dwg")) {
error = dwg_encode(&dat, &dwg);
}
#ifndef DISABLE_DXF
else if (!strcmp(type, "dxf")) {
error = dwg_write_dxf(&dat, &dwg);
}
else if (!strcmp(type, "dxfb")) {
error = dwg_write_dxfb(&dat, &dwg);
}
#endif
#ifndef DISABLE_JSON
else if (!strcmp(type, "json")) {
error = dwg_write_json(&dat, &dwg);
}
else if (!strcmp(type, "geojson")) {
error = dwg_write_geojson(&dat, &dwg);
}
#endif
else if (!strcmp(type, "yaml")) {
error = DWG_ERR_NOTYETSUPPORTED;
}
else if (!strcmp(type, "xml")) {
error = DWG_ERR_NOTYETSUPPORTED;
}
else {
error = DWG_ERR_INVALIDTYPE;
}
return error;
}
3 changes: 3 additions & 0 deletions src/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
/* Defined to <strings.h> or <string.h> if strcasecmp is found */
#undef AX_STRCASECMP_HEADER

/* Define to build only the LibreDWG simple convert library. */
#undef LIBCONVERTONLY

/* Define to 1 if using 'alloca.c'. */
#undef C_ALLOCA

Expand Down
Loading