
#include <stdio.h>
#include <string.h>
#include "app.h"
#include "GenCard.h"

/*
 *  To fit text into a rectangle, first try font start_size (e.g. 56),
 *  then perform a linear search down to stop_size (e.g. 16).
 *
 *  To make this faster, a binary chop should be used.
 *  One day, it may indeed use a binary chop.
 *
 *  After fitting the text, it may be drawn into that rectangle.
 */
int fit_text(Graphics *g, Font **font_vector[3],
		Rect r, int align,
		int start_size, int stop_size,
		char *text, int textbytes, char *textfnt,
		char *flavor, int flavbytes, char *flavfnt,
		int draw_it_too)
{
	int height = r.height;
	int font_size = start_size;
	int min_size, max_size;
	int step;
	Font *fonts[4];

	/* Handle single large mana symbol in text box of land. */
	if ((textbytes <= 2) && (flavor != NULL) && (flavbytes == 0)) {
		if (mana_font != NULL)
		{
			if (draw_it_too) {
				app_set_font(g, mana_font);
				app_draw_text(g, r, ALIGN_CENTRE | VALIGN_CENTRE,
						text, textbytes);
			}
			return font_size;
		}
		else
		{
			/* Load the symbol and draw it centered in the land's rule box. */
			Symbol *sym = code_to_symbol(text, textbytes);
			if (sym) {
				Image *img = load_symbol_image(g->app, sym);
				if (img) {
					if (img->height != 144) {
						Rect ir = app_get_image_area(img);
						Rect scaledr = rect(0,0,144,144);
						Rect dr = app_center_rect(scaledr, r);
						Image *scaled = app_scale_image(img, scaledr, ir);
						if (scaled) {
							if (draw_it_too)
								app_draw_image(g, dr, scaled, ir);
							app_del_image(scaled);
							return 144;
						}
					}
					else {
						Rect ir = app_get_image_area(img);
						Rect dr = app_center_rect(ir, r);
						if (draw_it_too)
							app_draw_image(g, dr, img, ir);
						return 144;
					}
				}
			}
			/* Well, directly loading the symbol image failed. */
			/* Draw the text instead, using fallback fonts. */
			
			fonts[0] = font_vector[0][60]; /* normal_fonts array */
			fonts[1] = font_vector[1][60]; /* italic_fonts array */
			fonts[2] = font_vector[2][60]; /* mana_fonts array */
			fonts[3] = NULL;

			if (draw_it_too)
				style_text(g, fonts, r,
						align | VALIGN_CENTRE | ALIGN_CENTRE,
						text, textbytes, textfnt);
			return 60;
		}
	}

	if (start_size > stop_size)
	{
		/* Find the largest font small enough that'll fit everything. */
		max_size = start_size;
		min_size = stop_size;
		step = -1;
	}
	else if (start_size <= stop_size)
	{
		/* Find the first font small enough that'll fit everything. */
		min_size = start_size;
		max_size = stop_size;
		step = +1;
	}

	while ((min_size <= font_size) && (font_size <= max_size))
	{
		fonts[0] = font_vector[0][font_size]; /* normal_fonts array */
		fonts[1] = font_vector[1][font_size]; /* italic_fonts array */
		fonts[2] = font_vector[2][font_size]; /* mana_fonts array */
		fonts[3] = NULL;

		if (fonts[0] == NULL) /* Skip any missing fonts. */
		{
			font_size += step;
			continue;
		}

		height = text_height(fonts, r.width, text, textbytes, textfnt);
		if (flavbytes)
			height += text_height(fonts, r.width, flavor, flavbytes, flavfnt);
		if (height <= r.height)
			break;
		font_size += step;
	}

	if (font_size <= 35) {
		if (logfile != NULL) {
			fprintf(logfile,
			"\tFont size smaller than recommended (only %d pixels high)\n",
			font_size);
		}
	}

	if (flavbytes && textbytes) {
		height = (r.height - height) / 3;
		if (height >= 0) {
			r.y += height;
			r.height -= height * 2;
		}
	}
	
	if (! draw_it_too)
		return font_size;

	if (flavbytes && textbytes) {
		style_text(g, fonts, r, align | VALIGN_TOP,
				text, textbytes, textfnt);
		style_text(g, fonts, r, align | VALIGN_BOTTOM | ALIGN_CENTRE,
				flavor, flavbytes, flavfnt);
	}
	else if (flavbytes) {
		style_text(g, fonts, r, align | VALIGN_CENTRE | ALIGN_CENTRE,
				flavor, flavbytes, flavfnt);
	}
	else {
		style_text(g, fonts, r, align | VALIGN_CENTRE,
				text, textbytes, textfnt);
	}
	
	return font_size;
}

/*
 * Draw some text into the specified rectangle, narrowing
 * it horizontally as much as necessary until it fits.
 * If it will fit without any narrowing, it is simply drawn
 * into that rectangle, otherwise a temporary image is made
 * of the full size, and that is scaled into the destination.
 */
void narrow_text(Graphics *g, Font **fonts, Rect r, int align,
		char *text, int textbytes, char *textfnt)
{
	Image *img1 = NULL, *img2 = NULL;
	int full_width;
	int draw_directly = 1;
	
	full_width = text_width(fonts, 1500, text, textbytes, textfnt);
	full_width += 2;

	for (; full_width > r.width; full_width = 0) /* do the following once */
	{
		Graphics *g1;
		Rect r1, r2;
		int x, y;
		Colour clear = CLEAR;

		img1 = app_new_image(full_width, r.height, 32);
		if (! img1)
			break;
		for (y = 0; y < r.height; y++)
		{
			for (x = 0; x < full_width; x++)
			{
				img1->data32[y][x] = clear;
			}
		}
		r1 = rect(0, 0, full_width, r.height);
		r2 = rect(0, 0, r.width, r.height);
		g1 = app_get_image_graphics(img1);
		if (! g1)
			break;
		style_text(g1, fonts, r1, align, text, textbytes, textfnt);
		app_del_graphics(g1);
		img2 = app_scale_image(img1, r2, r1);
		if (! img2)
			break;
		if (! app_draw_image(g, r, img2, r2))
			break;
		draw_directly = 0;
		break;
	}
	if (img2)
		app_del_image(img2);
	if (img1)
		app_del_image(img1);
	
	if (draw_directly)
	{
		style_text(g, fonts, r, align, text, textbytes, textfnt);
	}
}
