Texto en modo gráfico

 
Hardware
Modo 13h
Retrazado Vertical
Primitivas
La Paleta
Pantallas Virtuales
Sprites
Tablas Prefedifinidas
Efectos
Texto
Formatos gráficos
Periféricos
Optimizaciones
Herramientas
Cursos
Links
Foro
Correo Electrónico
Hasta el momento para colocar texto en la pantalla solo utilizábamos las funciones que nos proporcionaba nuestro compilador.

Ahora veremos como colocar texto en modo gráfico. Podemos colocar texto normal, en negrita, sombreado, cursiva, etc., sin el uso de la BIOS, ni funciones del compilador.

El método que veremos se basa en la lectura de los caracteres  que hay almacenados en la memoria ROM, pero como veremos más adelante, también los podremos cargar de un archivo utilizando  fuentes de 8x16  (los  archivos *.fnt que ocupan 4096 bytes=8*16*256). Y como veremos y hemos  dicho antes,  a estas les podremos aplicar diferentes efectos.

La tabla de caracteres se encuentra el la posición F000:FA6A, aquí es donde comienza la descripción de los 256 caracteres. Cada uno esta representado mediante 8 bytes. Cada byte es el patrón o mascara de una fila. Por ejemplo, si tenemos la letra 'A', sus 8 bytes serían 56, 108, 198, 198, 254, 198,198, y 0, como se muestra en la figura:

Letra A

Para descomponer los diferentes bits de un byte, es decir para saber si  va un pixel o no, lo que haremos será utilizar la operación lógica “>>”. Lo que hace esta operación es rotar un bit n posiciones a la derecha (lo cual corresponde a una división), así si queremos  saber que valor hay en el bit número 3 de menor peso del  número 53 (empezando por el de más a la derecha), haremos la siguiente operación:

53 AND (256 SHR 3)

Esto nos dará un 1 o por el contrario, un cero, depende de si dicho bit esta encendido o apagado.

Ahora crearemos nuestra primera rutina, la cual colocará solo un carácter en la pantalla. Pero para esto necesitamos un puntero a la tabla de caracteres de la ROM:

unsigned char *Font8x8=(unsigned char *) 0xF000FA6E; 

De esta forma utilizando el puntero Font8x8, podremos acceder a cualquiera de los 256 caracteres disponibles. 

Para poder representar estos bytes adecuadamente en la pantalla, tendremos  que irnos a la posición correspondiente de las 256 e ir descomponiendo  todos los bits de cada byte, e ir dibujando sólo los que den 1, a medida que cambiemos de byte, aumentaremos la posicion Y en uno, ya que es el que corresponde a una línea más abajo en pantalla. Veamos como queda:
 

void WriteChar8x8(int x, int y, unsigned char car, unsigned char color, 
                              unsigned char *where)
{
    register int linea, pos;

    for(linea=0; linea<8; linea++)
        for(pos=0; pos<8; pos++)
            if(Font8x8[(car<<3)+linea] & (256>>pos))
                where[((y+linea)<<8)+((y+linea)<<6)+x+pos]=color;
}

Para dibujar una cadena entera, lo que haremos será, antes de entrar en el bucle encargado de dibujarnos el carácter obtener  el tamaño de la  cadena. En C eso lo podemos hacer mediante la función strlen().

Como sabemos el tamaño de la cadena, sólo tendremos que ir dibujando carácter a carácter, teniendo en cuenta que tendremos que aumentar en 8 la X cada vez que dibujemos un carácter.
 

void Write8x8(int x, int y, unsigned char *cadena,  unsigned char color, 
                       unsigned char *where)
{
    register int i, linea, pos;
    int longitud=strlen(cadena);

    for(i=0; i<longitud; i++)
        for(linea=0; linea<8; linea++)
            for(pos=0; pos<8; pos++)
                if(Font8x8[(cadena[i]<<3)+linea] & (256>>pos))
                    where[((y+linea)<<8)+((y+linea)<<6)+x+pos+(i<<3)]=color;
}

 Si queremos hacerlo con cursiva, lo único que tendremos que hacer es ir desplazando X en n-1 posiciones cada vez, de manera que cuando Y sea igual 8, n sea igual 1, o sea, a X le sumaremos 0 y así quedará como  estaba,  vamos a ver esto con más detalle, la siguiente función coloca texto en cursiva:
 

void WriteCur8x8(int x, int y, unsigned char *cadena,  unsigned char color, 
                            unsigned char *where)
{
    register int i, linea, pos;
    int longitud=strlen(cadena);

    x+=6;
    for(i=0; i<longitud; i++)
        for(linea=0; linea<8; linea++)
            for(pos=0; pos<8; pos++)
                if(Font8x8[(cadena[i]<<3)+linea] & (256>>pos))
                    where[((y+linea)<<8)+((y+linea)<<6)+x+pos+(i<<3)-linea]=color;
}

Si lo que queremos es dibujar con sombra, la función necesitará dos valores; el  color del texto y el color de la sombra. Ahora lo  único que deberemos hacer es dibujar con la función encargada de escribir un texto que vimos antes, Write8x8().
Primero colocaremos la sombra, pero desplazando X e Y una posicion y luego el texto con el color correspondiente.
 

void WriteShadow8x8(int x, int y, unsigned char *cadena, unsigned char color, 
                                    unsigned char c_shadow, unsigned char *where)
{
    Write8x8(x+1, y+1, cadena, c_shadow, where);
    Write8x8(x, y, cadena, color, where);
}

También podríamos crear texto en negrita, esto es muy simple. Veamos:
 

void WriteNeg8x8(int x, int y, unsigned char *cadena, unsigned char color, 
                             unsigned char *where)
{
    Write8x8(x, y, cadena, color, where);
    Write8x8(x+1, y, cadena, color, where);
}

Normalmente el tamaño de 8x8 se  nos hace  demasiado pequeño para los modos SVGA que se usan hoy en día (como mínimo 640x480). Existen  otro  tipo diferente de letras, estas son el doble de altas  que  las  anteriores. Estos tipos de fuentes pueden  ser cargadas desde unos archivos de extensión *.fnt. Estos archivos contienen varios tipos diferentes de fuentes que podrán ser retocadas con alguno de los muchos diferentes tipos de programas que hay para esto, así que se hacen ideales para utilizar en juegos, demos, etc.  Estos archivos no son nada más que caracteres de tamaño 8x16 almacenados de la misma forma  que los de 8x8, pero en vez de estar en memoria, estos se encuentran en un archivo. Los primeros 16 bytes de estos archivos corresponderán al carácter 0 de la tabla ASCII, y así recorriendo todas sus posiciones hasta llegar al byte número 4096 (256*16). La forma de trabajar con estas, no difiere en nada con las anteriores (8x8), pero  ahora deberemos de tener en cuenta que son fuentes de 16 pixeles de alto en vez de 8.

Para trabajar con estos archivos crearemos un nuevo tipo de dato:

typedef unsigned char t_font[4096];

De esta forma cuando queramos cargar alguna fuente en especial, simplemente crearemos una variable del tipo t_font.

Una rutina que cargue estos archivos puede ser la siguiente:
 

int LoadFont8x16(char *filename, t_font font)
{
    enum{ARCHIVO_NO_ENCONTRADO=0, OK=1};
    FILE *f;

    if((f=fopen(filename,"rb"))==NULL) return ARCHIVO_NO_ENCONTRADO;

    fread(font, sizeof(char), 4096, f);
    fclose(f);

    return OK;
}

 La función para escribir cadenas de texto, pero utilizando caracteres de 8x16 es análoga a la que se hizo para las de 8x8. Ojo que la función tambien necesita como parámetro una variable de tipo t_font. Veamos entonces como nos quedaría esta función:
 

void Write8x16(int x, int y, unsigned char *cadena, unsigned char color, t_font font, 
                         unsigned char *where)
{
    register int i, linea, pos;
    int longitud=strlen(cadena);

    for(i=0; i<longitud; i++)
        for(linea=0; linea<16; linea++)
            for(pos=0; pos<8; pos++)
                if(font[(cadena[i]<<4)+linea] & (256>>pos))
                    where[((y+linea)<<8)+((y+linea)<<6)+x+pos+(i<<3)]=color;
}

Las demás funciones para trabajar con fuentes de 8x16, al igual que todas las rutinas que ya vimos, las podrán encontrar en una librería llamada write.h



Ejemplos 
 

Librería gráfica: vgalib.h
Librería texto: write.h
 


 
Bajar todo Bajar todo (64 Kb) 


Anterior
Página principal
Siguiente
1
Hosted by www.Geocities.ws

1