/* Hello, Emacs, this is -*-C-*- */
/* GNUPLOT - estimate.trm */
/*
* This file is included by ../src/term.c via term.h.
*
* This terminal driver supports:
* On return from ENHest_put_text()
* (*term)->xmax = estimated string width in characters
* (*term)->ymax = estimated string height (in tenths of a character height)
* ENHest_plaintext = non-enhanced text approximation of original string
*
* AUTHORS
*
* Ethan A Merritt - Dec 2004
*
*/
#include "driver.h"
#ifdef TERM_PROTO
TERM_PUBLIC void ENHest_put_text(unsigned int x, unsigned int y, const char str[]);
TERM_PUBLIC void ENHest_OPEN(char * fontname, double fontsize, double base,
TBOOLEAN widthflag, TBOOLEAN showflag, int overprint);
TERM_PUBLIC void ENHest_FLUSH(void);
#endif /* TERM_PROTO */
#ifdef TERM_BODY
static double ENHest_x, ENHest_y;
static double ENHest_xsave, ENHest_ysave;
static double ENHest_fragment_width;
static double ENHest_fontsize;
static double ENHest_min_height, ENHest_max_height;
static double ENHest_total_width;
static char *ENHest_plaintext = NULL;
static int ENHest_plaintext_buflen = 0;
static int ENHest_plaintext_pos = 0;
static TBOOLEAN ENHest_opened_string;
static TBOOLEAN ENHest_show = TRUE;
static int ENHest_overprint = 0;
static TBOOLEAN ENHest_widthflag = TRUE;
#define ENHest_font ""
static double ENHest_base;
/* Internal routines for UTF-8 support */
static size_t strwidth_utf8(const char *s);
/* DEBUG */
/* place holder for an estimate of the current font size at the time
* we switched from a "real" terminal to this special-purpose terminal.
*/
#define ENHest_ORIG_FONTSIZE 12.
TERM_PUBLIC void
ENHest_OPEN(
char *fontname,
double fontsize, double base,
TBOOLEAN widthflag, TBOOLEAN showflag,
int overprint)
{
/* There are two special cases:
* overprint = 3 means save current position
* overprint = 4 means restore saved position
*/
if (overprint == 3) {
ENHest_xsave = ENHest_x;
ENHest_ysave = ENHest_y;
return;
} else if (overprint == 4) {
ENHest_x = ENHest_xsave;
ENHest_y = ENHest_ysave;
return;
}
if (!ENHest_opened_string) {
ENHest_opened_string = TRUE;
/* Start new text fragment */
ENHest_fragment_width = 0;
/* font size will be used to estimate width of each character */
ENHest_fontsize = fontsize;
/* Scale fractional font height */
ENHest_base = base * 1.0;
if (ENHest_max_height < ENHest_base + fontsize)
ENHest_max_height = ENHest_base + fontsize;
if (ENHest_min_height > ENHest_base)
ENHest_min_height = ENHest_base;
FPRINTF((stderr,"ENHest_OPEN: base %g fontsize %g min %g max %g\n",
base,fontsize,ENHest_min_height,ENHest_max_height));
/* Keep track of whether we are supposed to show this string */
ENHest_show = showflag;
/* 0/1/2 no overprint / 1st pass / 2nd pass */
ENHest_overprint = overprint;
/* widthflag FALSE means do not update text position after printing */
ENHest_widthflag = widthflag;
}
}
TERM_PUBLIC void
ENHest_FLUSH()
{
double len = ENHest_fragment_width;
if (ENHest_opened_string) {
ENHest_fragment_width = 0;
if (!ENHest_widthflag)
/* don't update position */
;
else if (ENHest_overprint == 1)
/* First pass of overprint, leave position in center of fragment */
ENHest_x += len / 2;
else
/* Normal case is to update position to end of fragment */
ENHest_x += len;
ENHest_total_width = GPMAX(ENHest_total_width, ENHest_x);
ENHest_opened_string = FALSE;
}
}
TERM_PUBLIC void
ENHest_put_text(unsigned int x, unsigned int y, const char *str)
{
/* Set up global variables needed by enhanced_recursion() */
ENHest_fontsize = ENHest_ORIG_FONTSIZE;
ENHest_opened_string = FALSE;
ENHest_max_height = ENHest_fontsize;
ENHest_min_height = 0.0;
ENHest_total_width = 0.0;
strncpy(enhanced_escape_format,".",sizeof(enhanced_escape_format));
/* buffer in which we will return plaintext version of enhanced text string */
while (ENHest_plaintext_buflen xmax = strwidth_utf8(str);
else
term->xmax = strlen(str);
term->ymax = 10; /* 1 character height */
strcpy(ENHest_plaintext, str);
return;
}
ENHest_x = x;
ENHest_y = y;
while (*(str = enhanced_recursion((char *)str, TRUE,
ENHest_font, ENHest_fontsize,
0.0, TRUE, TRUE, 0))) {
(term->enhanced_flush)();
enh_err_check(str);
if (!*++str)
break; /* end of string */
}
ENHest_plaintext[ENHest_plaintext_pos] = '\0';
if (ENHest_x > 0.0 && ENHest_x < 1.0)
ENHest_x = 1;
term->xmax = ENHest_total_width;
term->ymax = 10. * (ENHest_max_height - ENHest_min_height)/ENHest_ORIG_FONTSIZE + 0.5;
}
TERM_PUBLIC void
ENHest_writec(int c)
{
if (c == '\n') {
ENHest_FLUSH();
ENHest_opened_string = TRUE;
ENHest_min_height -= 1.0 * ENHest_fontsize;
ENHest_base -= 1.0 * ENHest_fontsize;
ENHest_x = 0;
}
if (encoding == S_ENC_UTF8) {
/* Skip all but the first byte of UTF-8 multi-byte characters. */
if ((c & 0xc0) != 0x80) {
ENHest_fragment_width += 1;
/* [most] characters above 0x3000 are square CJK glyphs, */
/* which are wider than western characters. */
if ((unsigned char)c >= 0xec)
ENHest_fragment_width += 1;
}
} else
ENHest_fragment_width += 1;
ENHest_plaintext[ENHest_plaintext_pos++] = c;
}
/*
* This routine accounts for multi-byte characters in UTF-8.
* NB: It does not return the _number_ of characters in the string, but
* rather their approximate _width_ in units of typical character width.
* As with the ENHest_writec() routine, it approximates the width of characters
* above unicode 0x3000 as being twice that of western alphabetic characters.
*/
size_t strwidth_utf8(const char *s) {
int i = 0, j = 0;
while (s[i]) {
if ((s[i] & 0xc0) != 0x80) {
j++;
if ((unsigned char)(s[i]) >= 0xe3)
j++;
}
i++;
}
return j;
}
static struct termentry ENHest = {
"estimate", NULL,
1, 1, 1, 1, 1, 1,
NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, ENHest_put_text, NULL,
NULL, NULL, NULL, NULL,
0, 0, /* pointsize, flags */
NULL, NULL, NULL, NULL
#ifdef USE_MOUSE
, NULL, NULL, NULL, NULL, NULL
#endif
, NULL, NULL, NULL, NULL
, NULL
, ENHest_OPEN, ENHest_FLUSH, ENHest_writec
};
#endif /* TERM_BODY */