2004-02-15 01:26:35 +03:00
/*
* 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 < jmb202 @ ecs . soton . ac . uk >
2004-07-06 00:19:52 +04:00
* Copyright 2004 John Tytgat < John . Tytgat @ aaug . net >
2004-02-15 01:26:35 +03:00
*/
2004-06-03 01:26:12 +04:00
# include <assert.h>
2004-02-15 06:19:21 +03:00
# include <math.h>
2004-02-15 01:26:35 +03:00
# include <stdbool.h>
# include <string.h>
# include "oslib/drawfile.h"
# include "oslib/jpeg.h"
2004-07-06 00:19:52 +04:00
# include "oslib/osgbpb.h"
2004-02-15 01:26:35 +03:00
# include "oslib/osfile.h"
2004-07-06 00:19:52 +04:00
# include "oslib/osfind.h"
2004-02-15 01:26:35 +03:00
# include "netsurf/utils/config.h"
# include "netsurf/content/content.h"
# include "netsurf/css/css.h"
2004-06-03 01:26:12 +04:00
# include "netsurf/desktop/gui.h"
2004-02-15 01:26:35 +03:00
# 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"
# ifdef WITH_DRAW_EXPORT
/* in browser units = OS/2 = draw/512 */
# define A4PAGEWIDTH (744)
# define A4PAGEHEIGHT (1052)
2004-06-03 01:26:12 +04:00
2004-07-06 00:19:52 +04:00
/* Must be a power of 2 */
# define DRAWBUF_INITIAL_SIZE (1<<14)
typedef enum {
DrawBuf_eHeader ,
DrawBuf_eFontTable ,
DrawBuf_eBody
} drawbuf_type_e ;
typedef struct {
byte * bufP ;
size_t currentSize ;
size_t maxSize ;
} drawbuf_part_t ;
typedef struct {
drawbuf_part_t header ;
drawbuf_part_t fontTable ;
drawbuf_part_t body ;
void * * fontNamesP ; /**< 256 element malloc() pointer array */
size_t numFonts ;
} drawbuf_t ;
static byte * drawbuf_claim ( size_t size , drawbuf_type_e type ) ;
static void drawbuf_free ( void ) ;
static bool drawbuf_add_font ( const char * fontNameP , byte * fontIndex ) ;
static bool drawbuf_save_file ( const char * drawfilename ) ;
static bool add_options ( void ) ;
static bool add_box ( struct box * box , unsigned long cbc , long x , long y ) ;
static bool add_graphic ( struct content * content , struct box * box ,
2004-06-03 01:26:12 +04:00
unsigned long cbc , long x , long y ) ;
2004-07-06 00:19:52 +04:00
static bool add_rect ( struct box * box ,
2004-06-03 01:26:12 +04:00
unsigned long cbc , long x , long y , bool bg ) ;
2004-07-06 00:19:52 +04:00
static bool add_line ( struct box * box , unsigned long cbc , long x , long y ) ;
static bool add_circle ( struct box * box , unsigned long cbc , long x , long y ) ;
static bool add_text ( struct box * box , unsigned long cbc , long x , long y ) ;
2004-06-03 01:26:12 +04:00
2004-07-06 00:19:52 +04:00
static drawbuf_t oDrawBuf ; /* static -> complete struct inited to 0 */
2004-06-03 01:26:12 +04:00
/**
* Export a content as a Drawfile .
*
* \ param c content to export
* \ param path path to save Drawfile as
* \ return true on success , false on error and error reported
*/
2004-07-06 00:19:52 +04:00
bool save_as_draw ( struct content * c , const char * path )
2004-02-26 03:44:42 +03:00
{
2004-02-17 00:09:40 +03:00
struct box * box ;
2004-06-03 01:26:12 +04:00
int current_width ;
2004-02-17 00:09:40 +03:00
unsigned long bc ;
2004-07-06 00:19:52 +04:00
drawfile_diagram_base * diagram ;
2004-02-17 00:09:40 +03:00
2004-07-06 00:19:52 +04:00
if ( c - > type ! = CONTENT_HTML )
2004-06-03 01:26:12 +04:00
return false ;
2004-02-17 00:09:40 +03:00
box = c - > data . html . layout - > children ;
2004-06-03 01:26:12 +04:00
current_width = c - > available_width ;
2004-02-15 01:26:35 +03:00
2004-07-06 00:19:52 +04:00
if ( ( diagram = drawbuf_claim ( sizeof ( drawfile_diagram_base ) , DrawBuf_eHeader ) ) = = NULL )
goto draw_save_error ;
2004-02-15 01:26:35 +03:00
2004-07-06 00:19:52 +04:00
/* write the Draw diagram */
2004-06-03 01:26:12 +04:00
memcpy ( diagram - > tag , " Draw " , 4 ) ;
diagram - > major_version = 201 ;
diagram - > minor_version = 0 ;
memcpy ( diagram - > source , " NetSurf " , 12 ) ;
2004-02-15 01:26:35 +03:00
/* recalculate box widths for an A4 page */
2004-07-06 00:19:52 +04:00
if ( ! layout_document ( box , A4PAGEWIDTH , c - > data . html . box_pool ) ) {
warn_user ( " NoMemory " , 0 ) ;
goto draw_save_error ;
}
2004-02-15 01:26:35 +03:00
2004-06-03 01:26:12 +04:00
diagram - > bbox . x0 = 0 ;
diagram - > bbox . y0 = 0 ;
diagram - > bbox . x1 = A4PAGEWIDTH * 512 ;
diagram - > bbox . y1 = A4PAGEHEIGHT * 512 ;
2004-02-15 01:26:35 +03:00
2004-07-06 00:19:52 +04:00
if ( ! add_options ( ) )
goto draw_save_error ;
2004-02-15 01:26:35 +03:00
2004-07-06 00:19:52 +04:00
bc = 0xffffff ;
2004-02-15 01:26:35 +03:00
if ( c - > data . html . background_colour ! = TRANSPARENT ) {
bc = c - > data . html . background_colour ;
2004-07-06 00:19:52 +04:00
if ( ! add_rect ( box , bc < < 8 , 0 , A4PAGEHEIGHT * 512 , true ) )
goto draw_save_error ;
2004-02-15 01:26:35 +03:00
}
/* right, traverse the tree and grab the contents */
2004-07-06 00:19:52 +04:00
if ( ! add_box ( box , bc , 0 , A4PAGEHEIGHT * 512 ) )
goto draw_save_error ;
2004-02-15 01:26:35 +03:00
2004-07-06 00:19:52 +04:00
if ( ! drawbuf_save_file ( path ) )
goto draw_save_error ;
2004-02-15 01:26:35 +03:00
2004-07-06 00:19:52 +04:00
drawbuf_free ( ) ;
2004-02-15 01:26:35 +03:00
2004-06-03 01:26:12 +04:00
/* reset layout to current window width */
2004-07-06 00:19:52 +04:00
if ( ! layout_document ( box , current_width , c - > data . html . box_pool ) ) {
2004-06-03 01:26:12 +04:00
warn_user ( " NoMemory " , 0 ) ;
2004-07-06 00:19:52 +04:00
return false ;
}
2004-02-15 01:26:35 +03:00
2004-06-03 01:26:12 +04:00
return true ;
2004-02-15 01:26:35 +03:00
2004-07-06 00:19:52 +04:00
draw_save_error :
drawbuf_free ( ) ;
2004-06-03 01:26:12 +04:00
/* attempt to reflow back on failure */
2004-07-06 00:19:52 +04:00
( void ) layout_document ( box , current_width , c - > data . html . box_pool ) ;
2004-06-03 01:26:12 +04:00
return false ;
}
2004-02-16 01:19:43 +03:00
2004-06-03 01:26:12 +04:00
/**
2004-07-06 00:19:52 +04:00
* Claim size number of bytes available in that
* particular buffer .
*
* \ param size number of bytes to claim
* \ param type defines which Draw buffer needs its size to be ensured
* \ return non NULL when buffer size got correctly claimed , NULL on failure
2004-06-03 01:26:12 +04:00
*/
2004-07-06 00:19:52 +04:00
static byte * drawbuf_claim ( size_t size , drawbuf_type_e type )
2004-06-03 01:26:12 +04:00
{
2004-07-06 00:19:52 +04:00
drawbuf_part_t * drawBufPartP ;
2004-06-03 01:26:12 +04:00
2004-07-06 00:19:52 +04:00
switch ( type ) {
case DrawBuf_eHeader :
drawBufPartP = & oDrawBuf . header ;
break ;
case DrawBuf_eFontTable :
drawBufPartP = & oDrawBuf . fontTable ;
break ;
case DrawBuf_eBody :
drawBufPartP = & oDrawBuf . body ;
break ;
default :
assert ( 0 ) ;
}
2004-02-16 01:19:43 +03:00
2004-07-06 00:19:52 +04:00
if ( drawBufPartP - > bufP = = NULL ) {
const size_t sizeNeeded = ( size > DRAWBUF_INITIAL_SIZE ) ? size : DRAWBUF_INITIAL_SIZE ;
if ( ( drawBufPartP - > bufP = malloc ( sizeNeeded ) ) = = NULL ) {
warn_user ( " NoMemory " , 0 ) ;
return NULL ;
}
drawBufPartP - > currentSize = size ;
drawBufPartP - > maxSize = sizeNeeded ;
} else if ( drawBufPartP - > maxSize < drawBufPartP - > currentSize + size ) {
size_t sizeNeeded = drawBufPartP - > maxSize ;
while ( ( sizeNeeded * = 2 ) < drawBufPartP - > currentSize + size )
;
if ( ( drawBufPartP - > bufP = realloc ( drawBufPartP - > bufP , sizeNeeded ) ) = = NULL ) {
warn_user ( " NoMemory " , 0 ) ;
return NULL ;
}
drawBufPartP - > currentSize + = size ;
drawBufPartP - > maxSize = sizeNeeded ;
} else {
drawBufPartP - > currentSize + = size ;
}
2004-02-16 01:19:43 +03:00
2004-07-06 00:19:52 +04:00
return drawBufPartP - > bufP + drawBufPartP - > currentSize - size ;
}
2004-02-16 01:19:43 +03:00
2004-07-06 00:19:52 +04:00
/**
* Frees all the Draw buffers .
*/
static void drawbuf_free ( void )
{
free ( oDrawBuf . header . bufP ) ; oDrawBuf . header . bufP = NULL ;
free ( oDrawBuf . fontTable . bufP ) ; oDrawBuf . fontTable . bufP = NULL ;
free ( oDrawBuf . body . bufP ) ; oDrawBuf . body . bufP = NULL ;
if ( oDrawBuf . fontNamesP ! = NULL ) {
while ( oDrawBuf . numFonts > 0 )
free ( oDrawBuf . fontNamesP [ - - oDrawBuf . numFonts ] ) ;
free ( oDrawBuf . fontNamesP ) ; oDrawBuf . fontNamesP = NULL ;
}
oDrawBuf . numFonts = 0 ;
}
2004-02-16 01:19:43 +03:00
2004-02-15 01:26:35 +03:00
2004-07-06 00:19:52 +04:00
/**
* Return a font index for given RISC OS font name .
*
* \ param fontNameP NUL terminated RISC OS font name .
* \ param fontIndex Returned font index 0 - 255 for given font name .
* \ return true on success , false on error and error reported
*/
static bool drawbuf_add_font ( const char * fontNameP , byte * fontIndex )
{
size_t index ;
2004-02-15 01:26:35 +03:00
2004-07-06 00:19:52 +04:00
for ( index = 0 ; index < oDrawBuf . numFonts ; + + index ) {
if ( ! strcmp ( oDrawBuf . fontNamesP [ index ] , fontNameP ) ) {
* fontIndex = ( byte ) index + 1 ;
return true ;
}
}
/* Only max 255 RISC OS outline fonts can be stored in a Draw
* file .
*/
if ( oDrawBuf . numFonts = = 255 )
return false ; /** \todo: report GUI error */
if ( oDrawBuf . fontNamesP = = NULL
& & ( ( oDrawBuf . fontNamesP = malloc ( 255 * sizeof ( void * ) ) ) = = NULL ) ) {
warn_user ( " NoMemory " , 0 ) ;
return false ;
}
* fontIndex = ( byte ) oDrawBuf . numFonts + 1 ;
if ( ( oDrawBuf . fontNamesP [ oDrawBuf . numFonts + + ] = strdup ( fontNameP ) ) = = NULL )
2004-06-03 01:26:12 +04:00
return false ;
2004-02-15 01:26:35 +03:00
2004-07-06 00:19:52 +04:00
return true ;
}
/**
* Save the Draw file from memory to disk .
*
* \ param drawfilename RISC OS filename where to save the Draw file .
* \ return true on success , false on error and error reported
*/
static bool drawbuf_save_file ( const char * drawfilename )
{
size_t index ;
os_fw * handle = NULL ;
os_error * error ;
/* create font table (if needed). */
if ( oDrawBuf . numFonts > 0 ) {
drawfile_object * dro ;
if ( ( dro = drawbuf_claim ( 8 , DrawBuf_eFontTable ) ) = = NULL )
goto file_save_error ;
dro - > type = drawfile_TYPE_FONT_TABLE ;
/* we can't write dro->size yet. */
for ( index = 0 ; index < oDrawBuf . numFonts ; + + index ) {
const char * fontNameP = oDrawBuf . fontNamesP [ index ] ;
size_t len = 1 + strlen ( fontNameP ) + 1 ;
byte * bufP ;
if ( ( bufP = drawbuf_claim ( len , DrawBuf_eFontTable ) ) = = NULL )
goto file_save_error ;
* bufP + + = ( byte ) index + 1 ;
memcpy ( bufP , fontNameP , len + 1 ) ;
}
/* align to next word boundary */
if ( oDrawBuf . fontTable . currentSize % 4 ) {
size_t wordpad = 4 - ( oDrawBuf . fontTable . currentSize & 3 ) ;
byte * bufP ;
if ( ( bufP = drawbuf_claim ( wordpad , DrawBuf_eFontTable ) ) = = NULL )
goto file_save_error ;
memset ( bufP , ' \0 ' , wordpad ) ;
}
/* note that at the point it can be that
* dro ! = oDrawBuf . fontTable . bufP
*/
( ( drawfile_object * ) oDrawBuf . fontTable . bufP ) - > size = oDrawBuf . fontTable . currentSize ;
}
if ( ( error = xosfind_openoutw ( osfind_NO_PATH , drawfilename , NULL , & handle ) ) ! = NULL )
goto file_save_error ;
/* write Draw header */
if ( ( error = xosgbpb_writew ( handle , oDrawBuf . header . bufP , oDrawBuf . header . currentSize , NULL ) ) ! = NULL )
goto file_save_error ;
/* write font table (if needed) */
if ( oDrawBuf . fontTable . bufP ! = NULL
& & ( error = xosgbpb_writew ( handle , oDrawBuf . fontTable . bufP , oDrawBuf . fontTable . currentSize , NULL ) ) ! = NULL )
goto file_save_error ;
/* write Draw body */
if ( ( error = xosgbpb_writew ( handle , oDrawBuf . body . bufP , oDrawBuf . body . currentSize , NULL ) ) ! = NULL )
goto file_save_error ;
2004-02-15 01:26:35 +03:00
2004-07-06 00:19:52 +04:00
if ( ( error = xosfind_closew ( handle ) ) ! = NULL )
goto file_save_error ;
if ( ( error = xosfile_set_type ( drawfilename , osfile_TYPE_DRAW ) ) ! = NULL )
goto file_save_error ;
2004-02-15 01:26:35 +03:00
2004-06-03 01:26:12 +04:00
return true ;
2004-07-06 00:19:52 +04:00
file_save_error :
LOG ( ( " drawbuf_save_file() error: 0x%x: %s " ,
error - > errnum , error - > errmess ) ) ;
warn_user ( " SaveError " , error - > errmess ) ;
if ( handle ! = NULL )
( void ) xosfind_closew ( handle ) ;
return false ;
2004-02-15 01:26:35 +03:00
}
2004-06-03 01:26:12 +04:00
2004-02-15 01:26:35 +03:00
/**
* add options object
*/
2004-07-06 00:19:52 +04:00
bool add_options ( void )
2004-06-03 01:26:12 +04:00
{
drawfile_object * dro ;
drawfile_options * dfo ;
2004-07-06 00:19:52 +04:00
if ( ( dro = drawbuf_claim ( 8 + sizeof ( drawfile_options ) , DrawBuf_eBody ) ) = = NULL )
2004-06-03 01:26:12 +04:00
return false ;
dro - > type = drawfile_TYPE_OPTIONS ;
2004-07-06 00:19:52 +04:00
dro - > size = 8 + sizeof ( drawfile_options ) ;
2004-06-03 01:26:12 +04:00
2004-07-06 00:19:52 +04:00
dfo = & dro - > data . options ;
2004-06-03 01:26:12 +04:00
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 ;
return true ;
2004-02-15 01:26:35 +03:00
}
2004-06-03 01:26:12 +04:00
2004-02-15 01:26:35 +03:00
/**
* Traverses box tree , adding objects to the diagram as it goes .
*/
2004-07-06 00:19:52 +04:00
bool add_box ( struct box * box , unsigned long cbc , long x , long y )
2004-06-03 01:26:12 +04:00
{
2004-02-15 01:26:35 +03:00
struct box * c ;
x + = box - > x * 512 ;
y - = box - > y * 512 ;
2004-06-03 01:26:12 +04:00
if ( box - > style & & box - > style - > visibility = = CSS_VISIBILITY_HIDDEN ) {
2004-07-06 00:19:52 +04:00
for ( c = box - > children ; c ! = NULL ; c = c - > next ) {
if ( ! add_box ( c , cbc , x , y ) )
2004-06-03 01:26:12 +04:00
return false ;
}
return true ;
2004-02-15 01:26:35 +03:00
}
2004-07-06 00:19:52 +04:00
if ( box - > style & & box - > style - > background_color ! = TRANSPARENT ) {
2004-02-15 01:26:35 +03:00
cbc = box - > style - > background_color ;
2004-07-06 00:19:52 +04:00
if ( ! add_rect ( box , cbc < < 8 , x , y , false ) )
2004-06-03 01:26:12 +04:00
return false ;
2004-02-15 01:26:35 +03:00
}
if ( box - > object ) {
2004-06-03 01:26:12 +04:00
switch ( box - > object - > type ) {
case CONTENT_JPEG :
# ifdef WITH_PNG
case CONTENT_PNG :
# endif
case CONTENT_GIF :
# ifdef WITH_SPRITE
case CONTENT_SPRITE :
# endif
2004-07-06 00:19:52 +04:00
return add_graphic ( box - > object ,
2004-06-03 01:26:12 +04:00
box , cbc , x , y ) ;
case CONTENT_HTML :
c = box - > object - > data . html . layout - > children ;
2004-07-06 00:19:52 +04:00
return add_box ( c , cbc , x , y ) ;
2004-02-15 17:17:29 +03:00
}
2004-02-16 01:37:52 +03:00
2004-06-03 01:26:12 +04:00
} else if ( box - > gadget & & box - > gadget - > type = = GADGET_CHECKBOX ) {
2004-07-06 00:19:52 +04:00
return add_rect ( box , 0xDEDEDE00 , x , y , false ) ;
2004-06-03 01:26:12 +04:00
} else if ( box - > gadget & & box - > gadget - > type = = GADGET_RADIO ) {
2004-07-06 00:19:52 +04:00
return add_circle ( box , 0xDEDEDE00 , x , y ) ;
2004-02-16 01:37:52 +03:00
2004-06-03 01:26:12 +04:00
} else if ( box - > text & & box - > font ) {
2004-07-06 00:19:52 +04:00
int colour ;
2004-06-03 01:26:12 +04:00
2004-07-06 00:19:52 +04:00
if ( box - > length = = 0 )
2004-06-03 01:26:12 +04:00
return true ;
/* text-decoration */
2004-02-15 01:26:35 +03:00
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 ) ;
2004-07-06 00:19:52 +04:00
if ( box - > style - > text_decoration & CSS_TEXT_DECORATION_UNDERLINE
| | ( box - > parent - > parent - > style - > text_decoration & CSS_TEXT_DECORATION_UNDERLINE & & box - > parent - > parent - > type = = BOX_BLOCK ) ) {
if ( ! add_line ( box , ( unsigned ) colour < < 8 ,
2004-06-03 01:26:12 +04:00
x , ( int ) ( y + ( box - > height * 0.1 * 512 ) ) ) )
return false ;
2004-02-15 06:19:21 +03:00
}
2004-07-06 00:19:52 +04:00
if ( box - > style - > text_decoration & CSS_TEXT_DECORATION_OVERLINE
| | ( box - > parent - > parent - > style - > text_decoration & CSS_TEXT_DECORATION_OVERLINE & & box - > parent - > parent - > type = = BOX_BLOCK ) ) {
if ( ! add_line ( box , ( unsigned ) colour < < 8 ,
2004-06-03 01:26:12 +04:00
x , ( int ) ( y + ( box - > height * 0.9 * 512 ) ) ) )
return false ;
2004-02-15 06:19:21 +03:00
}
if ( box - > style - > text_decoration & CSS_TEXT_DECORATION_LINE_THROUGH | | ( box - > parent - > parent - > style - > text_decoration & CSS_TEXT_DECORATION_LINE_THROUGH & & box - > parent - > parent - > type = = BOX_BLOCK ) ) {
2004-07-06 00:19:52 +04:00
if ( ! add_line ( box , ( unsigned ) colour < < 8 ,
2004-06-03 01:26:12 +04:00
x , ( int ) ( y + ( box - > height * 0.4 * 512 ) ) ) )
return false ;
2004-02-15 06:19:21 +03:00
}
2004-07-06 00:19:52 +04:00
return add_text ( box , cbc , x , y ) ;
2004-06-03 01:26:12 +04:00
} else {
2004-02-15 01:26:35 +03:00
for ( c = box - > children ; c ! = 0 ; c = c - > next ) {
2004-06-03 01:26:12 +04:00
if ( c - > type ! = BOX_FLOAT_LEFT & & c - > type ! = BOX_FLOAT_RIGHT )
2004-07-06 00:19:52 +04:00
if ( ! add_box ( c , cbc , x , y ) )
2004-06-03 01:26:12 +04:00
return false ;
2004-02-15 01:26:35 +03:00
}
for ( c = box - > float_children ; c ! = 0 ; c = c - > next_float ) {
2004-07-06 00:19:52 +04:00
if ( ! add_box ( c , cbc , x , y ) )
2004-06-03 01:26:12 +04:00
return false ;
2004-02-15 01:26:35 +03:00
}
}
2004-06-03 01:26:12 +04:00
return true ;
2004-02-15 01:26:35 +03:00
}
2004-06-03 01:26:12 +04:00
2004-02-15 01:26:35 +03:00
/**
2004-07-06 00:19:52 +04:00
* Add images to the drawfile .
2004-02-15 01:26:35 +03:00
*/
2004-07-06 00:19:52 +04:00
bool add_graphic ( struct content * content , struct box * box ,
unsigned long cbc , long x , long y )
{
int sprite_length ;
2004-06-03 01:26:12 +04:00
drawfile_object * dro ;
drawfile_sprite * ds ;
/* cast-tastic... */
switch ( content - > type ) {
2004-07-06 00:19:52 +04:00
case CONTENT_JPEG :
sprite_length = ( ( osspriteop_header * ) ( ( char * ) content - > data . jpeg . sprite_area + content - > data . jpeg . sprite_area - > first ) ) - > size ;
break ;
2004-06-03 01:26:12 +04:00
# ifdef WITH_PNG
2004-07-06 00:19:52 +04:00
case CONTENT_PNG :
sprite_length = ( ( osspriteop_header * ) ( ( char * ) content - > data . png . sprite_area + content - > data . png . sprite_area - > first ) ) - > size ;
break ;
2004-06-03 01:26:12 +04:00
# endif
2004-07-06 00:19:52 +04:00
case CONTENT_GIF :
sprite_length = content - > data . gif . gif - > frame_image - > size ;
break ;
2004-06-03 01:26:12 +04:00
# ifdef WITH_SPRITE
2004-07-06 00:19:52 +04:00
case CONTENT_SPRITE :
sprite_length = ( ( osspriteop_header * ) ( ( char * ) content - > data . sprite . data + ( ( ( osspriteop_area * ) content - > data . sprite . data ) - > first ) ) ) - > size ;
break ;
2004-06-03 01:26:12 +04:00
# endif
2004-07-06 00:19:52 +04:00
default :
assert ( 0 ) ;
2004-06-03 01:26:12 +04:00
}
2004-07-06 00:19:52 +04:00
if ( ( dro = ( drawfile_object * ) drawbuf_claim ( 8 + 16 + sprite_length , DrawBuf_eBody ) ) = = NULL )
2004-06-03 01:26:12 +04:00
return false ;
dro - > type = drawfile_TYPE_SPRITE ;
dro - > size = 8 + 16 + sprite_length ;
2004-07-06 00:19:52 +04:00
ds = & dro - > data . sprite ;
2004-06-03 01:26:12 +04:00
ds - > bbox . x0 = x ;
2004-07-06 00:19:52 +04:00
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 ;
2004-06-03 01:26:12 +04:00
ds - > bbox . y1 = y ;
switch ( content - > type ) {
2004-07-06 00:19:52 +04:00
case CONTENT_JPEG :
memcpy ( ( char * ) ds + 16 , ( char * ) content - > data . jpeg . sprite_area + content - > data . jpeg . sprite_area - > first , ( unsigned ) sprite_length ) ;
break ;
2004-06-03 01:26:12 +04:00
# ifdef WITH_PNG
2004-07-06 00:19:52 +04:00
case CONTENT_PNG :
memcpy ( ( char * ) ds + 16 , ( char * ) content - > data . png . sprite_area + content - > data . png . sprite_area - > first , ( unsigned ) sprite_length ) ;
break ;
2004-06-03 01:26:12 +04:00
# endif
2004-07-06 00:19:52 +04:00
case CONTENT_GIF :
memcpy ( ( char * ) ds + 16 , ( char * ) content - > data . gif . gif - > frame_image , ( unsigned ) sprite_length ) ;
break ;
2004-06-03 01:26:12 +04:00
# ifdef WITH_SPRITE
2004-07-06 00:19:52 +04:00
case CONTENT_SPRITE :
memcpy ( ( char * ) ds + 16 , ( char * ) content - > data . sprite . data + ( ( osspriteop_area * ) content - > data . sprite . data ) - > first , ( unsigned ) sprite_length ) ;
break ;
2004-06-03 01:26:12 +04:00
# endif
2004-07-06 00:19:52 +04:00
default :
assert ( 0 ) ;
2004-06-03 01:26:12 +04:00
}
return true ;
2004-02-15 01:26:35 +03:00
}
/**
* Add a filled , borderless rectangle to the diagram
* Set bg to true to produce the background rectangle .
*/
2004-07-06 00:19:52 +04:00
bool add_rect ( struct box * box ,
unsigned long cbc , long x , long y , bool bg )
{
2004-06-03 01:26:12 +04:00
drawfile_object * dro ;
drawfile_path * dp ;
draw_path_element * dpe ;
2004-07-06 00:19:52 +04:00
if ( ( dro = ( drawfile_object * ) drawbuf_claim ( 8 + 96 , DrawBuf_eBody ) ) = = NULL )
2004-06-03 01:26:12 +04:00
return false ;
dro - > type = drawfile_TYPE_PATH ;
dro - > size = 8 + 96 ;
2004-07-06 00:19:52 +04:00
dp = & dro - > data . path ;
2004-06-03 01:26:12 +04:00
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 ;
2004-07-06 00:19:52 +04:00
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 ;
2004-06-03 01:26:12 +04:00
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 = ( draw_path_element * ) ( ( ( int * ) & dp - > path ) + 0 / sizeof ( int ) ) ;
dpe - > tag = draw_MOVE_TO ;
dpe - > reserved [ 0 ] = dpe - > reserved [ 1 ] = dpe - > reserved [ 2 ] = 0 ;
dpe - > data . move_to . x = dp - > bbox . x0 ;
dpe - > data . move_to . y = dp - > bbox . y0 ;
/* bottom right */
dpe = ( draw_path_element * ) ( ( ( int * ) & dp - > path ) + 12 / sizeof ( int ) ) ;
dpe - > tag = draw_LINE_TO ;
dpe - > reserved [ 0 ] = dpe - > reserved [ 1 ] = dpe - > reserved [ 2 ] = 0 ;
dpe - > data . line_to . x = dp - > bbox . x1 ;
dpe - > data . line_to . y = dp - > bbox . y0 ;
/* top right */
dpe = ( draw_path_element * ) ( ( ( int * ) & dp - > path ) + 24 / sizeof ( int ) ) ;
dpe - > tag = draw_LINE_TO ;
dpe - > reserved [ 0 ] = dpe - > reserved [ 1 ] = dpe - > reserved [ 2 ] = 0 ;
dpe - > data . line_to . x = dp - > bbox . x1 ;
dpe - > data . line_to . y = dp - > bbox . y1 ;
/* top left */
dpe = ( draw_path_element * ) ( ( ( int * ) & dp - > path ) + 36 / sizeof ( int ) ) ;
dpe - > tag = draw_LINE_TO ;
dpe - > reserved [ 0 ] = dpe - > reserved [ 1 ] = dpe - > reserved [ 2 ] = 0 ;
dpe - > data . line_to . x = dp - > bbox . x0 ;
dpe - > data . line_to . y = dp - > bbox . y1 ;
/* bottom left */
dpe = ( draw_path_element * ) ( ( ( int * ) & dp - > path ) + 48 / sizeof ( int ) ) ;
dpe - > tag = draw_LINE_TO ;
dpe - > reserved [ 0 ] = dpe - > reserved [ 1 ] = dpe - > reserved [ 2 ] = 0 ;
dpe - > data . line_to . x = dp - > bbox . x0 ;
dpe - > data . line_to . y = dp - > bbox . y0 ;
/* end */
dpe = ( draw_path_element * ) ( ( ( int * ) & dp - > path ) + 60 / sizeof ( int ) ) ;
dpe - > tag = draw_END_PATH ;
dpe - > reserved [ 0 ] = dpe - > reserved [ 1 ] = dpe - > reserved [ 2 ] = 0 ;
return true ;
2004-02-15 01:26:35 +03:00
}
2004-02-15 06:19:21 +03:00
2004-06-03 01:26:12 +04:00
2004-02-15 06:19:21 +03:00
/**
* add a line to the diagram
*/
2004-07-06 00:19:52 +04:00
bool add_line ( struct box * box , unsigned long cbc , long x , long y )
{
2004-06-03 01:26:12 +04:00
drawfile_object * dro ;
drawfile_path * dp ;
draw_path_element * dpe ;
2004-07-06 00:19:52 +04:00
if ( ( dro = ( drawfile_object * ) drawbuf_claim ( 8 + 60 , DrawBuf_eBody ) ) = = NULL )
2004-06-03 01:26:12 +04:00
return false ;
dro - > type = drawfile_TYPE_PATH ;
dro - > size = 8 + 60 ;
2004-07-06 00:19:52 +04:00
dp = & dro - > data . path ;
2004-06-03 01:26:12 +04:00
dp - > bbox . x0 = x ;
2004-07-06 00:19:52 +04:00
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 ;
2004-06-03 01:26:12 +04:00
dp - > bbox . y1 = y ;
dp - > fill = cbc ;
dp - > outline = cbc ;
dp - > width = 0 ;
dp - > style . flags = 0 ;
dp - > style . reserved = 0 ;
dp - > style . cap_width = 0 ;
dp - > style . cap_length = 0 ;
/* left end */
dpe = ( draw_path_element * ) ( ( ( int * ) & dp - > path ) + 0 / sizeof ( int ) ) ;
dpe - > tag = draw_MOVE_TO ;
dpe - > reserved [ 0 ] = dpe - > reserved [ 1 ] = dpe - > reserved [ 2 ] = 0 ;
dpe - > data . move_to . x = dp - > bbox . x0 ;
dpe - > data . move_to . y = dp - > bbox . y0 ;
/* right end */
dpe = ( draw_path_element * ) ( ( ( int * ) & dp - > path ) + 12 / sizeof ( int ) ) ;
dpe - > tag = draw_LINE_TO ;
dpe - > reserved [ 0 ] = dpe - > reserved [ 1 ] = dpe - > reserved [ 2 ] = 0 ;
dpe - > data . line_to . x = dp - > bbox . x1 ;
dpe - > data . line_to . y = dp - > bbox . y0 ;
/* end */
dpe = ( draw_path_element * ) ( ( ( int * ) & dp - > path ) + 24 / sizeof ( int ) ) ;
dpe - > tag = draw_END_PATH ;
dpe - > reserved [ 0 ] = dpe - > reserved [ 1 ] = dpe - > reserved [ 2 ] = 0 ;
return true ;
2004-02-15 06:19:21 +03:00
}
2004-02-15 17:17:29 +03:00
2004-06-03 01:26:12 +04:00
2004-02-15 17:17:29 +03:00
/**
* add a circle to the diagram .
*/
2004-07-06 00:19:52 +04:00
bool add_circle ( struct box * box , unsigned long cbc , long x , long y )
{
double radius , kappa ;
2004-06-03 01:26:12 +04:00
double cx , cy ;
drawfile_object * dro ;
drawfile_path * dp ;
draw_path_element * dpe ;
2004-07-06 00:19:52 +04:00
if ( ( dro = ( drawfile_object * ) drawbuf_claim ( 8 + 160 , DrawBuf_eBody ) ) = = NULL )
2004-06-03 01:26:12 +04:00
return false ;
dro - > type = drawfile_TYPE_PATH ;
dro - > size = 8 + 160 ;
2004-07-06 00:19:52 +04:00
dp = & dro - > data . path ;
2004-06-03 01:26:12 +04:00
dp - > bbox . x0 = x ;
2004-07-06 00:19:52 +04:00
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 ;
2004-06-03 01:26:12 +04:00
dp - > bbox . y1 = y ;
2004-07-06 00:19:52 +04:00
cx = ( dp - > bbox . x1 - dp - > bbox . x0 ) / 2. ;
cy = ( dp - > bbox . y1 - dp - > bbox . y0 ) / 2. ;
if ( cx = = cy )
radius = cx ; /* box is square */
2004-06-03 01:26:12 +04:00
else if ( cx > cy ) {
radius = cy ;
2004-07-06 00:19:52 +04:00
dp - > bbox . x1 - = cx - cy ; /* reduce box width */
2004-06-03 01:26:12 +04:00
}
else if ( cy > cx ) {
radius = cx ;
2004-07-06 00:19:52 +04:00
dp - > bbox . y0 + = cy - cx ; /* reduce box height */
2004-06-03 01:26:12 +04:00
}
2004-07-06 00:19:52 +04:00
kappa = radius * 4. * ( sqrt ( 2. ) - 1. ) / 3. ; /* ~= 0.5522847498 */
2004-06-03 01:26:12 +04:00
dp - > fill = cbc ;
dp - > outline = cbc ;
dp - > width = 0 ;
dp - > style . flags = drawfile_PATH_ROUND ;
/*
2004-07-06 00:19:52 +04:00
* Z b Y
2004-06-03 01:26:12 +04:00
*
2004-07-06 00:19:52 +04:00
* a X c
2004-06-03 01:26:12 +04:00
*
2004-07-06 00:19:52 +04:00
* V d W
2004-06-03 01:26:12 +04:00
*
* V = ( x0 , y0 )
* W = ( x1 , y0 )
* Y = ( x1 , y1 )
* Z = ( x0 , y1 )
*
* X = centre of circle ( x0 + cx , y0 + cx )
*
* The points a , b , c , d are where the circle intersects
* the bounding box . at these points , the bounding box is
* tangental to the circle .
*/
/* start at a */
dpe = ( draw_path_element * ) ( ( ( int * ) & dp - > path ) + 0 / sizeof ( int ) ) ;
dpe - > tag = draw_MOVE_TO ;
dpe - > reserved [ 0 ] = dpe - > reserved [ 1 ] = dpe - > reserved [ 2 ] = 0 ;
dpe - > data . move_to . x = ( dp - > bbox . x0 + cx ) - radius ;
dpe - > data . move_to . y = ( dp - > bbox . y0 + cy ) ;
/* point1->point2 : (point1)(ctrl1)(ctrl2)(point2) */
/* a->b : (x-r, y)(x-r, y+k)(x-k, y+r)(x, y+r) */
dpe = ( draw_path_element * ) ( ( ( int * ) & dp - > path ) + 12 / sizeof ( int ) ) ;
dpe - > tag = draw_BEZIER_TO ;
dpe - > reserved [ 0 ] = dpe - > reserved [ 1 ] = dpe - > reserved [ 2 ] = 0 ;
dpe - > data . bezier_to [ 0 ] . x = ( dp - > bbox . x0 + cx ) - radius ;
dpe - > data . bezier_to [ 0 ] . y = ( dp - > bbox . y0 + cy ) + kappa ;
dpe - > data . bezier_to [ 1 ] . x = ( dp - > bbox . x0 + cx ) - kappa ;
dpe - > data . bezier_to [ 1 ] . y = ( dp - > bbox . y0 + cy ) + radius ;
dpe - > data . bezier_to [ 2 ] . x = ( dp - > bbox . x0 + cx ) ;
dpe - > data . bezier_to [ 2 ] . y = ( dp - > bbox . y0 + cy ) + radius ;
/* b->c : (x, y+r)(x+k, y+r)(x+r, y+k)(x+r, y)*/
dpe = ( draw_path_element * ) ( ( ( int * ) & dp - > path ) + 40 / sizeof ( int ) ) ;
dpe - > tag = draw_BEZIER_TO ;
dpe - > reserved [ 0 ] = dpe - > reserved [ 1 ] = dpe - > reserved [ 2 ] = 0 ;
dpe - > data . bezier_to [ 0 ] . x = ( dp - > bbox . x0 + cx ) + kappa ;
dpe - > data . bezier_to [ 0 ] . y = ( dp - > bbox . y0 + cy ) + radius ;
dpe - > data . bezier_to [ 1 ] . x = ( dp - > bbox . x0 + cx ) + radius ;
dpe - > data . bezier_to [ 1 ] . y = ( dp - > bbox . y0 + cy ) + kappa ;
dpe - > data . bezier_to [ 2 ] . x = ( dp - > bbox . x0 + cx ) + radius ;
dpe - > data . bezier_to [ 2 ] . y = ( dp - > bbox . y0 + cy ) ;
/* c->d : (x+r, y)(x+r, y-k)(x+k, y-r)(x, y-r) */
dpe = ( draw_path_element * ) ( ( ( int * ) & dp - > path ) + 68 / sizeof ( int ) ) ;
dpe - > tag = draw_BEZIER_TO ;
dpe - > reserved [ 0 ] = dpe - > reserved [ 1 ] = dpe - > reserved [ 2 ] = 0 ;
dpe - > data . bezier_to [ 0 ] . x = ( dp - > bbox . x0 + cx ) + radius ;
dpe - > data . bezier_to [ 0 ] . y = ( dp - > bbox . y0 + cy ) - kappa ;
dpe - > data . bezier_to [ 1 ] . x = ( dp - > bbox . x0 + cx ) + kappa ;
dpe - > data . bezier_to [ 1 ] . y = ( dp - > bbox . y0 + cy ) - radius ;
dpe - > data . bezier_to [ 2 ] . x = ( dp - > bbox . x0 + cx ) ;
dpe - > data . bezier_to [ 2 ] . y = ( dp - > bbox . y0 + cy ) - radius ;
/* d->a : (x, y-r)(x-k, y-r)(x-r, y-k)(x-r, y)*/
dpe = ( draw_path_element * ) ( ( ( int * ) & dp - > path ) + 96 / sizeof ( int ) ) ;
dpe - > tag = draw_BEZIER_TO ;
dpe - > reserved [ 0 ] = dpe - > reserved [ 1 ] = dpe - > reserved [ 2 ] = 0 ;
dpe - > data . bezier_to [ 0 ] . x = ( dp - > bbox . x0 + cx ) - kappa ;
dpe - > data . bezier_to [ 0 ] . y = ( dp - > bbox . y0 + cy ) - radius ;
dpe - > data . bezier_to [ 1 ] . x = ( dp - > bbox . x0 + cx ) - radius ;
dpe - > data . bezier_to [ 1 ] . y = ( dp - > bbox . y0 + cy ) - kappa ;
dpe - > data . bezier_to [ 2 ] . x = ( dp - > bbox . x0 + cx ) - radius ;
dpe - > data . bezier_to [ 2 ] . y = ( dp - > bbox . y0 + cy ) ;
/* end */
dpe = ( draw_path_element * ) ( ( ( int * ) & dp - > path ) + 124 / sizeof ( int ) ) ;
dpe - > tag = draw_END_PATH ;
dpe - > reserved [ 0 ] = dpe - > reserved [ 1 ] = dpe - > reserved [ 2 ] = 0 ;
return true ;
2004-02-15 17:17:29 +03:00
}
2004-06-03 01:26:12 +04:00
2004-07-06 00:19:52 +04:00
/**
* Add the text line to the diagram .
*/
static bool add_text ( struct box * box , unsigned long cbc , long x , long y )
{
const char * txt = box - > text ;
size_t txt_len = box - > length ;
while ( txt_len ! = 0 ) {
unsigned int width , rolength , consumed ;
const char * rofontname , * rotext ;
byte fontIndex ;
drawfile_object * dro ;
drawfile_text * dt ;
nsfont_txtenum ( box - > font , txt , txt_len ,
& width ,
& rofontname ,
& rotext ,
& rolength ,
& consumed ) ;
LOG ( ( " txtenum <%.*s> (%d bytes), returned width %d, font name <%s>, RISC OS text <%.*s>, consumed %d \n " , txt_len , txt , txt_len , width , rofontname , rolength , rotext , consumed ) ) ;
/* Error happened ? */
if ( rotext = = NULL )
return false ;
if ( ! drawbuf_add_font ( rofontname , & fontIndex ) )
return false ;
if ( ( dro = ( drawfile_object * ) drawbuf_claim ( 8 + 44 + ( ( rolength + 1 + 3 ) & - 4 ) , DrawBuf_eBody ) ) = = NULL )
return false ;
dro - > type = drawfile_TYPE_TEXT ;
dro - > size = 8 + 44 + ( ( rolength + 1 + 3 ) & - 4 ) ;
dt = & dro - > data . text ;
dt - > bbox . x0 = x ;
dt - > bbox . y0 = y - box - > height * 1.5 * 512 ;
dt - > bbox . x1 = x + width * 512 ;
dt - > bbox . y1 = y ;
dt - > fill = box - > style - > color < < 8 ;
dt - > bg_hint = cbc < < 8 ;
dt - > style . font_index = fontIndex ;
dt - > style . reserved [ 0 ] = 0 ;
dt - > style . reserved [ 1 ] = 0 ;
dt - > style . reserved [ 2 ] = 0 ;
dt - > xsize = box - > font - > size * 40 ;
dt - > ysize = box - > font - > size * 40 ;
dt - > base . x = x ;
dt - > base . y = y - box - > height * 512 + 1536 ;
strncpy ( dt - > text , rotext , rolength ) ;
dt - > text [ rolength ] = 0 ;
for ( + + rolength ; rolength % 4 ; + + rolength )
dt - > text [ rolength ] = 0 ;
free ( rotext ) ;
/* Go to next chunk : */
x + = width * 512 ;
txt + = consumed ;
txt_len - = consumed ;
}
return true ;
}
2004-02-15 01:26:35 +03:00
# endif