/* Copyright 1996 Acorn Computers Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /**************************************************************************** * This source file was written by Acorn Computers Limited. It is part of * * the "DrawFile" library for rendering RISCOS Draw files from applications * * in C. It may be used freely in the creation of programs for Archimedes. * * It should be used with Acorn's C Compiler Release 2 or later. * * * * No support can be given to programmers using this code and, while we * * believe that it is correct, no correspondence can be entered into * * concerning behaviour or bugs. * * * * Upgrades of this code may or may not appear, and while every effort will * * be made to keep such upgrades upwards compatible, no guarantees can be * * given. * ***************************************************************************/ /* -> c.DrawFiles * * DrawFile module, internal code * History: * Version 0.1: 15 Feb 89, DAHE: created * 13 May 91, ECN: Use SWI names instead of numbers * Stack checking off on selected functions * * This file consists of code taken from the !Draw version of files c.draw * and c.drawDispl for use in the DrawFile module (release 0.2). * */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include "h.os" #include "h.bbc" #include "h.sprite" #include "h.font" #include "h.swis" #define scalefactor dr_scalefactor /* Name equivalence */ #include "h.DrawIntern.drawfile1" #include "h.drawfdiag" #include "h.DrawIntern.drawfile2" /*=========================================================================*/ /* Code from c.draw */ /* The following are needed to shut the preprocessor up */ /* Return the address of the first path element in a path object */ /* this starts either after the path header (no dash pattern) */ /* or after the dash pattern */ path_movestr *address_pathstart(draw_objptr hdrptr) { if (hdrptr.pathp->pathstyle.joincapwind & packmask_dashed) return (path_movestr*) &(hdrptr.pathp->data.dashelements[hdrptr.pathp->data.dashcount]); else return (path_movestr*)&hdrptr.pathp->data; } /* Return the address of the dash pattern of a path object */ /* or zero */ draw_dashstr *address_dashstart(draw_objptr hdrptr) { if (hdrptr.pathp->pathstyle.joincapwind & packmask_dashed) return &hdrptr.pathp->data; else return 0; } /*=========================================================================*/ /* Code from c.drawDispl */ #define visible(A) ((A.objhdrp->bbox.x0<=clip_x1) && \ (A.objhdrp->bbox.y0<=clip_y1) && \ (A.objhdrp->bbox.x1>=clip_x0) && \ (A.objhdrp->bbox.y1>=clip_y0) \ ) /* ScaleT - for text position coords ('font_paint' takes graphics coords) */ /* ScaleS - for sprite position coords ('put_sprite takes graphics coords) */ /* ScaleF - T.B.A */ #define scaleT(A,B) (((A)+ (int)(scalefactor*(double)(B)) ) >> 8) #define scaleS(A,B) (((A)+ (int)(scalefactor*(double)(B)) ) >> 8) #define scaleF(A) ( (int)(scalefactor*(double)(A)/40) ) #pragma -s1 /* GCol(action,colour) where colour is BBGGRRxx (foreground colour) */ static os_error *displ_settruecol(int action,draw_coltyp colour) { os_regset r; r.r[0] = colour; /* BBGGRRxx */ r.r[3] = 0; /* foreground */ r.r[4] = action; /* GCol action */ return(os_swix(ColourTrans_SetGCOL, &r)) ; } static os_error *displ_settruefontcol(font fonth, draw_coltyp foregrd, draw_coltyp backgrd ) { os_regset r; r.r[0] = (int)fonth; r.r[1] = backgrd; /* background BBGGRRxx (usually white) */ r.r[2] = foregrd; /* foreground BBGGRRxx */ r.r[3] = 14; /* max offset (magic number) */ return(os_swix(0x4074F/*ColourTrans_SetFontColour*/, &r)) ; } #pragma -s0 /* ------------------------------------------------------------------------- */ double scalefactor; os_error *do_objpath(draw_objptr, int,int); os_error *do_objsprite(draw_objptr hdrptr, int orgx,int orgy); os_error *do_objtext(draw_objptr hdrptr, int orgx,int orgy); /* Font catalogue - type defined in drawMenu */ static fontcatstr *fontcat; static BOOL fontcatseen; /* Record font catalogue */ void note_fontcat(draw_objptr hdrptr) { int ptr = sizeof(draw_fontliststrhdr); int fontNum; int size = hdrptr.fontlistp->size; /* malloc fontcat to save static space for shared library */ if (fontcat == 0) fontcat = (fontcatstr *)malloc(sizeof(fontcatstr)); if (hdrptr.bytep == 0) { fontcatseen = FALSE; return; } fontcat->list_size = 0; while (ptr < size) { if ((fontNum = (int)hdrptr.bytep[ptr++]) == 0) break; fontcat->name[fontNum] = hdrptr.bytep + ptr; ptr += strlen(fontcat->name[fontNum]) + 1; if (fontNum > fontcat->list_size) fontcat->list_size = fontNum; } fontcat->menu_size = fontcat->list_size; fontcatseen = TRUE; } /* ------------------------------------------------------------------- */ /* */ /* Draw the object 'hdrptr-> ' whose origin is (orgx,orgy) */ /* */ /* The object is: */ /* a PATH */ /* a line of TEXT */ /* a GROUPing of objects */ /* */ /* (orgx,orgy) takes into acount window and scroll bar positions. */ /* (orgx,orgy) & clip(x0,y0,x1,y1) are in dBase coordinates. */ /* */ /* This version is modified from the one in c.drawDispl, to use a */ /* different sort of error block, and to call the unknown object */ /* handler if it has been defined. -> TRUE if no error */ /* */ /* ------------------------------------------------------------------- */ BOOL do_objects(draw_objptr hdrptr,draw_objptr limit, int orgx,int orgy, int clip_x0,int clip_y0,int clip_x1,int clip_y1, draw_error *err) { os_error *oserr = 0; BOOL ok = TRUE; for ( ; ok && hdrptr.bytep < limit.bytep; hdrptr.bytep += hdrptr.objhdrp->size) { switch (hdrptr.objhdrp->tag) { case draw_OBJTEXT: if (visible(hdrptr)) oserr = do_objtext(hdrptr, orgx,orgy); break; case draw_OBJPATH: if (visible(hdrptr)) oserr = do_objpath(hdrptr, orgx,orgy); break; case draw_OBJSPRITE: if (visible(hdrptr)) oserr = do_objsprite(hdrptr, orgx,orgy); break; case draw_OBJGROUP: if (visible(hdrptr)) { draw_objptr objptr,objlim; objptr.bytep = hdrptr.bytep + sizeof(draw_groustr); objlim.bytep = hdrptr.bytep + hdrptr.objhdrp->size; /* Render the objects in the group */ ok = do_objects(objptr,objlim, orgx,orgy, clip_x0,clip_y0, clip_x1,clip_y1, err); } break; case draw_OBJTAGG: if (visible(hdrptr)) { draw_objptr objptr,objlim; objptr.bytep = hdrptr.bytep + sizeof(draw_taggstrhdr); objlim.bytep = objptr.bytep + objptr.objhdrp->size; /* Render the (one) object within the tagged object */ ok = do_objects(objptr,objlim, orgx,orgy, clip_x0,clip_y0, clip_x1,clip_y1, err); } break; case draw_OBJTEXTCOL: { draw_bboxtyp clipBox; clipBox.x0 = clip_x0; clipBox.y0 = clip_y0; clipBox.x1 = clip_x1; clipBox.y1 = clip_y1; if (visible(hdrptr)) oserr = do_objtextcol(hdrptr, orgx, orgy, &clipBox); break; } case draw_OBJTEXTAREA: { draw_bboxtyp clipBox; clipBox.x0 = clip_x0; clipBox.y0 = clip_y0; clipBox.x1 = clip_x1; clipBox.y1 = clip_y1; if (visible(hdrptr)) oserr = do_objtextarea(hdrptr, orgx, orgy, &clipBox); break; } case draw_OBJFONTLIST: note_fontcat(hdrptr); break; default: /* Call unknown object handler, if there is one */ if (visible(hdrptr) && dr_unknown_handler != NULL) ok = dr_unknown_handler((void*)hdrptr.bytep, dr_unknown_handle, err); break; } if (oserr) { DrawFile_OSError(err, *oserr); ok = FALSE; break; } } return(ok); } /* ------------------------------------------------------------------- */ /* Fill and/or outline a path */ static void displ_unpackpathstyle(draw_objptr hdrptr, draw_jointspec *jspecp) { int joincapwind = hdrptr.pathp->pathstyle.joincapwind; jspecp->join = (joincapwind & packmask_join); jspecp->endcap = (joincapwind & packmask_endcap) >> packshft_endcap; jspecp->startcap = (joincapwind & packmask_startcap) >> packshft_startcap; jspecp->reserved = 0; jspecp->mitrelimit = 0xA0000; /* Mitre limit=10.0 (post script default) */ jspecp->endtricapwid = jspecp->starttricapwid = (hdrptr.pathp->pathstyle.tricapwid << 4); jspecp->endtricaphei = jspecp->starttricaphei = (hdrptr.pathp->pathstyle.tricaphei << 4); } os_error *do_objpath(draw_objptr objhdr, int orgx, int orgy) { os_error *err = 0; os_regset r; draw_coltyp fillcol = objhdr.pathp->fillcolour; /* BBGGRRxx / 0xFFFFFFFF */ draw_coltyp linecol = objhdr.pathp->pathcolour; int linewid = objhdr.pathp->pathwidth; int joincapwind = objhdr.pathp->pathstyle.joincapwind; int matrix[6]; matrix[0] = matrix[3] = (int) (scalefactor*65536); matrix[1] = matrix[2] = 0; matrix[4] = orgx; matrix[5] = orgy; if (fillcol != TRANSPARENT) { /* fill the path */ err = displ_settruecol(0,fillcol); if (err) return(err); r.r[0] = (int)address_pathstart(objhdr); /*&(objhdr.pathp->path);*/ r.r[1] = 0x30 | ((joincapwind & packmask_windrule) >> 5); /*winding rule*/ r.r[2] = (int)&matrix[0]; /* transformation matrix */ r.r[3] = (int)(200/scalefactor); /* flatness */ err = os_swix(Draw_Fill, &r); if (err) return(err); } if (linecol != TRANSPARENT) { /* stroke the outline */ draw_jointspec jointspec; err = displ_settruecol(0,linecol); if (err) return(err); displ_unpackpathstyle(objhdr, &jointspec); r.r[0] = (int)address_pathstart(objhdr); /*&(objhdr.pathp->path);*/ r.r[1] = 0x38; /* fill (BBC) style */ r.r[2] = (int)&matrix[0]; /* transformation matrix */ r.r[3] = (int)(200/scalefactor); /* flatness */ r.r[4] = linewid; /* line thickness */ r.r[5] = (int)&jointspec; /* line cap & join spec. */ r.r[6] = (int)address_dashstart(objhdr); /* dash pattern */ err = os_swix(Draw_Stroke, &r); if (err) return(err); } return(0); } /* ------------------------------------------------------------------- */ /* Set size & spacing of VDU5 characters, units are pixels */ os_error *displ_setVDU5charsize(int xsize,int ysize, int xspace,int yspace) { os_error *e; currentmode.gcharaltered = 1; /* so we restore before next pollwimp */ e = bbc_vduq(23,17,7,2,xsize,xsize>>8,ysize,ysize>>8,0,0); if (!e) bbc_vduq(23,17,7,4,xspace,xspace>>8,yspace,yspace>>8,0,0); return(e); } /* Draw a line of text */ /* If the font can't be found (ie 'font disc not present' or font name */ /* came from a fontlist object), use the system font. This seems kinder */ /* than aborting, or poping up an error box. */ /* Any other errors are passed back. */ os_error *do_objtext(draw_objptr hdrptr, int orgx,int orgy) { os_error *err = 0; int textcol = hdrptr.textp->textcolour; int backgrd = hdrptr.textp->background; /* a hint (kludge) to font munger */ if (textcol == TRANSPARENT) return(0); /* nothing to plot */ if (fontcatseen && hdrptr.textp->textstyle.fontref) { font fonth; err = font_find(fontcat->name[hdrptr.textp->textstyle.fontref], scaleF(hdrptr.textp->fsizex), scaleF(hdrptr.textp->fsizey), 0,0, &fonth ); if (!err) { err = font_setfont(fonth); if (!err) { err = displ_settruefontcol(fonth,textcol,backgrd); if (!err) err = font_paint(&hdrptr.textp->text[0], font_OSCOORDS | font_ABS, scaleT(orgx, hdrptr.textp->coord.x), scaleT(orgy, hdrptr.textp->coord.y) ); } (void) font_lose(fonth); return(err); } } /* either system font specified, or fancy font could not be found */ /* so render in the system font (ie scaled VDU5 characters) */ { int xsize = (int)((scalefactor * hdrptr.textp->fsizex) / currentmode.pixsizex); int ysize = (int)((scalefactor * hdrptr.textp->fsizey) / currentmode.pixsizey); /* xsize,ysize in pixels. pixsizex,pixsizey in dBase coords per pixel */ err = displ_settruecol(0,textcol); if (err) return(err); /* assume char base line is row 7 (of 8) */ err = bbc_move(scaleT(orgx, hdrptr.textp->coord.x), scaleT(orgy, hdrptr.textp->coord.y + 7*(int)hdrptr.textp->fsizey/8) ); if (err) return(err); err = displ_setVDU5charsize(xsize,ysize, xsize,ysize); if (err) return(err); err = bbc_stringprint(&hdrptr.textp->text[0]); } return(err); } /********************************************* * Call the SWI to build a translation table * *********************************************/ #pragma -s1 static os_error *selecttable(int sourcemode, int *sourcepal, int destmode, int *destpal, char *transtab) { os_regset regs ; regs.r[0] = sourcemode ; regs.r[1] = (int) sourcepal ; regs.r[2] = destmode ; regs.r[3] = (int) destpal ; regs.r[4] = (int) transtab ; return (os_swix(ColourTrans_SelectTable, ®s)); } #pragma -s0 /* plot a sprite */ os_error *do_objsprite(draw_objptr hdrptr, int orgx,int orgy) { os_error *err = 0; sprite_id id; sprite_factors factors; int palentries; int *sourcepal; /* Points to paltab OR =0 (no palette) */ int paltab[256]; /* for 1st flash colours in sprite */ char pixtrans[256]; /* pixel conversion tab */ id.tag = sprite_id_addr; id.s.addr = &hdrptr.spritep->sprite; palentries = (hdrptr.spritep->sprite.image - sizeof(sprite_header))/8; if ((palentries > 256) || (palentries < 0)) palentries = 0; if (palentries == 0) sourcepal = 0; /* no palette, use default for sprite.mode */ else { int *from = hdrptr.spritep->palette; /* sprites palette entries */ int *to = paltab; /* have 1st & 2nd flash colours */ int i; /* extract ONLY 1st flash colour */ for (i=palentries; i>0; i--) { *to++ = *from; from += 2; } sourcepal = paltab; /* use sprite palette */ } err = selecttable(hdrptr.spritep->sprite.mode, /* srce mode = sprite mode */ sourcepal, /* srce pal = sprite/default pal */ -1, /* dest mode = current mode */ (int*)-1, /* dest pal = current pal */ &pixtrans[0] ); if (err) return(err); { sprite_id id; sprite_info info ; id.tag = sprite_id_addr; id.s.addr = &hdrptr.spritep->sprite; (void)sprite_readsize((sprite_area*)0xFF, /* this op needs no spArea */ &id, /* pass address of sprite */ &info /* result block */ ); factors.xmag = (int)((hdrptr.spritep->bbox.x1 - hdrptr.spritep->bbox.x0) * scalefactor ); factors.xdiv = currentmode.pixsizex * info.width; factors.ymag = (int)((hdrptr.spritep->bbox.y1 - hdrptr.spritep->bbox.y0) * scalefactor ); factors.ydiv = currentmode.pixsizey * info.height; } err = sprite_put_scaled((sprite_area*)0xFF, /* this op needs no spArea */ &id, /* pass address of sprite */ 8, /* GcolAction=STORE thro mask */ scaleS(orgx, hdrptr.spritep->bbox.x0), scaleS(orgy, hdrptr.spritep->bbox.y0), &factors, (sprite_pixtrans*)&pixtrans[0] ); return(err); } extern BOOL drawfiles_init(void); BOOL drawfiles_init(void) { return ((fontcat = malloc(sizeof(fontcatstr))) != 0); }