/*
 * Glyph Keeper benchmark with Allegro
 *
 * Copyright (c) 2003-2007 Kirill Kryukov
 *
 * This file is part of Glyph Keeper library, and may only be used,
 * modified, and distributed under the terms of the Glyph Keeper
 * license, located in the file 'license.txt' within this package.
 */


/*
 * This program prints random characters to screen (or memory bitmap),
 * testing Glyph Keeper rendering speed.
 *
 * Compiling: It requires Glyph Keeper 0.31 or later, and Allegro.
 *
 * Rinning: Just run it. All settings are in "bench.cfg" file.
 */

/* Standard includes. */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <limits.h>
#include <ctype.h>

/* Target library. */
#include <allegro.h>

/* Glyph Keeper header. */
#ifndef GK_NO_LEGACY
#define GK_NO_LEGACY
#endif
#include "glyph.h"

/* Code shared by several benchmark programs. */
#include "bench_utils.c"

/* Code shared by Glyph Keeper benchmarks. */
#include "bench_gk_common.c"



time_t start_time, now, now1;
int char_count = 0;

int info_color;

BITMAP* bmp = 0;



void exit_handler()
{
    glyph_keeper_finish();
}


void screen_message(int x,int y,char* text)
{
    textprintf_ex(screen,font,x,y,info_color,-1,text);
}


void screen_rect(int x1,int y1,int x2,int y2)
{
    rectfill(screen,x1,y1,x2,y2,info_color);
}


/* This function updates time and chars/sec count. */
/* Also updates screen if we are using memory bitmap. */
void update()
{
    int seconds = now1-start_time;
    int minutes = seconds/60;
    int hours;
    seconds -= minutes*60;
    hours = minutes/60;
    minutes -= hours*60;

    set_clip_rect(bmp,0,0,screen_width-1,screen_height-1);
    rectfill(bmp,0,0,screen_width-1,area_top-1,0);

    textprintf_ex(bmp,font,12,7,info_color,0,
                  "%02d:%02d:%02d  %ld chars/sec, glyph cache: %d bytes",
                  hours,minutes,seconds,char_count/(now1-start_time),gk_keeper_byte_count(keep));

    textprintf_ex(bmp,font,12,19,info_color,0,
                  "GK memory: %d bytes (GK: %d + %d, FT: %d + %d)",
                  gk_bytes_allocated(),
                  gk_total_gk_allocated_bytes(), gk_total_gk_overhead_bytes(),
                  gk_total_ft_allocated_bytes(), gk_total_ft_overhead_bytes() );

    /*textprintf_ex(bmp,font,12,17,info_color,0,"glyph cache: %d bytes",gk_keeper_byte_count(keep));
    textprintf_ex(bmp,font,200,17,info_color,0,"GK memory: %d bytes",gk_bytes_allocated());
    textprintf_ex(bmp,font,400,17,info_color,0,"GK total: %d bytes",gk_total_gk_bytes_allocated());
    textprintf_ex(bmp,font,600,17,info_color,0,"FT total: %d bytes",gk_total_ft_bytes_allocated());*/
    if (clip_on) set_clip_rect(bmp,SCREEN_W/4,SCREEN_H/4,SCREEN_W*3/4,SCREEN_H*3/4);
    else set_clip_rect(bmp,0,23,SCREEN_W,SCREEN_H);
    if (bmp!=screen) blit(bmp,screen,0,0,0,0,screen_width,screen_height);
}


int main(int argc,char *argv[])
{
    /* Registering exit handler. */
    atexit(exit_handler);

    /* Reading the configuration file. */
    init_benchmark("bench_gk_alleg",argv[0],(argc>1)?argv[1]:0);
    if (!logfile) { exit(1); }

    /* Initializing Allegro and setting graphics mode. */
    if (allegro_init()) { fprintf(logfile,"Can't init Allegro\n"); exit(1); }
    if (install_keyboard()) { fprintf(logfile,"Can't initialize keyboard\n"); exit(1); }
    set_color_depth(color_depth);
    if (set_gfx_mode(GFX_AUTODETECT_WINDOWED,screen_width,screen_height,0,0) || !screen)
        if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN,screen_width,screen_height,0,0) || !screen)
            { fprintf(logfile,"Can't set graphics mode\n"); exit(1); }
    fprintf(logfile,"Graphics mode %dx%dx%d set, draw_to_screen: %s, clipping: %s\n",
        SCREEN_W,SCREEN_H,(bitmap_color_depth(screen)),draw_to_screen?"ON":"OFF",clip_on?"ON":"OFF");

    info_color = makecol(128,192,128);

    /* Initializing target bitmap. */
    if (draw_to_screen) bmp = screen;
    else
    {
        bmp = create_bitmap(screen_width,screen_height);
        if (!bmp) { fprintf(logfile,"Can't create buffer bitmap\n"); exit(1); }
    }



    /* Loading a font from file, creating a glyph cache, etc. */
    glyph_keeper_startup();

    /* Creating and configuring font renderers. */
    create_font_renderers();

    /* Pre-caching the glyphs. */
    /* It will work without pre-caching about the same way, */
    /* just I think pre-caching may give slightly more accurate benchmark result. */
    if (cache_on) precache_all_glyphs();

    /* Filling the test dataset. */
    if (test_dataset_num_elements > 0) fill_test_dataset();



    /* Waiting for the start of new second. */
    { int zero = time(0); do time(&start_time); while (start_time==zero); }
    now = start_time;

    if (bmp==screen) clear(screen);
    if (clip_on) set_clip_rect(bmp,SCREEN_W/4,SCREEN_H/4,SCREEN_W*3/4,SCREEN_H*3/4);



    /* Running the benchmark until the ESC or SPACE is hit. */
    if (test_dataset_num_elements > 0)
    {
        int di = 0, ri = 0;
        int go_on = 1;
        int i;

        while (go_on)
        {
            for (i=0; i<100; i++)
            {
                gk_render_line_utf32(bmp,rends[ri],test_dataset[di].text,test_dataset[di].x,test_dataset[di].y);

                char_count += test_dataset[di].length;

                di++;
                if (di == test_dataset_num_elements) { di = 0; ri = 0; }
                else { ri = (ri+1)%number_of_renderers; }
            }
            now1 = time(0);
            if (now1!=now) { update(); now = now1; }

            while (keypressed())
            {
                int k = readkey() >> 8;
                if (k == KEY_ESC || k == KEY_SPACE) go_on = 0;
                if (k == KEY_C) clear(bmp);
            }
        }
    }
    else
    {
        int go_on = 1;
        int i;

        while (go_on)
        {
            for (i=0; i<100; i++)
            {
                int x,y,length;
                reset_x_y();
                reset_str32();

                if (transparent_on) gk_rend_set_text_alpha_color(rends[0],rand_4());
                else gk_rend_set_text_alpha_color(rends[0],0xFF000000|rand_4());
                if (background_on) gk_rend_set_back_color(rends[0],rand_4()&0xFFFFFF);
                if (angle_on) gk_rend_set_angle_in_radians(rends[0],ONE_DEGREE*(rand_4()&0xFF));

                if (random_italic_on)
                    gk_rend_set_italic_angle_in_degrees( rends[0], (double)(rand_4()%(90*1000+1)) / 1000 - 45 );
                else if (fixed_italic)
                    gk_rend_set_italic_angle_in_degrees( rends[0], fixed_italic );

                if (random_bold_on)
                    gk_rend_set_bold_strength( rends[0], rand_4()%601-300 );
                else if (fixed_bold)
                    gk_rend_set_bold_strength( rends[0], fixed_bold );

                gk_render_line_utf32(bmp,rends[0],str32,x,y);
                char_count += length;
            }
            now1 = time(0);
            if (now1!=now) { update(); now = now1; }

            while (keypressed())
            {
                int k = readkey() >> 8;
                if (k == KEY_ESC || k == KEY_SPACE) go_on = 0;
                if (k == KEY_C) clear(bmp);
            }
        }
    }

    while (key[KEY_SPACE] || key[KEY_ESC]) { rest(1); }
    while (!key[KEY_SPACE] && !key[KEY_ESC]) { rest(1); }

    gk_library_cleanup();

    return 0;
}
END_OF_MAIN()
