1/* Hello, Emacs, this is -*-C-*- */ 2 3/* GNUPLOT - estimate.trm */ 4 5/* 6 * This file is included by ../src/term.c via term.h. 7 * 8 * This terminal driver supports: 9 * On return from ENHest_put_text() 10 * (*term)->xmax = estimated string width 11 * (*term)->ymax = estimated string height (in tenths of a character height) 12 * ENHest_plaintext = non-enhanced text approximation of original string 13 * 14 * AUTHORS 15 * 16 * Ethan A Merritt - Dec 2004 17 * 18 */ 19#include "driver.h" 20 21#ifdef TERM_PROTO 22TERM_PUBLIC void ENHest_put_text(unsigned int x, unsigned int y, const char str[]); 23TERM_PUBLIC void ENHest_OPEN(char * fontname, double fontsize, double base, 24 TBOOLEAN widthflag, TBOOLEAN showflag, int overprint); 25TERM_PUBLIC void ENHest_FLUSH(void); 26#endif /* TERM_PROTO */ 27 28#ifdef TERM_BODY 29 30static double ENHest_x, ENHest_y; 31static double ENHest_xsave, ENHest_ysave; 32static double ENHest_fragment_width; 33static double ENHest_fontsize; 34static double ENHest_min_height, ENHest_max_height; 35static double ENHest_total_width; 36static char *ENHest_plaintext = NULL; 37static int ENHest_plaintext_buflen = 0; 38static int ENHest_plaintext_pos = 0; 39 40static TBOOLEAN ENHest_opened_string; 41static TBOOLEAN ENHest_show = TRUE; 42static int ENHest_overprint = 0; 43static TBOOLEAN ENHest_widthflag = TRUE; 44#define ENHest_font "" 45static double ENHest_base; 46 47/* Internal routines for UTF-8 support */ 48static size_t strwidth_utf8(const char *s); 49 50TERM_PUBLIC void 51ENHest_OPEN( 52 char *fontname, 53 double fontsize, double base, 54 TBOOLEAN widthflag, TBOOLEAN showflag, 55 int overprint) 56{ 57 /* There are two special cases: 58 * overprint = 3 means save current position 59 * overprint = 4 means restore saved position 60 */ 61 if (overprint == 3) { 62 ENHest_xsave = ENHest_x; 63 ENHest_ysave = ENHest_y; 64 return; 65 } else if (overprint == 4) { 66 ENHest_x = ENHest_xsave; 67 ENHest_y = ENHest_ysave; 68 return; 69 } 70 71 if (!ENHest_opened_string) { 72 ENHest_opened_string = TRUE; 73 /* Start new text fragment */ 74 ENHest_fragment_width = 0; 75 /* font size will be used to estimate width of each character */ 76 ENHest_fontsize = fontsize > 2.0 ? 1.0 : fontsize; 77 /* Scale fractional font height */ 78 ENHest_base = base * 1.0; 79 if (ENHest_max_height < ENHest_base+1.0*fontsize) 80 ENHest_max_height = ENHest_base+1.0*fontsize; 81 if (ENHest_min_height > ENHest_base) 82 ENHest_min_height = ENHest_base; 83 FPRINTF((stderr,"ENHest_OPEN: base %g fontsize %g min %g max %g\n", 84 base,fontsize,ENHest_min_height,ENHest_max_height)); 85 /* Keep track of whether we are supposed to show this string */ 86 ENHest_show = showflag; 87 /* 0/1/2 no overprint / 1st pass / 2nd pass */ 88 ENHest_overprint = overprint; 89 /* widthflag FALSE means do not update text position after printing */ 90 ENHest_widthflag = widthflag; 91 } 92} 93 94TERM_PUBLIC void 95ENHest_FLUSH() 96{ 97 double len = ENHest_fragment_width; 98 99 if (ENHest_opened_string) { 100 ENHest_fragment_width = 0; 101 102 if (!ENHest_widthflag) 103 /* don't update position */ 104 ; 105 else if (ENHest_overprint == 1) 106 /* First pass of overprint, leave position in center of fragment */ 107 ENHest_x += len / 2; 108 else 109 /* Normal case is to update position to end of fragment */ 110 ENHest_x += len; 111 112 ENHest_total_width = GPMAX(ENHest_total_width, ENHest_x); 113 ENHest_opened_string = FALSE; 114 } 115} 116 117TERM_PUBLIC void 118ENHest_put_text(unsigned int x, unsigned int y, const char *str) 119{ 120 /* Set up global variables needed by enhanced_recursion() */ 121 ENHest_fontsize = 1.0; 122 ENHest_opened_string = FALSE; 123 ENHest_max_height = 1.0; 124 ENHest_min_height = 0.0; 125 ENHest_total_width = 0.0; 126 strncpy(enhanced_escape_format,".",sizeof(enhanced_escape_format)); 127 128 /* buffer in which we will return plaintext version of enhanced text string */ 129 while (ENHest_plaintext_buflen <= strlen(str)) { 130 ENHest_plaintext_buflen += MAX_ID_LEN; 131 ENHest_plaintext = gp_realloc(ENHest_plaintext, ENHest_plaintext_buflen+1, "ENHest_plaintext"); 132 } 133 ENHest_plaintext[0] = '\0'; 134 ENHest_plaintext_pos = 0; 135 136 /* If no enhanced text processing is needed, strlen() is sufficient */ 137 if (ignore_enhanced_text || (!strpbrk(str, "{}^_@&~\n") && !contains_unicode(str))) { 138 if (encoding == S_ENC_UTF8) 139 term->xmax = strwidth_utf8(str); 140 else 141 term->xmax = strlen(str); 142 term->ymax = 10; 143 strcpy(ENHest_plaintext, str); 144 return; 145 } 146 147 ENHest_x = x; 148 ENHest_y = y; 149 150 while (*(str = enhanced_recursion((char *)str, TRUE, 151 ENHest_font, ENHest_fontsize, 152 0.0, TRUE, TRUE, 0))) { 153 (term->enhanced_flush)(); 154 155 enh_err_check(str); 156 if (!*++str) 157 break; /* end of string */ 158 } 159 160 ENHest_plaintext[ENHest_plaintext_pos] = '\0'; 161 if (ENHest_x > 0.0 && ENHest_x < 1.0) 162 ENHest_x = 1; 163 term->xmax = ENHest_total_width; 164 term->ymax = 10. * (ENHest_max_height - ENHest_min_height) + 0.5; 165} 166 167TERM_PUBLIC void 168ENHest_writec(int c) 169{ 170 if (c == '\n') { 171 ENHest_FLUSH(); 172 ENHest_opened_string = TRUE; 173 ENHest_min_height -= 1.0 * ENHest_fontsize; 174 ENHest_base -= 1.0 * ENHest_fontsize; 175 ENHest_x = 0; 176 } 177 178 if (encoding == S_ENC_UTF8) { 179 /* Skip all but the first byte of UTF-8 multi-byte characters. */ 180 if ((c & 0xc0) != 0x80) { 181 ENHest_fragment_width += ENHest_fontsize; 182 /* [most] characters above 0x3000 are square CJK glyphs, */ 183 /* which are wider than western characters. */ 184 if ((unsigned char)c >= 0xec) 185 ENHest_fragment_width += ENHest_fontsize; 186 } 187 } else 188 ENHest_fragment_width += ENHest_fontsize; 189 190 ENHest_plaintext[ENHest_plaintext_pos++] = c; 191} 192 193/* 194 * This routine accounts for multi-byte characters in UTF-8. 195 * NB: It does not return the _number_ of characters in the string, but 196 * rather their approximate _width_ in units of typical character width. 197 * As with the ENHest_writec() routine, it approximates the width of characters 198 * above unicode 0x3000 as being twice that of western alphabetic characters. 199 */ 200size_t strwidth_utf8(const char *s) { 201 int i = 0, j = 0; 202 while (s[i]) { 203 if ((s[i] & 0xc0) != 0x80) { 204 j++; 205 if ((unsigned char)(s[i]) >= 0xe3) 206 j++; 207 } 208 i++; 209 } 210 return j; 211} 212 213 214static struct termentry ENHest = { 215 "estimate", NULL, 216 1, 1, 1, 1, 1, 1, 217 NULL, NULL, NULL, 218 NULL, NULL, NULL, NULL, NULL, 219 NULL, ENHest_put_text, NULL, 220 NULL, NULL, NULL, NULL, 221 0, 0, /* pointsize, flags */ 222 NULL, NULL, NULL, NULL 223#ifdef USE_MOUSE 224 , NULL, NULL, NULL, NULL, NULL 225#endif 226 , NULL, NULL, NULL, NULL 227 , NULL 228 , ENHest_OPEN, ENHest_FLUSH, ENHest_writec 229}; 230 231#endif /* TERM_BODY */ 232