When using onscreen plotter: Collect nsfb internal font characters into a single bitmap instead of plotting each character.

svn path=/trunk/netsurf/; revision=12109
This commit is contained in:
Ole Loots 2011-03-20 22:28:53 +00:00
parent dad9306e2a
commit b24b7d8de4
4 changed files with 182 additions and 38 deletions

View File

@ -24,6 +24,8 @@
#include "utils/utf8.h"
#include "utils/log.h"
#include <windom.h>
static int dtor( FONT_PLOTTER self );
static int str_width( FONT_PLOTTER self,const plot_font_style_t *fstyle, const char * str, size_t length, int * width );
@ -43,6 +45,10 @@ const struct fb_font_desc font_italic;
const struct fb_font_desc font_bold;
const struct fb_font_desc font_italic_bold;
static MFDB tmp;
static int tmp_mfdb_size;
#define FONTDATAMAX 4096
static const struct fb_font_desc*
fb_get_font(const plot_font_style_t *fstyle)
@ -92,6 +98,9 @@ int ctor_font_plotter_internal( FONT_PLOTTER self )
static int dtor( FONT_PLOTTER self )
{
if( tmp.fd_addr != NULL ){
free( tmp.fd_addr );
}
return( 1 );
}
@ -169,28 +178,73 @@ static int text( FONT_PLOTTER self, int x, int y, const char *text, size_t leng
utf8_to_font_encoding(fb_font, text, length, &buffer);
if (buffer == NULL)
return true;
return 1;
/* y is given to the fonts baseline we need it to the fonts top */
y-=((fb_font->height * 75)/100);
y-=((fb_font->height * 75)/100);
y+=1; /* the coord is the bottom-left of the pixels offset by 1 to make
/* needed? */
y+=1; /* the coord is the bottom-left of the pixels offset by 1 to make
* it work since fb coords are the top-left of pixels
*/
c = fstyle->foreground;
/* in -> BGR */
/* out -> ARGB */
c = (ABGR_TO_RGB(c) | 0xFF);
blen = strlen(buffer);
loc.g_y = y;
loc.g_w = fb_font->width;
loc.g_h = fb_font->height;
for (chr = 0; chr < blen; chr++) {
loc.g_x = x;
chrp = fb_font->data + ((unsigned char)buffer[chr] * fb_font->height);
draw_glyph1(self, &loc, (uint8_t *)chrp, 32, c);
x+=fb_font->width;
}
if ( blen < 1 ) {
return( 1 );
}
if( self->plotter->flags & PLOT_FLAG_OFFSCREEN ){
/* when the plotter is an offscreen plotter the call to
bitmap() isn't that expensive. Draw an 8 bit bitmap into the
offscreen buffer.
*/
c = fstyle->foreground;
/* in -> BGR */
/* out -> ARGB */
c = (ABGR_TO_RGB(c) | 0xFF);
loc.g_y = y;
loc.g_x = x;
loc.g_w = fb_font->width;
loc.g_h = fb_font->height;
for (chr = 0; chr < blen; chr++) {
loc.g_x = x;
chrp = fb_font->data + ((unsigned char)buffer[chr] * fb_font->height);
draw_glyph1(self, &loc, (uint8_t *)chrp, 32, c);
x+=fb_font->width;
}
} else {
/* render the whole string into an monochrom mfdb */
/* and plot that to reduce overhead */
loc.g_x = x;
loc.g_y = y;
loc.g_w = blen * fb_font->width;
assert( loc.g_w > 0 );
loc.g_h = fb_font->height;
int stride = MFDB_STRIDE( loc.g_w );
if( tmp.fd_addr == NULL || tmp_mfdb_size < MFDB_SIZE( 1, stride, loc.g_h) ){
tmp_mfdb_size = init_mfdb( 1, loc.g_w, loc.g_h+1, MFDB_FLAG_STAND | MFDB_FLAG_ZEROMEM, &tmp );
} else {
void * buf = tmp.fd_addr;
int size = init_mfdb( 1, loc.g_w, loc.g_h+1, MFDB_FLAG_STAND | MFDB_FLAG_NOALLOC, &tmp );
tmp.fd_addr = buf;
memset( tmp.fd_addr, 0, size );
}
int ypos;
int rowsize = tmp.fd_wdwidth << 1;
char * d;
uint32_t * pp;
for (chr = 0; chr < blen; chr++) {
pp = (uint32_t*)fb_font->data + ((unsigned char)buffer[chr] * fb_font->height);
d = ((uint8_t*)tmp.fd_addr) + chr;
for( ypos=0; (unsigned int)ypos<loc.g_h; ypos++){
*d = (unsigned char)*pp++;
d += rowsize;
}
}
unsigned short out[4];
rgb_to_vdi1000( (unsigned char*)&fstyle->foreground, (unsigned short*)&out );
vs_color( self->plotter->vdi_handle, OFFSET_CUSTOM_COLOR, (unsigned short*)&out[0] );
self->plotter->plot_mfdb( self->plotter, &loc, &tmp, PLOT_FLAG_TRANS );
}
free(buffer);
return( 1 );
@ -200,8 +254,6 @@ static int text( FONT_PLOTTER self, int x, int y, const char *text, size_t leng
/* Fontdata */
/* ------------------*/
#define FONTDATAMAX 4096
static const uint32_t fontdata_bold[FONTDATAMAX] = {
0x00, 0xFE, 0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE,
0x00, 0xEE, 0xAA, 0xAA, 0xAA, 0xEE, 0x00, 0xFE,

View File

@ -683,16 +683,22 @@ short rgb_to_666_index(unsigned char r, unsigned char g, unsigned char b)
}
int init_mfdb(int bpp, int w, int h, bool stand, MFDB * out )
int init_mfdb(int bpp, int w, int h, uint32_t flags, MFDB * out )
{
int dststride;
dststride = MFDB_STRIDE( w );
int size = MFDB_SIZE( bpp, dststride, h );
if( bpp > 0 ) {
out->fd_addr = malloc( ((dststride >> 3) * h) * bpp );
if( out->fd_addr == NULL ){
return( 0 );
if( (flags & MFDB_FLAG_NOALLOC) == 0 ) {
out->fd_addr = malloc( size );
if( out->fd_addr == NULL ){
return( 0 );
}
if( (flags & MFDB_FLAG_ZEROMEM) ){
memset( out->fd_addr, 0, size );
}
}
out->fd_stand = stand;
out->fd_stand = (flags & MFDB_FLAG_STAND) ? 1 : 0;
out->fd_nplanes = (short)bpp;
out->fd_r1 = out->fd_r2 = out->fd_r3 = 0;
} else {
@ -701,7 +707,7 @@ int init_mfdb(int bpp, int w, int h, bool stand, MFDB * out )
out->fd_w = dststride;
out->fd_h = h;
out->fd_wdwidth = dststride >> 4;
return( 1 );
return( size );
}
@ -714,6 +720,21 @@ int plotter_get_clip( GEM_PLOTTER self, struct rect * out )
return( 1 );
}
void plotter_get_clip_grect( GEM_PLOTTER self, GRECT * out )
{
out->g_x = self->clipping.x0;
out->g_y = self->clipping.y0;
out->g_w = self->clipping.x1 - self->clipping.x0;
out->g_h = self->clipping.y1 - self->clipping.y0;
}
void plotter_get_visible_grect( GEM_PLOTTER self, GRECT * out )
{
out->g_x = self->clipping.x0;
out->g_y = self->clipping.y0;
out->g_w = self->clipping.x1 - self->clipping.x0;
out->g_h = self->clipping.y1 - self->clipping.y0;
}
int plotter_std_clip(GEM_PLOTTER self, const struct rect * clip)
{

View File

@ -38,6 +38,7 @@
#include "utils/log.h"
#ifndef ceilf
#warning "ceilf emulation"
#define ceilf(x) (float)ceil((double)x)
#endif
@ -55,6 +56,10 @@
#define PLOT_FLAG_DITHER 0x04
#define PLOT_FLAG_TRANS 0x08
#define MFDB_FLAG_STAND 0x01
#define MFDB_FLAG_ZEROMEM 0x02
#define MFDB_FLAG_NOALLOC 0x04
/* Error codes: */
#define ERR_BUFFERSIZE_EXCEEDS_SCREEN 1
#define ERR_NO_MEM 2
@ -168,6 +173,7 @@ typedef int (*_pmf_path)(GEM_PLOTTER self, const float *p, unsigned int n, int f
typedef int (*_pmf_bitmap_resize) ( GEM_PLOTTER self, struct bitmap * bm, int nw, int nh );
typedef int (*_pmf_bitmap)(GEM_PLOTTER self, struct bitmap * bmp, int x, int y,
unsigned long bg, unsigned long flags );
typedef int (*_pmf_plot_mfdb)(GEM_PLOTTER self, GRECT * loc, MFDB * mfdb, uint32_t flags);
typedef int (*_pmf_text)(GEM_PLOTTER self, int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle);
typedef int (*_pmf_dtor)(GEM_PLOTTER self);
@ -206,6 +212,7 @@ struct s_gem_plotter
_pmf_path path;
_pmf_bitmap_resize bitmap_resize;
_pmf_bitmap bitmap;
_pmf_plot_mfdb plot_mfdb;
_pmf_text text;
_pmf_dtor dtor;
};
@ -296,9 +303,10 @@ short rgb_to_666_index(unsigned char r, unsigned char g, unsigned char b);
If bpp == 0, this function assumes that the MFDB shall point to the screen
and will not allocate any memory (mfdb.fd_addr == 0).
The function will return 0 when the memory allocation fails
( out of memory).
( out of memory), otherwise it returns the size of the mfdb.fd_addr
as number of bytes.
*/
int init_mfdb(int bpp, int w, int h, bool stand, MFDB * out );
int init_mfdb(int bpp, int w, int h, uint32_t flags, MFDB * out );
/* shared / static methods follows */
@ -307,11 +315,22 @@ int init_mfdb(int bpp, int w, int h, bool stand, MFDB * out );
*/
int plotter_get_clip( GEM_PLOTTER self, struct rect * out );
/*
Get clipping for current framebuffer as GRECT
*/
void plotter_get_clip_grect( GEM_PLOTTER self, GRECT * out );
/*
Get current visible coords
*/
void plotter_get_visible_grect( GEM_PLOTTER self, GRECT * out );
/*
Set clipping for current framebuffer
*/
int plotter_std_clip(GEM_PLOTTER self, const struct rect * clip);
/*
convert framebuffer clipping to vdi clipping and activates it
*/
@ -358,5 +377,6 @@ void plotter_vdi_clip( GEM_PLOTTER self, bool set);
#define OFFSET_CUSTOM_COLOR 255
#define RGB_TO_VDI(c) rgb_to_666_index( (c&0xFF),(c&0xFF00)>>8,(c&0xFF0000)>>16)+OFFSET_WEB_PAL
#define ABGR_TO_RGB(c) ( ((c&0xFF)<<16) | (c&0xFF00) | ((c&0xFF0000)>>16) ) << 8
#define MFDB_SIZE( bpp, stride, h ) ( ((stride >> 3) * h) * bpp )
#endif

View File

@ -65,6 +65,7 @@ static int path(GEM_PLOTTER self,const float *p, unsigned int n, int fill, float
static int bitmap_resize( GEM_PLOTTER self, struct bitmap * img, int nw, int nh );
static int bitmap( GEM_PLOTTER self, struct bitmap * bmp, int x, int y,
unsigned long bg, unsigned long flags );
static int plot_mfdb( GEM_PLOTTER self, GRECT * where, MFDB * mfdb, uint32_t flags);
static int text(GEM_PLOTTER self, int x, int y, const char *text,size_t length, const plot_font_style_t *fstyle);
static unsigned short sys_pal[256][3]; /*RGB*/
@ -143,6 +144,7 @@ int ctor_plotter_vdi(GEM_PLOTTER self )
self->path = path;
self->bitmap = bitmap;
self->bitmap_resize = bitmap_resize;
self->plot_mfdb = plot_mfdb;
self->text = text;
LOG(("Screen: x: %d, y: %d\n", vdi_sysinfo.scr_w, vdi_sysinfo.scr_h));
@ -352,10 +354,7 @@ static int update_region( GEM_PLOTTER self, GRECT region )
int src_offs;
GRECT screen_area, tmp, visible;
short pxy[10];
visible.g_x = CURFB(self).vis_x;
visible.g_y = CURFB(self).vis_y;
visible.g_w = CURFB(self).vis_w;
visible.g_h = CURFB(self).vis_h;
plotter_get_visible_grect( self, &visible );
/*
LOG(("%s: %s %d\n", (char*)__FILE__, __FUNCTION__, __LINE__));
@ -453,10 +452,7 @@ static int copy_rect( GEM_PLOTTER self, GRECT src, GRECT dst )
GRECT vis;
/* clip to visible rect, only needed for onscreen renderer: */
vis.g_x = CURFB(self).vis_x;
vis.g_y = CURFB(self).vis_y;
vis.g_w = CURFB(self).vis_w;
vis.g_h = CURFB(self).vis_h;
plotter_get_visible_grect( self, &vis );
if( !rc_intersect(&vis, &src) )
return 1;
@ -990,10 +986,7 @@ static int bitmap( GEM_PLOTTER self, struct bitmap * bmp, int x, int y,
return( true );
}
vis.g_x = CURFB(self).vis_x;
vis.g_y = CURFB(self).vis_y;
vis.g_w = CURFB(self).vis_w;
vis.g_h = CURFB(self).vis_h;
plotter_get_visible_grect( self, &vis );
if( !rc_intersect( &vis, &off) ) {
return( true );
}
@ -1020,6 +1013,64 @@ static int bitmap( GEM_PLOTTER self, struct bitmap * bmp, int x, int y,
return( true );
}
static int plot_mfdb (GEM_PLOTTER self, GRECT * loc, MFDB * insrc, uint32_t flags)
{
MFDB screen, tran;
MFDB * src;
short pxy[8];
short pxyclip[4];
short c[2] = {OFFSET_CUSTOM_COLOR, WHITE};
plotter_vdi_clip(self, true);
init_mfdb( 0, loc->g_w, loc->g_h, 0, &screen );
pxy[0] = 0;
pxy[1] = 0;
pxy[2] = loc->g_w -1;
pxy[3] = loc->g_h -1;
pxy[4] = CURFB(self).x + loc->g_x;
pxy[5] = CURFB(self).y + loc->g_y;
pxy[6] = pxy[4] + loc->g_w -1;
pxy[7] = pxy[5] + loc->g_h -1;
if( insrc->fd_stand ){
int size = init_mfdb( insrc->fd_nplanes, loc->g_w, loc->g_h,
MFDB_FLAG_NOALLOC,
&tran
);
if( DUMMY_PRIV(self)->size_buf_scr == 0 ){
DUMMY_PRIV(self)->buf_scr.fd_addr = malloc( size );
DUMMY_PRIV(self)->size_buf_scr = size;
} else {
if( size > DUMMY_PRIV(self)->size_buf_scr ) {
DUMMY_PRIV(self)->buf_scr.fd_addr = realloc(
DUMMY_PRIV(self)->buf_scr.fd_addr, size
);
DUMMY_PRIV(self)->size_buf_scr = size;
}
}
tran.fd_addr = DUMMY_PRIV(self)->buf_scr.fd_addr;
vr_trnfm( self->vdi_handle, insrc, &tran );
src = &tran;
} else {
src = insrc;
}
if( flags & PLOT_FLAG_TRANS && src->fd_nplanes == 1){
vrt_cpyfm( self->vdi_handle, MD_TRANS, (short*)pxy, src, &screen, (short*)&c );
} else {
}
if( insrc->fd_stand ){
// TODO: shrink conv buffer
}
plotter_vdi_clip(self, false);
return( 1 );
}
static int text(GEM_PLOTTER self, int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle)
{
self->font_plotter->text( self->font_plotter, x, y,