1 // This file is part of Deark.
2 // Copyright (C) 2018 Jason Summers
3 // See the file COPYING for terms of use.
5 // RISC OS Draw / Acorn Draw / ArcDraw
7 #include <deark-config.h>
8 #include <deark-private.h>
9 DE_DECLARE_MODULE(de_module_rodraw
);
21 typedef struct localctx_struct
{
22 unsigned int majver
, minver
;
26 static void do_object_sprite(deark
*c
, lctx
*d
, struct objinfo
*oi
)
32 fi
= de_finfo_create(c
);
38 // Skip transformation matrix
44 // Peek at the sprite name, to use in the output filename.
45 de_ucstring
*s
= NULL
;
46 s
= ucstring_create(c
);
47 dbuf_read_to_ucstring(c
->infile
, dpos
+4, 12, s
,
48 DE_CONVFLAG_STOP_AT_NUL
, DE_ENCODING_RISCOS
);
49 de_finfo_set_name_from_ucstring(c
, fi
, s
, 0);
53 // An .acorn extension may be needed to open these files with XnView.
54 outf
= dbuf_create_output_file(c
, "acorn", fi
, 0x0);
56 // Manufacture a sprite file, by adding a 12-byte header.
57 dbuf_writeu32le(outf
, 1); // number of sprites
58 dbuf_writeu32le(outf
, 12+4); // offset of sprite data (+4)
59 dbuf_writeu32le(outf
, 12+dlen
+4); // file size (+4)
60 dbuf_copy(c
->infile
, dpos
, dlen
, outf
);
63 de_finfo_destroy(c
, fi
);
66 // Caller sets oi->objtype.
67 // We set oi->tyname, oi->hasbbox.
68 static void get_objtype_info(struct objinfo
*oi
)
71 case 0: oi
->tyname
="font table"; break;
72 case 1: oi
->tyname
="text"; oi
->hasbbox
=1; break;
73 case 2: oi
->tyname
="path"; oi
->hasbbox
=1; break;
74 case 5: oi
->tyname
="sprite"; oi
->hasbbox
=1; break;
75 case 6: oi
->tyname
="group"; oi
->hasbbox
=1; break;
76 case 7: oi
->tyname
="tagged object"; oi
->hasbbox
=1; break;
77 case 9: oi
->tyname
="text area"; oi
->hasbbox
=1; break;
78 case 10: oi
->tyname
="text column"; oi
->hasbbox
=1; break;
79 case 11: oi
->tyname
="options"; oi
->hasbbox
=1; break;
80 case 12: oi
->tyname
="transformed text"; oi
->hasbbox
=1; break;
81 case 13: oi
->tyname
="transformed sprite"; oi
->hasbbox
=1; break;
82 case 65637: oi
->tyname
="DrawPlus internal data"; break;
84 if(!oi
->tyname
) oi
->tyname
="?";
87 static int do_object_sequence(deark
*c
, lctx
*d
, i64 pos1
, i64 len
);
89 static int do_object(deark
*c
, lctx
*d
, struct objinfo
*oi
)
91 if(oi
->objtype
==6) { // group
92 // TODO: group name, 12 bytes
93 do_object_sequence(c
, d
, oi
->dpos
+12, oi
->dlen
-12);
95 else if(oi
->objtype
==5) { // sprite
96 do_object_sprite(c
, d
, oi
);
98 else if(oi
->objtype
==13) { // transformed sprite
99 do_object_sprite(c
, d
, oi
);
101 // TODO: objtype 7 (tagged object)
106 static int do_object_sequence(deark
*c
, lctx
*d
, i64 pos1
, i64 len
)
111 if(d
->nesting_level
>16) goto done
;
116 de_zeromem(&oi
, sizeof(struct objinfo
));
118 if((oi
.objpos
+24) > (pos1
+len
)) break;
119 oi
.objtype
= (u32
)de_getu32le_p(&pos
);
120 oi
.objsize
= de_getu32le_p(&pos
);
121 if(oi
.objsize
<8 || (oi
.objpos
+oi
.objsize
)>(pos1
+len
)) {
122 de_err(c
, "Bad object size (%u) at %"I64_FMT
, (unsigned int)oi
.objsize
, oi
.objpos
);
126 get_objtype_info(&oi
);
128 de_dbg(c
, "object at %"I64_FMT
", type=%u (%s), len=%"I64_FMT
, oi
.objpos
,
129 oi
.objtype
, oi
.tyname
, oi
.objsize
);
135 oi
.dlen
= oi
.objpos
+oi
.objsize
- oi
.dpos
;
136 if(oi
.dlen
<0) goto done_obj
;
139 do_object(c
, d
, &oi
);
140 de_dbg_indent(c
, -1);
143 pos
= oi
.objpos
+ oi
.objsize
;
151 static int do_header(deark
*c
, lctx
*d
, i64 pos1
)
155 de_dbg(c
, "header at %d", (int)pos1
);
157 pos
+= 4; // file signature
158 d
->majver
= (unsigned int)de_getu32le_p(&pos
);
159 d
->minver
= (unsigned int)de_getu32le_p(&pos
);
160 de_dbg(c
, "format version: %u,%u", d
->majver
, d
->minver
);
161 pos
+= 12; // app name
162 pos
+= 16; // bounding box
163 de_dbg_indent(c
, -1);
167 static void de_run_rodraw(deark
*c
, de_module_params
*mparams
)
172 d
= de_malloc(c
, sizeof(lctx
));
175 if(!do_header(c
, d
, pos
)) goto done
;
178 if(!do_object_sequence(c
, d
, pos
, c
->infile
->len
-pos
)) goto done
;
184 static int de_identify_rodraw(deark
*c
)
186 if(!dbuf_memcmp(c
->infile
, 0, "Draw", 4)) {
187 if(!dbuf_memcmp(c
->infile
, 4, "\xc9\0\0\0\0\0\0\0", 8)) {
195 void de_module_rodraw(deark
*c
, struct deark_module_info
*mi
)
198 mi
->desc
= "RISC OS Draw, Acorn Draw";
199 mi
->run_fn
= de_run_rodraw
;
200 mi
->identify_fn
= de_identify_rodraw
;