Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F70153227
text.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Fri, Jul 5, 12:33
Size
7 KB
Mime Type
text/x-c
Expires
Sun, Jul 7, 12:33 (2 d)
Engine
blob
Format
Raw Data
Handle
18798446
Attached To
R10977 RADIANCE Photon Map
text.c
View Options
#ifndef lint
static const char RCSid[] = "$Id: text.c,v 2.27 2016/03/22 03:56:17 greg Exp $";
#endif
/*
* text.c - functions for text patterns and mixtures.
*/
#include "copyright.h"
#include "ray.h"
#include "paths.h"
#include "otypes.h"
#include "rtotypes.h"
#include "font.h"
/*
* A text pattern is specified as the text (a file or line),
* the upper left anchor point, the right motion vector, the down
* motion vector, and the foreground and background brightness.
* For a file, the description is as follows:
*
* modifier brighttext id
* 2 fontfile textfile
* 0
* 11+
* Ax Ay Az
* Rx Ry Rz
* Dx Dy Dz
* foreground background
* [spacing]
*
* For a single line, we use:
*
* modifier brighttext id
* N+2 fontfile . This is a line with N words...
* 0
* 11+
* Ax Ay Az
* Rx Ry Rz
* Dx Dy Dz
* foreground background
* [spacing]
*
* Colortext is identical, except colors are given rather than
* brightnesses.
*
* Mixtext has foreground and background modifiers:
*
* modifier mixtext id
* 4+ foremod backmod fontfile text..
* 0
* 9+
* Ax Ay Az
* Rx Ry Rz
* Dx Dy Dz
* [spacing]
*/
#define fndx(m) ((m)->otype==MIX_TEXT ? 2 : 0)
#define tndx(m) ((m)->otype==MIX_TEXT ? 3 : 1)
#define sndx(m) ((m)->otype==PAT_BTEXT ? 11 : \
(m)->otype==PAT_CTEXT ? 15 : 9)
typedef struct tline {
struct tline *next; /* pointer to next line */
short *spc; /* character spacing */
int width; /* total line width */
/* followed by the string */
} TLINE;
#define TLSTR(l) ((char *)((l)+1))
typedef struct {
FVECT right, down; /* right and down unit vectors */
FONT *f; /* our font */
TLINE tl; /* line list */
} TEXT;
static TLINE * tlalloc(char *s);
static TEXT * gettext(OBJREC *tm);
static int intext(FVECT p, OBJREC *m);
static int inglyph(double x, double y, GLYPH *gl);
int
do_text(
OBJREC *m,
RAY *r
)
{
FVECT v;
int foreground;
/* get transformed position */
if (r->rox != NULL)
multp3(v, r->rop, r->rox->b.xfm);
else
VCOPY(v, r->rop);
/* check if we are within a text glyph */
foreground = intext(v, m);
/* modify */
if (m->otype == MIX_TEXT) {
OBJECT omod;
char *modname = m->oargs.sarg[foreground ? 0 : 1];
if (!strcmp(modname, VOIDID))
omod = OVOID;
else if ((omod = lastmod(objndx(m), modname)) == OVOID) {
sprintf(errmsg, "undefined modifier \"%s\"", modname);
objerror(m, USER, errmsg);
}
if (rayshade(r, omod)) {
if (m->omod != OVOID)
objerror(m, USER, "inappropriate modifier");
return(1);
}
} else if (m->otype == PAT_BTEXT) {
if (foreground)
scalecolor(r->pcol, m->oargs.farg[9]);
else
scalecolor(r->pcol, m->oargs.farg[10]);
} else { /* PAT_CTEXT */
COLOR cval;
if (foreground)
setcolor(cval, m->oargs.farg[9],
m->oargs.farg[10],
m->oargs.farg[11]);
else
setcolor(cval, m->oargs.farg[12],
m->oargs.farg[13],
m->oargs.farg[14]);
multcolor(r->pcol, cval);
}
return(0);
}
static TLINE *
tlalloc( /* allocate and assign text line */
char *s
)
{
int siz;
TLINE *tl;
siz = strlen(s) + 1;
if ((tl=(TLINE *)malloc(sizeof(TLINE)+siz)) == NULL ||
(tl->spc=(short *)malloc(siz*sizeof(short))) == NULL)
error(SYSTEM, "out of memory in tlalloc");
tl->next = NULL;
strcpy(TLSTR(tl), s);
return(tl);
}
static TEXT *
gettext( /* get text structure for material */
OBJREC *tm
)
{
#define R (tm->oargs.farg+3)
#define D (tm->oargs.farg+6)
FVECT DxR;
double d;
FILE *fp;
char linbuf[512];
TEXT *t;
int i;
TLINE *tlp;
char *s;
if ((t = (TEXT *)tm->os) != NULL)
return(t);
/* check arguments */
if (tm->oargs.nsargs - tndx(tm) < 1 || tm->oargs.nfargs < sndx(tm))
objerror(tm, USER, "bad # arguments");
if ((t = (TEXT *)malloc(sizeof(TEXT))) == NULL)
error(SYSTEM, "out of memory in gettext");
/* compute vectors */
fcross(DxR, D, R);
fcross(t->right, DxR, D);
d = DOT(t->right,t->right);
if (d <= FTINY*FTINY*FTINY*FTINY)
objerror(tm, USER, "illegal motion vector");
d = DOT(D,D)/d;
for (i = 0; i < 3; i++)
t->right[i] *= d;
fcross(t->down, R, DxR);
d = DOT(R,R)/DOT(t->down,t->down);
for (i = 0; i < 3; i++)
t->down[i] *= d;
/* get text */
tlp = &t->tl;
if (tm->oargs.nsargs - tndx(tm) > 1) { /* single line */
s = linbuf;
for (i = tndx(tm)+1; i < tm->oargs.nsargs; i++) {
strcpy(s, tm->oargs.sarg[i]);
s += strlen(s);
*s++ = ' ';
}
*--s = '\0';
tlp->next = tlalloc(linbuf);
tlp = tlp->next;
} else { /* text file */
if ((s = getpath(tm->oargs.sarg[tndx(tm)],
getrlibpath(), R_OK)) == NULL) {
sprintf(errmsg, "cannot find text file \"%s\"",
tm->oargs.sarg[tndx(tm)]);
error(SYSTEM, errmsg);
}
if ((fp = fopen(s, "r")) == NULL) {
sprintf(errmsg, "cannot open text file \"%s\"", s);
error(SYSTEM, errmsg);
}
while (fgets(linbuf, sizeof(linbuf), fp) != NULL) {
s = linbuf + strlen(linbuf) - 1;
if (*s == '\n')
*s = '\0';
tlp->next = tlalloc(linbuf);
tlp = tlp->next;
}
fclose(fp);
}
tlp->next = NULL;
/* get the font */
t->f = getfont(tm->oargs.sarg[fndx(tm)]);
/* compute character spacing */
i = sndx(tm);
d = i < tm->oargs.nfargs ? tm->oargs.farg[i] : 0.0;
i = d * 255.0;
t->tl.width = 0;
for (tlp = t->tl.next; tlp != NULL; tlp = tlp->next) {
if (i < 0)
tlp->width = squeeztext(tlp->spc, TLSTR(tlp), t->f, -i);
else if (i > 0)
tlp->width = proptext(tlp->spc, TLSTR(tlp), t->f, i, 3);
else
tlp->width = uniftext(tlp->spc, TLSTR(tlp), t->f);
if (tlp->width > t->tl.width)
t->tl.width = tlp->width;
}
/* we're done */
tm->os = (char *)t;
return(t);
#undef R
#undef D
}
void
freetext( /* free text structures associated with m */
OBJREC *m
)
{
TEXT *tp;
TLINE *tlp;
tp = (TEXT *)m->os;
if (tp == NULL)
return;
while ((tlp = tp->tl.next) != NULL) {
tp->tl.next = tlp->next;
free((void *)tlp->spc);
free((void *)tlp);
}
freefont(tp->f); /* release font reference */
free((void *)tp);
m->os = NULL;
}
static int
intext( /* check to see if p is in text glyph */
FVECT p,
OBJREC *m
)
{
TEXT *tp;
TLINE *tlp;
FVECT v;
double y, x;
int i, h;
/* first, compute position in text */
tp = gettext(m);
v[0] = p[0] - m->oargs.farg[0];
v[1] = p[1] - m->oargs.farg[1];
v[2] = p[2] - m->oargs.farg[2];
x = DOT(v, tp->right);
i = sndx(m);
if (i < m->oargs.nfargs)
x *= tp->f->mwidth + 255.*fabs(m->oargs.farg[i]);
else
x *= 255.;
h = x;
i = y = DOT(v, tp->down);
if (x < 0.0 || y < 0.0)
return(0);
x -= (double)h;
y = ((i+1) - y)*255.;
/* find the line position */
for (tlp = tp->tl.next; tlp != NULL; tlp = tlp->next)
if (--i < 0)
break;
if (tlp == NULL || h >= tlp->width)
return(0);
for (i = 0; (h -= tlp->spc[i]) >= 0; i++)
if (h < 255 && inglyph(h+x, y,
tp->f->fg[TLSTR(tlp)[i]&0xff]))
return(1);
return(0);
}
static int
inglyph( /* (x,y) within font glyph gl? */
double x, /* real coordinates in range [0,255) */
double y,
GLYPH *gl
)
{
int n, ncross;
int xlb, ylb;
int tv;
GORD *p0, *p1;
if (gl == NULL)
return(0);
xlb = x;
ylb = y;
if (gl->left > xlb || gl->right <= xlb || /* check extent */
gl->bottom > ylb || gl->top <= ylb)
return(0);
xlb = xlb<<1 | 1; /* add 1/2 to test points... */
ylb = ylb<<1 | 1; /* ...so no equal comparisons */
n = gl->nverts; /* get # of vertices */
p0 = gvlist(gl) + 2*(n-1); /* connect last to first */
p1 = gvlist(gl);
ncross = 0;
/* positive x axis cross test */
while (n--) {
if ((p0[1]<<1 > ylb) ^ (p1[1]<<1 > ylb)) {
tv = (p0[0]<<1 > xlb) | ((p1[0]<<1 > xlb) << 1);
if (tv == 03)
ncross++;
else if (tv)
ncross += (p1[1] > p0[1]) ^
((p0[1]-y)*(p1[0]-x) >
(p0[0]-x)*(p1[1]-y));
}
p0 = p1;
p1 += 2;
}
return(ncross & 01);
}
Event Timeline
Log In to Comment