#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: raster_text.c,v 1.10 2012/01/31 04:28:03 matt Exp $");
#include <sys/param.h>
#ifdef _KERNEL
#include <sys/systm.h>
#include <dev/rcons/raster.h>
#ifdef COLORFONT_CACHE
#include <sys/malloc.h>
#define NEW(size) malloc(size, M_DEVBUF, M_NOWAIT)
#endif
#else
#include <string.h>
#include "raster.h"
#ifdef COLORFONT_CACHE
#include <malloc.h>
#define NEW(size) malloc(size)
#endif
#endif
int
raster_text(
struct raster* r,
int x,
int y,
int rop,
struct raster_font* rf,
unsigned char* text)
{
return raster_textn( r, x, y, rop, rf, text, strlen( text ) );
}
int
raster_textn(
struct raster* r,
int x,
int y,
int rop,
struct raster_font* rf,
unsigned char* text,
int n)
{
int clip;
int x1, y1;
struct raster_char* c;
struct raster* charrast;
int i;
unsigned char ch;
int thisx, thisy;
int phase;
clip = 0;
if ( rf->flags & RASFONT_FIXEDWIDTH &&
rf->flags & RASFONT_NOVERTICALMOVEMENT )
{
c = &(rf->chars['@']);
charrast = c->r;
if ( x + c->homex < 0 || y + c->homey < 0 ||
x + c->homex + n * c->nextx > r->width ||
y + c->homey + charrast->height > r->height )
clip = 1;
}
else
{
for ( i = 0, x1 = x, y1 = y;
i < n;
++i, x1 += c->nextx, y1 += c->nexty )
{
c = &(rf->chars[text[i]]);
charrast = c->r;
if ( charrast != (struct raster*) 0 )
{
if ( x1 + c->homex < 0 || y1 + c->homey < 0 ||
x1 + c->homex + charrast->width > r->width ||
y1 + c->homey + charrast->height > r->height )
{
clip = 1;
break;
}
}
}
}
for ( i = 0, x1 = x, y1 = y;
i < n;
++i, x1 += c->nextx, y1 += c->nexty )
{
ch = text[i];
c = &(rf->chars[ch]);
charrast = c->r;
if ( charrast != (struct raster*) 0 )
{
thisx = x1 + c->homex;
thisy = y1 + c->homey;
phase = 0;
#ifdef COLORFONT_CACHE
if ( r->depth == 8 )
{
if ( rf->cache == (struct raster_fontcache*) -1 )
{
int c;
rf->cache = (struct raster_fontcache*)
NEW( sizeof(struct raster_fontcache) );
if ( rf->cache != (struct raster_fontcache*) 0 )
for ( c = 0; c < 256; ++c )
rf->cache->cr[c] = (struct raster*) 0;
}
if ( rf->cache != (struct raster_fontcache*) 0 )
{
int color;
struct raster* cr;
color = RAS_GETCOLOR( rop );
cr = rf->cache->cr[ch];
if ( cr != (struct raster*) 0 )
{
if ( rf->cache->color[ch] == color )
{
charrast = cr;
}
else
{
if ( raster_op_noclip(
cr, 0, 0, charrast->width,
charrast->height, rop, charrast, 0, 0 ) == 0 )
{
rf->cache->color[ch] = color;
charrast = cr;
}
}
}
else
{
cr = raster_alloc(
charrast->width, charrast->height, 8 );
if ( cr != (struct raster*) 0 )
if ( raster_op_noclip(
cr, 0, 0, charrast->width, charrast->height,
rop, charrast, 0, 0 ) == 0 )
{
rf->cache->color[ch] = color;
charrast = rf->cache->cr[ch] = cr;
}
}
}
}
#endif
if ( clip )
{
if ( raster_op(
r, thisx, thisy, charrast->width, charrast->height,
rop, charrast, phase, 0 ) < 0 )
return -1;
}
else
{
if ( raster_op_noclip(
r, thisx, thisy, charrast->width, charrast->height,
rop, charrast, phase, 0 ) < 0 )
return -1;
}
}
}
return 0;
}
#ifdef COLORFONT_CACHE
struct raster*
raster_alloc(
int width,
int height,
int depth)
{
struct raster* r;
int linelongs;
if ( width <= 0 || height <= 0 || ( depth != 1 && depth != 8 ) )
return (struct raster*) 0;
linelongs = ( ( width * depth + 31 ) >> 5 );
r = (struct raster*)
NEW( sizeof(struct raster) + height * linelongs * sizeof(u_int32_t));
if ( r == (struct raster*) 0 )
return (struct raster*) 0;
r->width = width;
r->height = height;
r->depth = depth;
r->linelongs = linelongs;
r->pixels = (u_int32_t*) (r + 1);
r->data = (void *) 0;
return r;
}
#endif