martes, 1 de diciembre de 2020

Cuadro de texto (Parte 1 de 2 )

Se define un cuadro o rectángulo donde se muestra un texto, que se adapta al tamaño. En este ejemplo se realizará una clase encargada de mostrar el texto por pantalla, dada unas dimensiones de un rectángulo que delimita el espacio donde se muestra el texto.





La clase en cuestión la llamaremos Mensaje.


Esta clase consta de varios métodos:

  • Crear - se utiliza para indicar el texto a mostrar e indicar el tamaño del rectangulo.
  • Cuadro - se encarga de modificar el tamaño del rectangulo
  • CambiarFuente - se encarga de cambiar el tipo de letra que se utiliza al pintar el texto.
  • Pinta - muestra por pantalla el cuadro.


Para controlar todo esto la clase tiene las siguientes variables privadas:

  • string stexto - contiene el texto a mostrar
  • ALLEGRO_FONT* fuente - almacena el tipo de fuente que se utiliza.
  • int espaciado - indica el numero de pixels que deja entre el texto y el limite del rectángulo
  • int mx1, my1,mx2, my2 - Se utilizan para delimitar el rectángulo donde se muestra el texto.
  • int ancho, alto - contiene las medidas del rectángulo actual, el ancho y el alto respectivamente.
  • int tancho - contiene el ancho que ocupa el texto según la fuente almacenada.
  • int talto - contiene la altura que ocupa el texto según la fuente almacenada.
  • int nlineas - indica el número de líneas que se necesitan para mostrar todo el texto dentro del rectángulo definido.


POR PARTES


Método Crear


    void Crear(const char* t, ALLEGRO_FONT* f, int x1, int y1, int x2, int y2, int _espaciado = 4)
    {
        stexto = t;
        espaciado = _espaciado;
        ancho = 0;
        CambiarFuente(f);
        Cuadro(x1, y1, x2, y2);
    }


El método crear tiene seis parámetros obligatorios y uno opcional. 

  • El primero indica el texto que se quiere mostrar.
  • El segundo el tipo de fuente que se utilizará para escribir el texto.
  • El tercero y cuarto, indican la posición de una esquina del rectángulo.
  • El quinto y sexto, indican la posición de la esquina opuesta del rectángulo.
  • El séptimo parámetro indica el espacio de separación entre el texto y el marco del rectángulo. Si no se especifica toma como valor por defecto 4.

Lo primero que hace este método es asignar el texto recibido a la variable correspondiente stexto.

Luego se asigna de igual forma espaciado. Y a ancho se le asigna valor 0 para que cuando se llame la función CambiarFuente tenga un valor inicial, si no se hiciera esto daría un error.

Se llama a la función CambiarFuente con la fuente recibida, y cuadro con las coordenadas recibidas. 


Método CambiarFuente


    void CambiarFuente(ALLEGRO_FONT* f) {
        tancho = al_get_text_width(f, stexto.c_str());
        talto = al_get_font_line_height(f) + espaciado;
        fuente = f;
        if ( ancho > 0) numlineas();
    };


Este método tiene un único parámetro que es la fuente que se desea utilizar.

Partiendo del texto y la fuente se calcula el ancho y alto que ocupa el texto con ese tipo de letra y se guardan en tancho y talto respectivamente.

Si ancho es mayor de cero quiere decir que ya se ha calculado el tamaño del rectángulo y en ese caso se calcula el numero de líneas que ocupará el texto.


Método Cuadro


    void Cuadro(int x1, int y1, int x2, int y2)
    {
        mx1 = min(x1, x2);
        mx2 = max(x1, x2);
        my1 = min(y1, y2);
        my2 = max(y1, y2);
        ancho = mx2 - mx1;
        alto  = my2 - my1;
        if ( ancho > 0) numlineas();
    }


Este método tiene cuatro parámetros mediante los cuales se indica el tamaño del rectángulo.

Se ordenan las coordenadas dejando la posición mas pequeña en mx1,my1 , y los de mayor valor en mx2,my2. De este modo me aseguro que cuando se realice la resta salga positivo.

Esta parte realmente se podría haber realizado de otro modo por ejemplo:

    void Cuadro(int x1, int y1, int x2, int y2)
    {
        ancho = abs(mx1 - mx2);
        alto = abs(my1 - my2);
        if ( ancho > 0) numlineas();
    }


Tiene una condición que comprueba si el ancho es mayor de cero calcula el numero de líneas, esto es para evitar posibles errores.

Realmente cuando el ancho sea muy pequeño no debería mostrar nada, ya que no hay espacio para poner el texto.


Método Pinta


    void Pinta()
    {
        int cont;
        int espacio = 0;
        char* mtexto = (char*)stexto.c_str();
        int linea = 0;
        int ni;
        int altura = 0;
        float exacto;
        ALLEGRO_COLOR black = al_map_rgb(0, 0, 0);
        ALLEGRO_COLOR blue = al_map_rgb(0, 200, 250);
        al_draw_rectangle(mx1, my1, mx2, my2, black, 0);
        if (tancho + espaciado > ancho && ancho > espaciado ) 
        {
            // no cabe en una linea  
            string resto = stexto;
            string trozo;
            char caracter[] = " ";
            char* caracter2;
            int nuevoancho = 0;
            int nc = 0;
            int restoancho = 0;
            do 
            {
                cont = 1;
                trozo = resto.substr(0, cont);
                mtexto = (char*)trozo.c_str();
                nuevoancho = al_get_text_width(fuente, mtexto);
                espacio = 0;
                while (nuevoancho + espaciado < ancho) 
                {
                    trozo = resto.substr(cont, 1);
                    caracter2 = (char*)trozo.c_str();
                    if (strcmp(caracter2, caracter) == 0) 
                    {
                        espacio = cont;
                    }
                    cont++;
                    trozo = resto.substr(0, cont);
                    mtexto = (char*)trozo.c_str();
                    nuevoancho = al_get_text_width(fuente, mtexto);
                }
                nc = resto.length();
                trozo = resto.substr(cont, 1);
                caracter2 = (char*)trozo.c_str();
                if (espacio > 0 && cont < nc && strcmp(caracter2, caracter) != 0) 
                {
                    trozo = resto.substr(0, espacio);
                    mtexto = (char*)trozo.c_str();
                    resto = resto.substr(espacio);                   
                }
                else 
                {
                    trozo = resto.substr(0, cont);
                    mtexto = (char*)trozo.c_str();
                    resto = resto.substr(cont);
                }
                altura = alto - (talto * nlineas);
                exacto = (alto / nlineas);
                ni = int(exacto);
                al_draw_text(fuente, blue, mx1 + 1, my1 + (ni * linea) - (talto / 2) + (ni / 2), 0, mtexto);
                
                linea++;
                restoancho = al_get_text_width(fuente, resto.c_str());
            } while (restoancho + espaciado > ancho);
            mtexto = (char*)resto.c_str();
            al_draw_text(fuente, blue, mx1 + 1, my1 + (ni * linea) - (talto / 2) + (ni / 2), 0, mtexto);
        }
        else 
        {
            if ( ancho > espaciado)
              al_draw_text(fuente, blue, mx1 + 1, my1 + ((alto - talto) / 2), 0, mtexto);
        }
    }


El método pinta es el que se encarga de todo lo importante, quizás no sea lo mas correcto pero es la forma como lo yo lo hice. 

Se comprueba si cabe la frase en una línea, y si no es así empieza a recorrer carácter a carácter y va comprobando si cabe en el ancho del rectángulo, en el momento en el que ya no cabe se comprueba si ha aparecido algún espacio y si es así corta la frase hasta el espacio, sino cortará la palabra para hacer que entre.

Como aún queda mucho por explicar lo he dividido en dos partes, aquí finaliza la primera parte. 

No hay comentarios:

Publicar un comentario

Antes de publicar un comentario

Todos los comentarios que se realicen en el blog son moderados.

Debido a esto es muy probable que tu comentario no aparezca de inmediato ya que previamente debe ser revisado para evitar un mal uso (SPAM).

Podrán realizar comentario cualquiera que tenga una cuenta de Google.

Related Posts Plugin for WordPress, Blogger...