/*
 * Glyph Keeper benchmark with SDL
 *
 * 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.
 */

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

/* Target library. */
#include <SDL/SDL.h>
#include <SDL/SDL_gfxPrimitives.h>
#include <SDL/SDL_gfxPrimitives_font.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;

SDL_Surface* screen;
SDL_Surface* bmp;

int info_color_r = 128;
int info_color_g = 192;
int info_color_b = 128;
char info_str[200] = "";



void exit_handler()
{
    glyph_keeper_finish();
    SDL_Quit();
}


void screen_message(int x,int y,char* text)
{
    stringRGBA(screen,x,y,text,info_color_r,info_color_g,info_color_b,255);
    SDL_UpdateRect(screen,0,text_y,screen_width,text_y+text_line_height);
}


void screen_rect(int x1,int y1,int x2,int y2)
{
    x1++; x2++;
    boxRGBA(screen,x1,y1,x2,y2,info_color_r,info_color_g,info_color_b,255);
    SDL_UpdateRect(screen,x1,y1,x2-x1+1,y2-y1+1);
}


void update()
{
    int seconds = now1-start_time;
    int minutes = seconds/60;
    int hours;
    seconds -= minutes*60;
    hours = minutes/60;
    minutes -= hours*60;

    /*if (clip_on)
    {*/
        SDL_Rect rect = {0,0,screen_width,screen_height};
        SDL_SetClipRect(bmp,&rect);
    /*}*/
    boxRGBA(bmp,0,0,screen_width-1,area_top-1,0,0,0,255);

    sprintf(info_str,"%02d:%02d:%02d  %ld chars/sec",hours,minutes,seconds,char_count/(now1-start_time));
    stringRGBA(bmp,12,7,info_str,info_color_r,info_color_g,info_color_b,255);
    sprintf(info_str,"glyph cache: %d bytes",gk_keeper_byte_count(keep));
    stringRGBA(bmp,12,19,info_str,info_color_r,info_color_g,info_color_b,255);

    SDL_UpdateRect(bmp,0,0,screen_width,area_top);

    if (clip_on)
    {
        SDL_Rect rect = {screen_width/4,screen_height/4,screen_width/2,screen_height/2};
        SDL_SetClipRect(bmp,&rect);
    }
    else
    {
        SDL_Rect rect = {0,area_top,screen_width,screen_height};
        SDL_SetClipRect(bmp,&rect);
    }

    if (bmp!=screen)
    {
        SDL_BlitSurface(bmp,0,screen,0);
        SDL_UpdateRect(screen,0,0,screen_width,screen_height);
    }
}


int main(int argc,char *argv[])
{
    int go_on = 1;
    SDL_Event event;


    /* Registering exit handler. */
    atexit(exit_handler);

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

    /* Initializing SDL and setting graphics mode. */
    if (SDL_Init(SDL_INIT_VIDEO)<0) { fprintf(logfile,"Can't init SDL\n"); exit(1); }
    screen = SDL_SetVideoMode(screen_width,screen_height,color_depth,SDL_SWSURFACE);
    if (!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_width,screen_height,color_depth,draw_to_screen?"ON":"OFF",clip_on?"ON":"OFF");

    /* Initializing target bitmap. */
    if (draw_to_screen) bmp = screen;
    else
    {
        int rmask = screen->format->Rmask;
        int gmask = screen->format->Gmask;
        int bmask = screen->format->Bmask;
        int amask = screen->format->Amask;
        bmp = SDL_CreateRGBSurface(SDL_SWSURFACE,screen_width,screen_height,32,rmask,gmask,bmask,amask);
        if (!bmp) { fprintf(logfile,"Can't create buffer bitmap\n"); exit(1); }
    }
    if (clip_on)
    {
        SDL_Rect rect = {screen_width/4,screen_height/4,screen_width/2,screen_height/2};
        SDL_SetClipRect(bmp,&rect);
    }
    else
    {
        SDL_Rect rect = {0,0,screen_width,screen_height};
        SDL_SetClipRect(bmp,&rect);
    }



    /* 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)
    {
        boxRGBA(screen,0,0,screen_width-1,screen_height-1,0,0,0,255);
        SDL_UpdateRect(screen,0,0,screen_width,screen_height);
    }
    if (clip_on)
    {
        SDL_Rect rect = {screen_width/4,screen_height/4,screen_width/2,screen_height/2};
        SDL_SetClipRect(bmp,&rect);
    }



    /* Running the benchmark until the ESC or SPACE is hit. */
    if (test_dataset_num_elements > 0)
    {
        int di = 0, ri = 0;
        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 (SDL_PollEvent(&event))
            {
                if (event.type == SDL_KEYDOWN)
                {
                    if (event.key.keysym.sym==SDLK_ESCAPE || event.key.keysym.sym==SDLK_SPACE) go_on = 0;
                    if (event.key.keysym.sym==SDLK_c)
                    {
                        boxRGBA(screen,0,0,screen_width-1,screen_height-1,0,0,0,255);
                        SDL_UpdateRect(screen,0,0,screen_width,screen_height);
                    }
                }
            }
        }
    }
    else
    {
        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 (SDL_PollEvent(&event))
            {
                if (event.type == SDL_KEYDOWN)
                {
                    if (event.key.keysym.sym==SDLK_ESCAPE || event.key.keysym.sym==SDLK_SPACE) go_on = 0;
                    if (event.key.keysym.sym==SDLK_c)
                    {
                        boxRGBA(screen,0,0,screen_width-1,screen_height-1,0,0,0,255);
                        SDL_UpdateRect(screen,0,0,screen_width,screen_height);
                    }
                }
            }
        }
    }


    go_on = 1;
    while (go_on)
    {
        SDL_Delay(10);
        while (SDL_PollEvent(&event))
        {
            if (event.type == SDL_KEYDOWN)
            {
                if (event.key.keysym.sym==SDLK_ESCAPE || event.key.keysym.sym==SDLK_SPACE) go_on = 0;
            }
        }
    }


    return 0;
}
