home *** CD-ROM | disk | FTP | other *** search
- /*
- ** dispatch.c - dispatcher for Font DataType class
- ** Copyright © 1995 Michael Letowski
- */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <dos/dos.h>
- #include <dos/rdargs.h>
- #include <graphics/displayinfo.h>
- #include <graphics/gfx.h>
- #include <graphics/modeid.h>
- #include <graphics/rastport.h>
- #include <graphics/text.h>
- #include <intuition/classes.h>
- #include <datatypes/datatypesclass.h>
- #include <datatypes/pictureclass.h>
- #include <diskfont/diskfont.h>
- #include <datatypes/datatypes.h>
- #include <diskfont/diskfonttag.h>
- #include <utility/hooks.h>
- #include <utility/tagitem.h>
- #include <support/types.h>
- #include <support/graphics.h>
-
- #include <stdlib.h>
-
- #include <proto/dos.h>
- #include <proto/exec.h>
- #include <proto/diskfont.h>
- #include <proto/datatypes.h>
- #include <proto/graphics.h>
- #include <proto/intuition.h>
- #include <proto/utility.h>
- #include <clib/support_protos.h>
-
- #include "classbase.h"
- #include "dispatch.h"
- #include "prefs.h"
- #include "otag.h"
-
- #define IDS_CNT 4
-
- #define COL_WHITE 0xFF
- #define COL_BLACK 0x00
-
- #define DEF_XDPI 72
- #define DEF_YDPI 80
-
- /* 256 for ASCII set, 2 for terminator */
- #define MAX_CHAR (256+2)
- /* 32 chars for font name, 6 for size, 2 for terminator */
- #define MAX_CHAR2 (32+6+2)
- /* Total number of strings */
- #define MAX_STRING 32
-
- /* Get font's name */
- #define FontName(f) ((f)->tf_Message.mn_Node.ln_Name)
-
- typedef int (SFUNC)(void const*, void const *);
-
- STATIC ASM Object *Dispatch(R_A0 Class *cl, R_A2 Object *o, R_A1 Msg msg);
- STATIC LBOOL GetFont(struct ClassBase *cb, Object *o, struct TagItem *attrs);
-
- /* Font management */
- STATIC struct TextFont **OpenFonts(struct ClassBase *cb, struct Opts *opts,
- struct FontContentsHeader *fch, STRPTR name);
- STATIC VOID CloseFonts(struct ClassBase *cb, struct TextFont **f, ULONG cnt);
- /* Rendering */
- STATIC LBOOL GetWH(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
- struct TextFont *f, ULONG *w, ULONG *h);
- STATIC LBOOL Render(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
- struct TextFont **f, ULONG cnt, ULONG w);
- STATIC STRPTR *PrepStrings(struct ClassBase *cb, struct Opts *opt,
- struct TextFont *f, ULONG *cnt);
- STATIC LONG SortFunc(struct TextFont **tf1, struct TextFont **tf2);
-
- /* DataTypes stubs */
- STATIC ULONG LocSetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...);
- STATIC ULONG LocGetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...);
-
- Class *InitClass(struct ClassBase *cb)
- {
- Class *CL;
-
- /* Create our class (no instance) */
- if(CL=MakeClass(FONTDTCLASS,PICTUREDTCLASS,NULL,NULL,0))
- {
- CL->cl_Dispatcher.h_Entry=(HOOKFUNC)Dispatch;
- CL->cl_UserData=(ULONG)cb;
- AddClass(CL);
- }
- return(CL);
- } /* InitClass */
-
- STATIC ASM Object *Dispatch(R_A0 Class *cl, R_A2 Object *o, R_A1 Msg msg)
- {
- struct ClassBase *cb=(struct ClassBase *)cl->cl_UserData;
- Object *Obj;
-
- switch(msg->MethodID)
- {
- case OM_NEW: /* We know this method */
- if(Obj=(Object *)DoSuperMethodA(cl,o,msg))
- unless(GetFont(cb,Obj,((struct opSet *)msg)->ops_AttrList))
- {
- CoerceMethod(cl,Obj,OM_DISPOSE);
- return(NULL);
- }
- break;
- default: /* Let the superclass handle it */
- Obj=(Object *)DoSuperMethodA(cl,o,msg);
- break;
- }
- return(Obj);
- }
-
- STATIC LBOOL GetFont(struct ClassBase *cb, Object *o, struct TagItem *attrs)
- {
- STATIC CONST ULONG SourceIDs[IDS_CNT]= /* Font flag->mode selector */
- {
- LORES_KEY,HIRES_KEY,LORESLACE_KEY,HIRESLACE_KEY
- }; /* ModeIDs */
-
- struct RastPort RP;
- struct Opts Opts;
- struct BitMapHeader *BMHD=NULL;
- struct ColorRegister *CMap=NULL;
- LONG *CRegs=NULL;
- struct FileInfoBlock *FIB;
- struct FontContentsHeader *FCH;
- struct TextFont **Fonts,*F;
- struct ColorTextFont *CF;
- struct ColorFontColors *CFC;
- struct PrefsHandle *PH;
-
- STRPTR Name=NULL,Title; /* Font file name & picture title */
- BPTR DirLock,FH=0;
- ULONG TallWide,ModeID;
- ULONG Width,Height,Depth,NumColors;
- ULONG I,J,NumFonts;
- UBYTE ForeRed,ForeGrn,ForeBlu,BackRed,BackGrn,BackBlu;
- LBOOL Result=FALSE;
-
- /* Read preferences */
- PH=GetFontPrefs(cb,&Opts);
-
- /* Get default title */
- Title=(STRPTR)GetTagData(DTA_Name,NULL,attrs);
-
- /* Get file handle and BitMapHeader */
- LocGetDTAttrs(cb,o,DTA_Handle,&FH,PDTA_BitMapHeader,&BMHD,TAG_DONE);
- try(FH && BMHD, EXIT);
-
- /* Get font file name */
- try(FIB=AllocDosObject(DOS_FIB,NULL), NO_FIB);/* Create FileInfoBlock */
- if(ExamineFH(FH,FIB)) /* Examine it */
- Name=FIB->fib_FileName; /* Get name pointer */
- unless(Name) /* Still no name */
- if(Title) /* Use title to get name */
- Name=FilePart(Title); /* Get file part of title */
- try(Name, NO_NAME);
-
- /* Get font */
- try(DirLock=ParentOfFH(FH), NO_LOCK);
- try(FCH=NewFC(cb,DirLock,Name), NO_FCH);
- try(Fonts=OpenFonts(cb,&Opts,FCH,Name), NO_FONTS);
- NumFonts=FCH->fch_NumEntries;
-
- /* Set colours */
- ForeRed=ForeGrn=ForeBlu=COL_BLACK;
- if(Opts.opt_ForeRed) ForeRed=clamp(*Opts.opt_ForeRed,0,255);
- if(Opts.opt_ForeGrn) ForeGrn=clamp(*Opts.opt_ForeGrn,0,255);
- if(Opts.opt_ForeBlu) ForeBlu=clamp(*Opts.opt_ForeBlu,0,255);
- BackRed=BackGrn=BackBlu=COL_WHITE;
- if(Opts.opt_BackRed) BackRed=clamp(*Opts.opt_BackRed,0,255);
- if(Opts.opt_BackGrn) BackGrn=clamp(*Opts.opt_BackGrn,0,255);
- if(Opts.opt_BackBlu) BackBlu=clamp(*Opts.opt_BackBlu,0,255);
-
- /* Calculate sizes */
- TallWide=0;
- Width=Height=0;
- Depth=1;
- InitRastPort(&RP); /* Set up RastPort - here! */
- for(I=0; I<NumFonts; I++)
- if(F=Fonts[I]) /* Opened successfully */
- {
- try(GetWH(cb,&RP,&Opts,F,&Width,&Height), ERROR);
- if(ftst(F->tf_Style,FSF_COLORFONT)) /* This is ColorFont */
- {
- CF=(struct ColorTextFont *)F;
- if(CF->ctf_Depth>Depth) /* Deeper? */
- Depth=CF->ctf_Depth; /* Set new depth */
- }
- TallWide=(F->tf_Flags & (FPF_TALLDOT | FPF_WIDEDOT))>>FPB_TALLDOT;
- }
-
- /* Set up BitMap header */
- BMHD->bmh_Width=Width; /* Fill in informations */
- BMHD->bmh_Height=Height;
- BMHD->bmh_Depth=Depth;
- NumColors=1<<Depth;
-
- /* Get display mode id */
- ModeID=BestModeID(BIDTAG_DesiredWidth, Width,
- BIDTAG_DesiredHeight, Height,
- BIDTAG_Depth, Depth,
- BIDTAG_SourceID, SourceIDs[TallWide & (IDS_CNT-1)],
- TAG_DONE);
-
- /* Set colors */
- LocSetDTAttrs(cb,o,PDTA_NumColors,NumColors,TAG_DONE);
- LocGetDTAttrs(cb,o,PDTA_ColorRegisters,&CMap,PDTA_CRegs,&CRegs,TAG_DONE);
- try(CMap && CRegs, ERROR);
- if(Depth==1) /* B&W font */
- {
- if(Opts.opt_Inverse)
- {
- swap(ForeRed,BackRed);
- swap(ForeGrn,BackGrn);
- swap(ForeBlu,BackBlu);
- }
- CMap[0].red=BackRed; CMap[0].green=BackGrn; CMap[0].blue=BackBlu;
- CMap[1].red=ForeRed; CMap[1].green=ForeGrn; CMap[1].blue=ForeBlu;
- CRegs[0]=Color32(BackRed); CRegs[3]=Color32(ForeRed);
- CRegs[1]=Color32(BackGrn); CRegs[4]=Color32(ForeGrn);
- CRegs[2]=Color32(BackBlu); CRegs[5]=Color32(ForeBlu);
- }
- else /* Some color fonts */
- for(I=0; I<NumFonts; I++)
- if(F=Fonts[I])
- if(ftst(F->tf_Style,FSF_COLORFONT))
- {
- CF=(struct ColorTextFont *)F;
- if(CFC=CF->ctf_ColorFontColors) /* Color map exists */
- for(J=0; J<CFC->cfc_Count; J++) /* Fore each color in table */
- {
- CMap[J].red= (CFC->cfc_ColorTable[J] & 0x0F00)>>4;
- CRegs[J*3+0]= Color32(CMap[J].red);
- CMap[J].green= (CFC->cfc_ColorTable[J] & 0x00F0);
- CRegs[J*3+1]= Color32(CMap[J].green);
- CMap[J].blue= (CFC->cfc_ColorTable[J] & 0x000F)<<4;
- CRegs[J*3+2]= Color32(CMap[J].blue);
- }
- }
-
- /* Prepare bitmap */
- try(RP.BitMap=AllocBitMap(BMHD->bmh_Width,BMHD->bmh_Height,BMHD->bmh_Depth,
- BMF_CLEAR | BMF_INTERLEAVED,NULL),
- ERROR);
-
- /* Do rendering */
- if(Render(cb,&RP,&Opts,Fonts,NumFonts,Width))
- {
- /* Set attributes of destination picture */
- LocSetDTAttrs(cb,o,DTA_ObjName, Title,
- DTA_NominalHoriz, BMHD->bmh_Width,
- DTA_NominalVert, BMHD->bmh_Height,
- PDTA_BitMap, RP.BitMap,
- PDTA_ModeID, ModeID,
- TAG_DONE);
- Result=TRUE;
- }
- else
- FreeBitMap(RP.BitMap);
-
- /* Cleanup */
- catch(ERROR, );
- catch(NO_FONTS, CloseFonts(cb,Fonts,NumFonts));
- catch(NO_FCH, DisposeFC(cb,FCH));
- catch(NO_LOCK, UnLock(DirLock));
- catch(NO_NAME, );
- catch(NO_FIB, FreeDosObject(DOS_FIB,FIB)); /* MUST be freed here, not before! */
- catch(EXIT, );
- if(PH) FreeFontPrefs(cb,PH);
- return(Result);
- } /* GetFont */
-
-
- /****************************************************************************/
- /* Font management */
- /****************************************************************************/
-
- STATIC struct TextFont **OpenFonts(struct ClassBase *cb, struct Opts *opts,
- struct FontContentsHeader *fch, STRPTR name)
- {
- struct TagItem MyTags[]=
- {
- {TA_DeviceDPI, 0},
- {TAG_DONE, 0}
- }; /* MyTags */
- struct TTextAttr TTA;
- struct TextFont **Fonts;
- struct TFontContents *TFC;
- LONG XDPI,YDPI;
- ULONG I,NumEntries=fch->fch_NumEntries;
- LBOOL One=FALSE; /* Got at least one size */
-
- try(Fonts=AllocVec(NumEntries*sizeof(APTR),MEMF_CLEAR), NO_FONTS);
- for(I=0; I<NumEntries; I++)
- {
- TFC=&TFontContents(fch)[I]; /* Get FontContents */
- TTA.tta_Name=name; /* Copy attrs */
- TTA.tta_YSize=TFC->tfc_YSize;
- TTA.tta_Style=TFC->tfc_Style;
- TTA.tta_Flags=TFC->tfc_Flags | FPF_DISKFONT;
- if(ftst(TFC->tfc_Style,FSF_TAGGED)) /* Tags should be set */
- TTA.tta_Tags=(struct TagItem *)
- &TFC->tfc_FileName
- [MAXFONTPATH-(TFC->tfc_TagCount*sizeof(struct TagItem))];
- else if(opts->opt_XDPI && opts->opt_YDPI) /* Set our own DPI tags */
- {
- XDPI=clamp(*opts->opt_XDPI,1,65535);
- YDPI=clamp(*opts->opt_YDPI,1,65535);
- MyTags[0].ti_Data=(XDPI<<16) | YDPI;
- TTA.tta_Tags=MyTags;
- fset(TTA.tta_Style,FSF_TAGGED);
- }
- if(Fonts[I]=OpenDiskFont((struct TextAttr *)&TTA))
- One=TRUE;
- }
- if(One) /* Got at least one font */
- { /* Sort by size */
- qsort(Fonts,NumEntries,sizeof(APTR),(SFUNC *)SortFunc);
- return(Fonts);
- }
- else
- SetIoErr(ERROR_OBJECT_NOT_FOUND); /* Set error */
-
- catch(NO_FONTS, FreeVec(Fonts));
- return(NULL);
- } /* OpenFonts */
-
- STATIC VOID CloseFonts(struct ClassBase *cb, struct TextFont **f, ULONG cnt)
- {
- ULONG I;
-
- for(I=0; I<cnt; I++)
- if(f[I])
- CloseFont(f[I]);
- FreeVec(f);
- } /* CloseFonts */
-
-
- /****************************************************************************/
- /* Rendering */
- /****************************************************************************/
-
- STATIC LBOOL GetWH(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
- struct TextFont *f, ULONG *w, ULONG *h)
- {
- STRPTR CurStr,*Strs;
- ULONG W,J,SCnt;
-
- if(Strs=PrepStrings(cb,opt,f,&SCnt)) /* Allocate and init strings */
- {
- /* Calculate sizes */
- SetFont(rp,f);
- for(J=0; J<SCnt; J++)
- {
- CurStr=Strs[J];
- W=TextLength(rp,CurStr,strlen(CurStr)); /* Calculate len of this line */
- if(W>*w) /* If larger... */
- *w=W; /* Make it new width */
- *h+=f->tf_YSize; /* Add to height */
- }
- FreeVec(Strs); /* Free strings */
- }
- return(Strs!=NULL);
- } /* GetWH */
-
- STATIC LBOOL Render(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
- struct TextFont **f, ULONG cnt, ULONG w)
- {
- struct TextFont *F;
- STRPTR CurStr,*Strs;
- ULONG SCnt,I,J,X,Y=0;
- LBOOL Rendered=FALSE;
-
- for(I=0; I<cnt; I++) /* For each font size */
- if(F=f[I]) /* Size opened? */
- if(Strs=PrepStrings(cb,opt,F,&SCnt)) /* Allocate and init strings */
- {
- Rendered=TRUE;
- /* Do rendering */
- SetFont(rp,F); /* Make it current font */
- for(J=0; J<SCnt; J++)
- {
- CurStr=Strs[J];
- X=opt->opt_Center ? (w-TextLength(rp,CurStr,strlen(CurStr)))/2 : 0;
- Move(rp,X,Y+F->tf_Baseline);
- Text(rp,CurStr,strlen(CurStr));
- Y+=F->tf_YSize;
- }
- FreeVec(Strs); /* Free strings */
- }
- return(Rendered);
- } /* Render */
-
- STATIC STRPTR *PrepStrings(struct ClassBase *cb, struct Opts *opt,
- struct TextFont *f, ULONG *cnt)
- {
- STRPTR S1,S2,CurStr;
- STRPTR *Strs,*Ss;
- ULONG I,Cnt,Temp;
-
- /* Calculate number of strings */
- Cnt=2;
- if(Ss=opt->opt_Strings) /* Strings given */
- while(CurStr=*Ss++) /* For each string */
- if(*CurStr) /* Non-empty string */
- Cnt++; /* Increase count */
-
- /* Allocate and fill strings array */
- if(Strs=AllocVec(Cnt*sizeof(STRPTR)+MAX_CHAR+MAX_CHAR2,MEMF_CLEAR))
- {
- S1=(STRPTR)Strs+Cnt*sizeof(STRPTR);
- S2=S1+MAX_CHAR;
- Cnt=0;
- if(opt->opt_FontName && FontName(f)) /* FontName - first */
- {
- SNPrintf(S2,MAX_CHAR-1,"%s %ld",FontName(f),f->tf_YSize);
- Strs[Cnt++]=S2; /* Init strings array */
- }
- Temp=Cnt;
- if(Ss=opt->opt_Strings) /* User's strings given */
- while(CurStr=*Ss++) /* While array not filled */
- if(*CurStr) /* Non-empty string */
- Strs[Cnt++]=CurStr; /* Fill in array */
- if(Cnt==0 || !Ss && Cnt==Temp) /* Use charset */
- {
- for(I=f->tf_LoChar; I<=f->tf_HiChar; I++)
- S1[I - f->tf_LoChar]=I ? (CHAR)I : ' '; /* Make ASCII array */
- Strs[Cnt++]=S1;
- }
- *cnt=Cnt;
- }
- return(Strs);
- } /* PrepStrings */
-
- STATIC LONG SortFunc(struct TextFont **tf1, struct TextFont **tf2)
- {
- if(*tf1 && *tf2) return((LONG)(*tf1)->tf_YSize - (*tf2)->tf_YSize);
- else if(*tf1) return(-1);
- else if(*tf2) return(1);
- else return(0);
- } /* SortFunc */
-
-
- /****************************************************************************/
- /* DataTypes stubs */
- /****************************************************************************/
-
- STATIC ULONG LocSetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...)
- {
- return(SetDTAttrsA(o,NULL,NULL,(struct TagItem *)&data));
- } /* LocSetDTAttrs */
-
- STATIC ULONG LocGetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...)
- {
- return(GetDTAttrsA(o,(struct TagItem *)&data));
- } /* LocGetDTAttrs */
-