From 3720fafac037bb637d2a5d194c6ee3ba07148831 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Sat, 14 Feb 2004 22:26:35 +0000 Subject: [project @ 2004-02-14 22:26:35 by jmb] Draw export module. svn path=/import/netsurf/; revision=541 --- riscos/save_draw.c | 456 +++++++++++++++++++++++++++++++++++++++++++++++++++++ riscos/save_draw.h | 15 ++ riscos/window.c | 5 + utils/config.h | 3 + 4 files changed, 479 insertions(+) create mode 100644 riscos/save_draw.c create mode 100644 riscos/save_draw.h diff --git a/riscos/save_draw.c b/riscos/save_draw.c new file mode 100644 index 000000000..e6e27294d --- /dev/null +++ b/riscos/save_draw.c @@ -0,0 +1,456 @@ +/* + * This file is part of NetSurf, http://netsurf.sourceforge.net/ + * Licensed under the GNU General Public License, + * http://www.opensource.org/licenses/gpl-license + * Copyright 2004 John M Bell + */ + +#include +#include + +#include "oslib/drawfile.h" +#include "oslib/jpeg.h" +#include "oslib/osfile.h" + +#include "netsurf/utils/config.h" +#include "netsurf/content/content.h" +#include "netsurf/css/css.h" +#include "netsurf/render/form.h" +#include "netsurf/render/layout.h" +#include "netsurf/riscos/save_draw.h" +#include "netsurf/utils/log.h" +#include "netsurf/utils/utils.h" + +/* TODO - fix fonts (see below) + * fix text issues + * fix jpegs + * fix duplicate image issue (qv www.iconbar.com) + * GUI + */ + +#ifdef WITH_DRAW_EXPORT + +/* in browser units = OS/2 = draw/512 */ +#define A4PAGEWIDTH (744) +#define A4PAGEHEIGHT (1052) +static unsigned long length; +static drawfile_diagram *d; + +static void add_font_table(void); +static void add_options(void); +static void add_objects(struct content *content, struct box *box, + unsigned long cbc, long x, long y); +static void add_graphic(struct content *content, struct box *box, + unsigned long cbc, long x, long y); +static void add_jpeg(struct content *content, struct box *box, + unsigned long cbc, long x, long y); +static void add_rect(struct content *content, struct box *box, + unsigned long cbc, long x, long y, bool bg); + +/* TODO - this will probably want to take a filename/path too... */ +void save_as_draw(struct content *c) { + + struct box *box = c->data.html.layout->children; + int temp = c->width; + unsigned long bc = 0xffffff; + + d = xcalloc(40, sizeof(char)); + + length = 40; + + memcpy((char*)&d->tag, "Draw", 4); + d->major_version = 201; + d->minor_version = 0; + memcpy((char*)&d->source, "NetSurf ", 12); + + /* recalculate box widths for an A4 page */ + layout_document(box, A4PAGEWIDTH); + + d->bbox.x0 = 0; + d->bbox.y0 = 0; + d->bbox.x1 = A4PAGEWIDTH*512; + d->bbox.y1 = A4PAGEHEIGHT*512; + + add_font_table(); + + add_options(); + + if (c->data.html.background_colour != TRANSPARENT) { + bc = c->data.html.background_colour; + add_rect(c, box, bc<<8, 0, A4PAGEHEIGHT*512, true); + } + + /* right, traverse the tree and grab the contents */ + add_objects(c, box, bc, 0, A4PAGEHEIGHT*512); + + xosfile_save_stamped(".draw", 0xaff, (byte*)d, (byte*)d+length); + + xfree(d); + + /* reset layout to current window width */ + layout_document(box, temp); +} + +/** + * add font table + * TODO - add all fonts required. for now we just use Homerton Medium + */ +void add_font_table() { + + drawfile_object *dro = xcalloc(8+28, sizeof(char)); + drawfile_font_table *ft = xcalloc(28, sizeof(char)); + drawfile_FONT_DEF(40) fd[] = { + { 1, "Homerton.Medium\\ELatin1" }, + /*{ 2, "Homerton.Medium.Oblique\\ELatin1" }, + { 3, "Homerton.Bold\\ELatin1" }, + { 4, "Homerton.Bold.Oblique\\ELatin1" },*/ + }; + + memcpy(ft->font_def, (char*)&fd, 28); + + dro->type = drawfile_TYPE_FONT_TABLE; + dro->size = 8+28; + memcpy((char*)&dro->data.font_table, ft, 28); + + d = xrealloc(d, (unsigned)length+dro->size); + + memcpy((char*)&d->objects, dro, (unsigned)dro->size); + + length += 8+28; + + xfree(ft); + xfree(dro); +} + +/** + * add options object + */ +void add_options() { + + drawfile_object *dro = xcalloc(8+80, sizeof(char)); + drawfile_options *dfo = xcalloc(80, sizeof(char)); + + dfo->bbox.x0 = dfo->bbox.y0 = dfo->bbox.x1 = dfo->bbox.y1 = 0; + dfo->paper_size = 0x500; /* A4 */ + dfo->paper_options = (drawfile_paper_options)0; + dfo->grid_spacing = 1; + dfo->grid_division = 2; + dfo->isometric = false; + dfo->auto_adjust = false; + dfo->show = false; + dfo->lock = false; + dfo->cm = true; + dfo->zoom_mul = 1; + dfo->zoom_div = 1; + dfo->zoom_lock = false; + dfo->toolbox = true; + dfo->entry_mode = drawfile_ENTRY_MODE_SELECT; + dfo->undo_size = 5000; + + dro->type = drawfile_TYPE_OPTIONS; + dro->size = 8+80; + memcpy((char*)&dro->data.options, dfo,(unsigned)dro->size-8); + + d = xrealloc(d, length+dro->size); + memcpy((char*)d+length, dro, (unsigned)dro->size); + + length += dro->size; + + xfree(dfo); + xfree(dro); +} + +/** + * Traverses box tree, adding objects to the diagram as it goes. + */ +void add_objects(struct content *content, struct box *box, + unsigned long cbc, long x, long y) { + + struct box *c; + int width, height, colour; + + x += box->x * 512; + y -= box->y * 512; + width = (box->padding[LEFT] + box->width + box->padding[RIGHT]) * 2; + height = (box->padding[TOP] + box->height + box->padding[BOTTOM]) * 2; + + if (box->style->visibility == CSS_VISIBILITY_HIDDEN) { + for (c = box->children; c; c = c->next) + add_objects(content, c, cbc, x, y); + return; + } + + if (box->style != 0 && box->style->background_color != TRANSPARENT) { + cbc = box->style->background_color; + add_rect(content, box, cbc<<8, x, y, false); + } + + if (box->object) { + if (box->object->type == CONTENT_PLUGIN || + box->object->type == CONTENT_OTHER || + box->object->type == CONTENT_UNKNOWN || + box->object->type == CONTENT_HTML || + box->object->type == CONTENT_TEXTPLAIN || + box->object->type == CONTENT_CSS || + box->object->type == CONTENT_DRAW) { + return; /* don't handle these */ + } + else { + add_graphic(box->object, box, cbc, x, y); + return; + } + } + else if (box->gadget && (box->gadget->type == GADGET_CHECKBOX || + box->gadget->type == GADGET_RADIO)) { + return; /* nor these... */ + } + else if (box->text && box->font) { + colour = box->style->color; + colour = ((((colour >> 16) + (cbc >> 16)) / 2) << 16) + | (((((colour >> 8) & 0xff) + + ((cbc >> 8) & 0xff)) / 2) << 8) + | ((((colour & 0xff) + (cbc & 0xff)) / 2) << 0); + /* ignore text decorations for now */ + { + drawfile_object *dro = xcalloc(8+44+((strlen(box->text)+1+3)/4*4), sizeof(char)); + drawfile_text *dt = xcalloc(44+((strlen(box->text)+1+3)/4*4), sizeof(char)); + + dt->bbox.x0 = x; + dt->bbox.y0 = y-(box->height*1.5*512); + dt->bbox.x1 = x+(box->width*512); + dt->bbox.y1 = y; + dt->fill = colour<<8; + dt->bg_hint = cbc<<8; + dt->style.font_index = 1; + dt->xsize = box->font->size*40; + dt->ysize = box->font->size*40; + dt->base.x = x; + dt->base.y = y-(box->height*512)+1536; + memcpy(dt->text, box->text, strlen(box->text)); + + dro->type = drawfile_TYPE_TEXT; + dro->size = ((strlen(box->text)+1+3)/4*4) + 44 + 8; + memcpy((char*)&dro->data.text, dt, (unsigned)dro->size-8); + d = xrealloc(d, (unsigned)length + dro->size); + memcpy((char*)d+length, dro, (unsigned)dro->size); + length += dro->size; + + xfree(dt); + xfree(dro); + return; + } + } + else { + for (c = box->children; c != 0; c = c->next) { + add_objects(content, c, cbc, x, y); + } + for (c = box->float_children; c != 0; c = c->next_float) { + add_objects(content, c, cbc, x, y); + } + } +} + +/** + * Add images to the drawfile. Uses add_jpeg as a helper. + */ +void add_graphic(struct content *content, struct box *box, + unsigned long cbc, long x, long y) { + + drawfile_object *dro; + drawfile_sprite *ds; + long sprite_length = 0; + + switch (content->type) { + case CONTENT_JPEG: + if (content->data.jpeg.use_module) { + sprite_length = -1; + } + else { + sprite_length = content->data.jpeg.sprite_area->size; + } + break; + case CONTENT_PNG: + sprite_length = content->data.png.sprite_area->size; + break; + case CONTENT_GIF: + sprite_length = content->data.gif.sprite_area->size; + break; + case CONTENT_SPRITE: + sprite_length = content->data.sprite.length-16; + break; + default: + break; + } + + if (sprite_length == -1 && content->type == CONTENT_JPEG) { + add_jpeg(content, box, cbc, x, y); + return; + } + + dro = xcalloc((unsigned)8 + 16 + sprite_length, sizeof(char)); + ds = xcalloc((unsigned)16 + sprite_length, sizeof(char)); + + ds->bbox.x0 = x; + ds->bbox.y0 = y-((box->padding[TOP] + box->height + box->padding[BOTTOM])*512); + ds->bbox.x1 = x+((box->padding[LEFT] + box->width + box->padding[RIGHT])*512); + + ds->bbox.y1 = y; + + switch (content->type) { + case CONTENT_JPEG: + memcpy((char*)ds+16, content->data.jpeg.sprite_area+1, + (unsigned)sprite_length); + break; + case CONTENT_PNG: + memcpy((char*)ds+16, content->data.png.sprite_area+1, + (unsigned)sprite_length); + break; + case CONTENT_GIF: + memcpy((char*)ds+16, content->data.gif.sprite_area+1, + (unsigned)sprite_length); + break; + case CONTENT_SPRITE: + memcpy((char*)ds+16, (char*)content->data.sprite.data+16, + (unsigned)sprite_length); + break; + default: + break; + } + + dro->type = drawfile_TYPE_SPRITE; + dro->size = 8 + 16 + sprite_length; + memcpy((char*)&dro->data.sprite, ds, (unsigned)16 + sprite_length); + + d = xrealloc(d, length+dro->size); + memcpy((char*)d+length, dro, (unsigned)dro->size); + + length += dro->size; + + xfree(ds); + xfree(dro); +} + +/** + * Add jpeg objects which the OS can cope with. + * Jpegs the OS doesn't understand are added as sprites + * This may still be a little buggy. + */ +void add_jpeg(struct content *content, struct box *box, + unsigned long cbc, long x, long y) { + + drawfile_object *dro = xcalloc(8+60+((content->data.jpeg.length+3)/4*4), sizeof(char)); + drawfile_jpeg *dj = xcalloc(60+((content->data.jpeg.length+3)/4*4), sizeof(char)); + + dj->bbox.x0 = x; + dj->bbox.y0 = y-((box->padding[TOP] + box->height + box->padding[BOTTOM])*512); + dj->bbox.x1 = x+((box->padding[LEFT] + box->width + box->padding[RIGHT])*512); + dj->bbox.y1 = y; + + xjpeginfo_dimensions((jpeg_image const*)content->data.jpeg.data, + (int)content->data.jpeg.length, + 0, &dj->width, &dj->height, + &dj->xdpi, &dj->ydpi, 0); + dj->width *= 512; + dj->height *= 512; + dj->trfm.entries[0][0] = 1 << 16; + dj->trfm.entries[0][1] = 0; + dj->trfm.entries[1][0] = 0; + dj->trfm.entries[1][1] = 1 << 16; + dj->trfm.entries[2][0] = x; + dj->trfm.entries[2][1] = dj->bbox.y0; + dj->len = content->data.jpeg.length; + memcpy((char*)&dj->image, content->data.jpeg.data, (unsigned)dj->len); + + dro->type = drawfile_TYPE_JPEG; + dro->size = 8 + 60 + ((dj->len+3)/4*4); + memcpy((char*)&dro->data.jpeg, dj, (unsigned)dro->size-8); + + d = xrealloc(d, length+dro->size); + memcpy((char*)d+length, dro, (unsigned)dro->size); + + length += dro->size; + + xfree(dj); + xfree(dro); +} + +/** + * Add a filled, borderless rectangle to the diagram + * Set bg to true to produce the background rectangle. + */ +void add_rect(struct content *content, struct box *box, + unsigned long cbc, long x, long y, bool bg) { + + drawfile_object *dro = xcalloc(8+96, sizeof(char)); + drawfile_path *dp = xcalloc(96, sizeof(char)); + draw_path_element *dpe = xcalloc(12, sizeof(char)); + + if (bg) { + dp->bbox.x0 = 0; + dp->bbox.y0 = 0; + dp->bbox.x1 = A4PAGEWIDTH*512; + dp->bbox.y1 = A4PAGEHEIGHT*512; + } + else { + dp->bbox.x0 = x; + dp->bbox.y0 = y-((box->padding[TOP] + box->height + box->padding[BOTTOM])*512); + dp->bbox.x1 = x+((box->padding[LEFT] + box->width + box->padding[RIGHT])*512); + dp->bbox.y1 = y; + } + + dp->fill = cbc; + dp->outline = cbc; + dp->width = 0; + dp->style.flags = 0; + + /** + * X<------X + * | ^ + * | | + * v | + * -->X------>X + */ + + /* bottom left */ + dpe->tag = draw_MOVE_TO; + dpe->data.move_to.x = dp->bbox.x0; + dpe->data.move_to.y = dp->bbox.y0; + memcpy((char*)&dp->path, dpe, 12); + /* bottom right */ + dpe->tag = draw_LINE_TO; + dpe->data.line_to.x = dp->bbox.x1; + dpe->data.line_to.y = dp->bbox.y0; + memcpy((char*)&dp->path+12, dpe, 12); + /* top right */ + dpe->tag = draw_LINE_TO; + dpe->data.line_to.x = dp->bbox.x1; + dpe->data.line_to.y = dp->bbox.y1; + memcpy((char*)&dp->path+24, dpe, 12); + /* top left */ + dpe->tag = draw_LINE_TO; + dpe->data.line_to.x = dp->bbox.x0; + dpe->data.line_to.y = dp->bbox.y1; + memcpy((char*)&dp->path+36, dpe, 12); + /* bottom left */ + dpe->tag = draw_LINE_TO; + dpe->data.line_to.x = dp->bbox.x0; + dpe->data.line_to.y = dp->bbox.y0; + memcpy((char*)&dp->path+48, dpe, 12); + /* end */ + dpe->tag = draw_END_PATH; + memcpy((char*)&dp->path+60, dpe, 4); + + dro->type = drawfile_TYPE_PATH; + dro->size = 8+96; + memcpy((char*)&dro->data.path, dp, (unsigned)dro->size-8); + + d = xrealloc(d, length+dro->size); + memcpy((char*)d+length, dro, (unsigned)dro->size); + + length += dro->size; + + xfree(dpe); + xfree(dp); + xfree(dro); +} +#endif diff --git a/riscos/save_draw.h b/riscos/save_draw.h new file mode 100644 index 000000000..ca58e924d --- /dev/null +++ b/riscos/save_draw.h @@ -0,0 +1,15 @@ +/* + * This file is part of NetSurf, http://netsurf.sourceforge.net/ + * Licensed under the GNU General Public License, + * http://www.opensource.org/licenses/gpl-license + * Copyright 2003 John M Bell + */ + +#ifndef _NETSURF_RISCOS_SAVE_DRAW_H_ +#define _NETSURF_RISCOS_SAVE_DRAW_H_ + +#include "netsurf/content/content.h" + +void save_as_draw(struct content *c); + +#endif diff --git a/riscos/window.c b/riscos/window.c index b2f5fcc56..4a0e12683 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -20,6 +20,7 @@ #include "netsurf/utils/config.h" #include "netsurf/riscos/constdata.h" #include "netsurf/riscos/gui.h" +#include "netsurf/riscos/save_draw.h" #include "netsurf/riscos/theme.h" #include "netsurf/utils/log.h" #include "netsurf/utils/utils.h" @@ -742,6 +743,10 @@ bool ro_gui_window_keypress(gui_window *g, int key, bool toolbar) #endif return true; + case wimp_KEY_SHIFT + wimp_KEY_CONTROL + wimp_KEY_F3: + save_as_draw(g->data.browser.bw->current_content); + return true; + case wimp_KEY_RETURN: if (!toolbar) break; diff --git a/utils/config.h b/utils/config.h index 66c1a20b6..f681c96be 100644 --- a/utils/config.h +++ b/utils/config.h @@ -43,5 +43,8 @@ /* ANT URL protocol support */ #define WITH_URL +/* Export modules */ +#define WITH_DRAW_EXPORT + #endif -- cgit v1.2.3