/* Hello, Emacs, this is -*-C-*- * $Id: estimate.trm,v 1.13 2015/07/08 17:47:04 sfeam Exp $ * */ /* 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 * (*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 __PROTO((unsigned int x, unsigned int y, const char str[])); TERM_PUBLIC void ENHest_OPEN __PROTO((char * fontname, double fontsize, double base, TBOOLEAN widthflag, TBOOLEAN showflag, int overprint)); TERM_PUBLIC void ENHest_FLUSH __PROTO((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 __PROTO((const char *s)); 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 > 2.0 ? 1.0 : fontsize; /* Scale fractional font height */ ENHest_base = base * 1.0; if (ENHest_max_height < ENHest_base+1.0*fontsize) ENHest_max_height = ENHest_base+1.0*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 = 1.0; ENHest_opened_string = FALSE; ENHest_max_height = 1.0; 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 <= strlen(str)) { ENHest_plaintext_buflen += MAX_ID_LEN; ENHest_plaintext = gp_realloc(ENHest_plaintext, ENHest_plaintext_buflen+1, "ENHest_plaintext"); } ENHest_plaintext[0] = '\0'; ENHest_plaintext_pos = 0; /* If no enhanced text processing is needed, strlen() is sufficient */ if (ignore_enhanced_text || !strpbrk(str, "{}^_@&~\n")) { if (encoding == S_ENC_UTF8) term->xmax = strwidth_utf8(str); else term->xmax = strlen(str); term->ymax = 10; 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) + 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 += ENHest_fontsize; /* [most] characters above 0x3000 are square CJK glyphs, */ /* which are wider than western characters. */ if ((unsigned int)c >= 0xec) ENHest_fragment_width += ENHest_fontsize; } } else ENHest_fragment_width += ENHest_fontsize; 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 */