Skip to content

Commit

Permalink
Implement export to .ocd version 8. Templates are not exported yet, e…
Browse files Browse the repository at this point in the history
…verything else should work
  • Loading branch information
Thomas Schoeps committed Jul 4, 2012
1 parent e7eb724 commit 908d404
Show file tree
Hide file tree
Showing 15 changed files with 1,490 additions and 66 deletions.
80 changes: 80 additions & 0 deletions libocad/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ int ocad_file_open(OCADFile **pfile, const char *filename) {
if (file->fd <= 0) { err = -2; goto ocad_file_open_1; }
if (fstat(file->fd, &fs) < 0) { err = -3; goto ocad_file_open_1; }
file->size = fs.st_size;
file->reserved_size = file->size;

#ifdef MMAP_AVAILABLE
file->buffer = mmap(NULL, file->size, PROT_READ | PROT_WRITE, 0, file->fd, 0);
Expand Down Expand Up @@ -237,6 +238,84 @@ int ocad_file_save_as(OCADFile *pfile, const char *filename) {
return err;
}

int ocad_file_new(OCADFile **pfile) {
OCADFile *pnew;
u8 *dest, *p;
u32 size;

// Create OCADFile struct
pnew = (OCADFile *)malloc(sizeof(OCADFile));
if (pnew == NULL) return -1;
pnew->filename = NULL;
pnew->fd = 0;
pnew->mapped = FALSE;

// Allocate buffer
size = 1024 * 1024; // start with 1 MiB
dest = (u8 *)malloc(size);
if (dest == NULL) return -1;
memset(dest, 0, size);
p = dest;

pnew->buffer = dest;
pnew->reserved_size = size;

// Place header at start
pnew->header = (OCADFileHeader *)dest;
p += sizeof(OCADFileHeader);

// Color table
pnew->colors = (OCADColor *)p;
p += 256 * sizeof(OCADColor);
p += 32 * sizeof(OCADColorSeparation);

// Setup data
pnew->header->osetup = (p - dest);
pnew->header->ssetup = sizeof(OCADSetup); // NOTE: This does not include all possible elements!
pnew->setup = (OCADSetup *)p;
p += pnew->header->ssetup;

// First symbol block
pnew->header->osymidx = (p - dest);
p += sizeof(OCADSymbolIndex);

// First object block
pnew->header->oobjidx = (p - dest);
p += sizeof(OCADObjectIndex);

// String block
pnew->header->ostringidx = (p - dest);
p += sizeof(OCADStringIndex);

// Done
pnew->size = (p - dest);
*pfile = pnew;
return 0;
}

int ocad_file_reserve(OCADFile *file, int amount) {
u32 old_reserved_size = file->reserved_size;
if (file->reserved_size - file->size >= amount)
return 0;

u32 header_offset = (u8*)file->header - file->buffer;
u32 colors_offset = (u8*)file->colors - file->buffer;
u32 setup_offset = (u8*)file->setup - file->buffer;

while (file->reserved_size - file->size < amount) {
file->reserved_size *= 2;
}
file->buffer = realloc(file->buffer, file->reserved_size);

file->header = (OCADFileHeader*)(file->buffer + header_offset);
file->colors = (OCADColor*)(file->buffer + colors_offset);
file->setup = (OCADSetup*)(file->buffer + setup_offset);

if (file->buffer == NULL) return -1;
memset(file->buffer + old_reserved_size, 0, file->reserved_size - old_reserved_size);
return 0;
}

int ocad_file_compact(OCADFile *pfile) {
OCADFile dfile, *pnew;
u8 *dest, *p;
Expand All @@ -250,6 +329,7 @@ int ocad_file_compact(OCADFile *pfile) {
p = dest;
pnew->buffer = dest;
pnew->size = pfile->size; // will change this later...
pnew->reserved_size = pfile->size;
pnew->header = (OCADFileHeader *)dest;

b.base = dest;
Expand Down
3 changes: 2 additions & 1 deletion libocad/format8.txt
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,8 @@ ordinary map objects.
3: circle
4: dot (filled circle)}
stFlags: word; {Flags
1: line with round ends}
1: line with round ends
4: line with miter joins}
stColor: SmallInt; {color of the object. This is the
number which appears in the Colors
dialog box}
Expand Down
48 changes: 42 additions & 6 deletions libocad/libocad.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,19 @@ struct _OCADColor {
, OCADColor)


PACK(typedef
struct _OCADColorSeparation {
str sep_name[16];
byte cyan;
byte magenta;
byte yellow;
byte black;
word raster_freq;
word raster_angle;
}
, OCADColorSeparation)


PACK(typedef
struct _OCADSymbolEntry {
dword ptr;
Expand All @@ -175,7 +188,8 @@ struct _OCADSymbolIndex {
s16 size; \
s16 number; \
s16 type; \
s16 subtype; \
byte subtype; \
byte base_flags; \
s16 extent; \
bool selected; \
byte status; \
Expand Down Expand Up @@ -299,7 +313,8 @@ struct _OCADTextSymbol {
s16 color;
s16 dpts; // in decipoints
s16 bold; // as used in Windows GDI, 400=normal, 700=bold
wbool italic;
byte italic;
byte charset;
s16 cspace; // character spacing
s16 wspace; // word spacing
s16 halign; // left, center, right, justified = 0-3
Expand Down Expand Up @@ -354,7 +369,8 @@ struct _OCADRectSymbol {
PACK(typedef
struct _OCADObject {
s16 symbol; // symbol number
s16 type; // symbol type
byte type; // object type
byte unicode;
s16 npts; // number of OCADPoints
s16 ntext;
s16 angle;
Expand Down Expand Up @@ -432,7 +448,7 @@ struct _OCADSetup {
double grid; // in meters
double gpsangle;
// aGpsAdjust: array[0..11] of TGpsAdjPoint;
u8 notused[256+56]; // Contains <=v7 template info
u8 notused[12*40+4+8+8+8+256+2+2+8+8+8]; // Contains <=v7 template info
// Print information
OCADPoint printmin; // Lower left corner of print window
OCADPoint printmax; // Upper right corner of print window
Expand Down Expand Up @@ -474,7 +490,8 @@ struct _OCADFile {
const char *filename; // Filename
int fd; // File descriptor
u8 *buffer; // Location of the buffer
u32 size; // Size of the buffer
u32 size; // Size of the used part of the buffer
u32 reserved_size; // Complete size of the buffer
bool mapped; // Flag indicating whether the memory is mapped

OCADFileHeader *header; // Pointer to file header
Expand Down Expand Up @@ -661,6 +678,20 @@ bool ocad_rect_intersects(const OCADRect *r1, const OCADRect *r2);
*/
int ocad_to_background(OCADBackground *bg, OCADCString *templ);

/** Creates a new OCADFile struct in memory. Unused parts of the file buffer are set to zero.
*
* Returns OCAD_OK on success, or OCAD_OUT_OF_MEMORY.
*/
int ocad_file_new(OCADFile **pfile);

/** Makes sure that 'amount' number of bytes are reserved in the file's buffer
* in addition to the already used space. Sets newly reserved memory to zero.
* Returns OCAD_OK or OCAD_OUT_OF_MEMORY.
*
* WARNING: be extremely careful with this, as it might invalidate pointers to the buffer!
*/
int ocad_file_reserve(OCADFile *file, int amount);

/** Opens a file with the given filename. The file is loaded into memory and is accessible through
* the various ocad_file_* methods. The first argument can either be a pointer to a pre-allocated
* OCADFile object (e.g., on the stack), or NULL to cause the object to be allocated on the heap.
Expand Down Expand Up @@ -794,6 +825,11 @@ OCADSymbolIndex *ocad_symidx_next(OCADFile *pfile, OCADSymbolIndex *current);
int ocad_symbol_count(OCADFile *pfile);


/** Adds a new symbol with the given size in bytes to the file and returns a pointer to the new symbol.
*/
OCADSymbol *ocad_symbol_new(OCADFile *pfile, int size);


/** Returns a pointer to the symbol in the specified location within the index block, or NULL if there
* is no such symbol.
*/
Expand Down Expand Up @@ -932,7 +968,7 @@ OCADObject *ocad_object_alloc(const OCADObject *source);
* The provided object is copied into the file and is left unchanged by this call. A pointer to the new
* object is returned, or NULL if the object could not be added.
*/
OCADObject *ocad_object_add(OCADFile *file, const OCADObject *object);
OCADObject *ocad_object_add(OCADFile *file, const OCADObject *object, OCADObjectEntry** out_entry);

/** Returns a pointer to the first string index block, or NULL if the file isn't valid. Also returns
* NULL if the file contains no object.
Expand Down
43 changes: 33 additions & 10 deletions libocad/ocad_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,19 @@
#include "libocad.h"
#include "array.h"

static dword ocad_alloc_object(u32 npts) {
int size = 0x20 + 8 * npts;
size++;
return 0; // FIXME
static dword ocad_alloc_object(OCADFile *pfile, u32 num_coords) {
u32 index;
OCADObject* object;
int size = sizeof(OCADObject) - sizeof(OCADPoint) + 8 * num_coords;

if (ocad_file_reserve(pfile, size) == OCAD_OUT_OF_MEMORY)
return 0;
index = pfile->size;
object = (OCADObject*)(pfile->buffer + index);
object->npts = num_coords;
pfile->size += size;

return index;
}

static bool ocad_object_copy(OCADObject *dest, const OCADObject *src) {
Expand Down Expand Up @@ -63,30 +72,41 @@ OCADObjectEntry *ocad_object_entry_at(OCADFile *pfile, OCADObjectIndex *current,
}

OCADObjectEntry *ocad_object_entry_new(OCADFile *pfile, u32 npts) {
OCADObjectEntry *empty = NULL; // holder for first empty (npts=0) index entry, if needed
OCADObjectEntry *empty = NULL;
OCADObjectIndex *idx;
dword offs;
u32 last_idx_offset;
u32 empty_offset = 0; // holder for offset of first empty (npts=0) index entry, if needed

if (!pfile->header) return NULL;
if (npts == 0) return NULL;
for (idx = ocad_objidx_first(pfile); idx != NULL; idx = ocad_objidx_next(pfile, idx)) {
int i;
last_idx_offset = (u8*)idx - pfile->buffer;
for (i = 0; i < 256; i++) {
OCADObjectEntry *entry = &(idx->entry[i]);
if (entry->symbol == 0) {
if (entry->npts == 0 && !empty) empty = entry;
if (entry->npts == 0 && empty_offset == 0) empty_offset = (u8*)&idx->entry[i] - pfile->buffer;
else if (entry->npts >= npts) return entry;
}
}
}

if (!empty) {
if (empty_offset == 0) {
// We don't have any empty entries - need to create a new one!
return NULL; // FIXME
ocad_file_reserve(pfile, sizeof(OCADObjectIndex));
idx = (OCADObjectIndex*)(pfile->buffer + last_idx_offset);
idx->next = pfile->size;
idx = (OCADObjectIndex*)(pfile->buffer + pfile->size);
pfile->size += sizeof(OCADObjectIndex);
empty_offset = (u8*)&idx->entry[0] - pfile->buffer;
}

// There exists an empty index entry, with symbol=0 and npts=0. We can allocate a new object and fill it
offs = ocad_alloc_object(npts);
offs = ocad_alloc_object(pfile, npts);
if (offs == 0) return NULL; // no memory

empty = (OCADObjectEntry*)(pfile->buffer + empty_offset);
empty->ptr = offs;
empty->npts = npts;
// symbol, min, and max still need to be updated by the caller!
Expand Down Expand Up @@ -191,10 +211,13 @@ OCADObject *ocad_object_alloc(const OCADObject *source) {
}


OCADObject *ocad_object_add(OCADFile *file, const OCADObject *object) {
OCADObject *ocad_object_add(OCADFile *file, const OCADObject *object, OCADObjectEntry** out_entry) {
OCADObjectEntry *entry = ocad_object_entry_new(file, object->npts + object->ntext);
if (out_entry)
*out_entry = entry;
OCADObject *dest;
if (entry == NULL) return NULL;
entry->symbol = object->symbol;
dest = ocad_object(file, entry);
if (!ocad_object_copy(dest, object)) return NULL;
ocad_object_entry_refresh(file, entry, dest);
Expand Down
41 changes: 41 additions & 0 deletions libocad/ocad_symbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,47 @@ int ocad_symbol_count(OCADFile *pfile) {
return count;
}

OCADSymbol *ocad_symbol_new(OCADFile *pfile, int size) {
OCADSymbol* new_symbol;
OCADSymbolIndex *idx;
u32 last_idx_offset;
int i;
bool found = FALSE;

for (idx = ocad_symidx_first(pfile); idx != NULL; idx = ocad_symidx_next(pfile, idx)) {
last_idx_offset = (u8*)idx - pfile->buffer;
for (i = 0; i < 256; i++) {
OCADSymbol *sym = ocad_symbol_at(pfile, idx, i);
if (sym == NULL)
{
found = TRUE;
break;
}
}
if (found)
break;
}

if (idx == NULL) {
ocad_file_reserve(pfile, sizeof(OCADSymbolIndex) + size);
idx = (OCADSymbolIndex*)(pfile->buffer + last_idx_offset);
idx->next = pfile->size;
idx = (OCADSymbolIndex*)(pfile->buffer + pfile->size);
pfile->size += sizeof(OCADSymbolIndex);
i = 0;
}
else {
last_idx_offset = (u8*)idx - pfile->buffer;
ocad_file_reserve(pfile, size);
idx = (OCADSymbolIndex*)(pfile->buffer + last_idx_offset);
}

new_symbol = (OCADSymbol*)(pfile->buffer + pfile->size);
idx->entry[i].ptr = pfile->size;
pfile->size += size;
return new_symbol;
}

OCADSymbol *ocad_symbol_at(OCADFile *pfile, OCADSymbolIndex *current, int index) {
dword offs;
if (!pfile || !pfile->header || !current) return NULL;
Expand Down
Loading

0 comments on commit 908d404

Please sign in to comment.