Index: gd.c =================================================================== RCS file: /repository/php-src/ext/gd/gd.c,v retrieving revision 1.221.2.46 diff -u -r1.221.2.46 gd.c --- gd.c 2 Nov 2004 16:42:13 -0000 1.221.2.46 +++ gd.c 6 Nov 2004 05:47:45 -0000 @@ -3322,6 +3322,173 @@ } /* }}} */ +T1_OUTLINE* php_T1_GetLineOutline( T1_OUTLINE *str_path, int length, float size, float position, float thickness ) +{ + T1_PATHSEGMENT *head; + T1_PATHSEGMENT *line_path; + T1_PATHSEGMENT *path; + int starty=0; + int endy=0; + + /* I'm not too sure about these calculations. + Why 72/2? + 72 because t1libs DEFAULT_RES is 72. + Divide by 2 because it worked better for me + + */ + starty = (-1) * (int) floor( (position-0.5*thickness) * size + 0.5 ) * (72.0*0.5); + endy = starty - (int) floor(thickness*size+0.5) * (72.0*0.5); + + head = line_path = (T1_PATHSEGMENT *) malloc(sizeof(T1_PATHSEGMENT)); + memset(line_path, 0, sizeof(T1_PATHSEGMENT)); + line_path->type = T1_PATHTYPE_MOVE; + line_path->link = (T1_PATHSEGMENT *)NULL; + line_path->references = 0; + line_path->dest.x = -length; + line_path->dest.y = starty; + line_path->size = sizeof(T1_PATHSEGMENT); + + path = line_path; + line_path = (T1_PATHSEGMENT *) malloc(sizeof(T1_PATHSEGMENT)); + path->link = line_path; + memset(line_path, 0, sizeof(T1_PATHSEGMENT)); + line_path->type = T1_PATHTYPE_LINE; + line_path->link = (T1_PATHSEGMENT *)NULL; + line_path->references = 0; + line_path->dest.x = length; + line_path->dest.y = 0; + line_path->size = sizeof(T1_PATHSEGMENT); + + path = line_path; + line_path = (T1_PATHSEGMENT *) malloc(sizeof(T1_PATHSEGMENT)); + path->link = line_path; + memset(line_path, 0, sizeof(T1_PATHSEGMENT)); + line_path->type = T1_PATHTYPE_LINE; + line_path->link = (T1_PATHSEGMENT *)NULL; + line_path->references = 1; + line_path->dest.x = 0; + line_path->dest.y = endy - starty; + line_path->size = sizeof(T1_PATHSEGMENT); + + path = line_path; + line_path = (T1_PATHSEGMENT *) malloc(sizeof(T1_PATHSEGMENT)); + path->link = line_path; + memset(line_path, 0, sizeof(T1_PATHSEGMENT)); + line_path->type = T1_PATHTYPE_LINE; + line_path->link = (T1_PATHSEGMENT *)NULL; + line_path->references = 1; + line_path->dest.x = -length; + line_path->dest.y = 0; + line_path->size = sizeof(T1_PATHSEGMENT); + + path = line_path; + line_path = (T1_PATHSEGMENT *) malloc(sizeof(T1_PATHSEGMENT)); + path->link = line_path; + memset(line_path, 0, sizeof(T1_PATHSEGMENT)); + line_path->flag = 64; + line_path->type = T1_PATHTYPE_LINE; + line_path->link = (T1_PATHSEGMENT *)NULL; + line_path->last = (T1_PATHSEGMENT *)NULL; + line_path->references = 1; + line_path->dest.x = 0; + line_path->dest.y = starty-endy; + line_path->size = sizeof(T1_PATHSEGMENT); + + path = line_path; + line_path = (T1_PATHSEGMENT *) malloc(sizeof(T1_PATHSEGMENT)); + path->link = line_path; + memset(line_path, 0, sizeof(T1_PATHSEGMENT)); + line_path->type = T1_PATHTYPE_MOVE; + line_path->link = (T1_PATHSEGMENT *)NULL; + line_path->last = (T1_PATHSEGMENT *)NULL; + line_path->references = 1; + line_path->dest.x = length; + line_path->dest.y = -starty; + line_path->size = sizeof(T1_PATHSEGMENT); + + head->last = line_path; + head->flag = str_path->flag; /* hack to "close" the path */ + + str_path = T1_ConcatOutlines(str_path, (T1_OUTLINE *)head); + + return str_path; +} + +int php_gdgetcontrolsequence( char *str, int len, float *var ) +{ + int ret; + char *ptr, *ptr2; + float f=0.0; + + if( *str != 27 ) + return -1; + + switch( str[1] ) + { + case 'u': + /* toggle underlining */ + return 1; + case 'i': + /* change slope (italic) */ + ret = 2; + break; + case 'w': + /* change weight (bold) (not implemented, hard) */ + ret = 3; + break; + case 'c': + /* change color (not implemented, possible) */ + ret = 4; + break; + case 'x': + /* move in X-direction (not implemented, should be easy) */ + ret = 5; + break; + case 'y': + /* move in Y-direction (not implemented, should be easy) */ + ret = 6; + break; + case 's': + /* change size */ + ret = 7; + break; + case 'f': + /* font (not implemented, tricky) */ + ret = 8; + break; + case 'a': + /* change angle */ + ret = 9; + break; + case 't': + /* change spacing (tracking, tightness) */ + ret = 10; + break; + case 'e': + /* set condense (extension) */ + ret = 11; + break; + default: + return -1; + } + + ptr = str + 2; + ptr2 = ptr; + while( *ptr!='\0' && *ptr!=';' && len>0 ) { + ptr++; + len--; + } + if( *ptr == ';' ) + { + *ptr = '\0'; + f = atof( ptr2 ); + *var = f; + *ptr = ';'; + } + + return ret; +} + /* {{{ proto array imagepstext(int image, string text, int font, int size, int xcoord, int ycoord [, int space, int tightness, float angle, int antialias]) Rasterize a string over an image */ PHP_FUNCTION(imagepstext) @@ -3346,6 +3513,10 @@ char *str; int str_len; int argc = ZEND_NUM_ARGS(); + int underline_length, min_ux, max_ux; + float control_var; + float size; + int cmd; if (argc != 8 && argc != 12) { ZEND_WRONG_PARAM_COUNT(); @@ -3425,17 +3596,99 @@ } if (width) { - extend = T1_GetExtend(*f_ind); - str_path = T1_GetCharOutline(*f_ind, str[0], size, transform); - + if( str_len==0 ) { + str_path = T1_GetCharOutline(*f_ind, str[0], size, transform); if (!str_path) { if (T1_errno) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "libt1 returned error %d", T1_errno); } RETURN_FALSE; } + } else { + extend = T1_GetExtend(*f_ind); + str_path = NULL; for (i = 1; i < str_len; i++) { + if( _str[i] == (char) 27 ) { + cmd = php_gdgetcontrolsequence( _str + i, len-i-1, &control_var ); + if( cmd == -1 ) { + continue; + } + /* skip i past the control sequence */ + while( _str[i] != ';' && _str[i] != '\0' ) { + i++; + } + if( _str[i] == '\0' ) { + continue; + } + switch( cmd ) { + case 1: /* underlining */ + if( mod_flag & T1_UNDERLINE ) { + mod_flag &= ~T1_UNDERLINE; + underline_length = 0; + while( underline_path != NULL && underline_path->type == T1_PATHTYPE_MOVE ) { + underline_path=underline_path->link; + } + min_ux = 0; + max_ux = 0; + while( underline_path != NULL ) { + underline_length+=underline_path->dest.x; + min_ux = min_ux < underline_length ? min_ux : underline_length; + max_ux = max_ux > underline_length ? max_ux : underline_length; + underline_path=underline_path->link; + } + underline_length = max_ux - min_ux; + if( str_path == (T1_OUTLINE *)NULL ) { + continue; + } + str_path = php_T1_GetLineOutline(str_path, underline_length, size, T1_GetUnderlinePosition(*f_ind), T1_GetUnderlineThickness(*f_ind)); + + } else { + mod_flag |= T1_UNDERLINE; + if( str_path != (T1_OUTLINE *)NULL ) + underline_path = str_path->last; + } + break; + case 2: /* change slope (italic) */ + slant = control_var; + T1_DeleteAllSizes( *f_ind ); + T1_SlantFont( *f_ind, slant ); + break; + case 3: /* change weight (bold) */ + break; + case 4: /* change color */ + break; + case 5: /* move x */ + break; + case 6: /* move y */ + break; + case 7: /* set size */ + size = control_var; + break; + case 8: /* set font */ + break; + case 9: /* change angle */ + angle = control_var; + transform = T1_RotateMatrix(NULL, angle); + break; + case 10: /* change spacing (tracking) */ + width = control_var; + break; + case 11: /* set condense (extension) */ + extend = control_var; + T1_DeleteAllSizes( *f_ind ); + T1_ExtendFont( *f_ind, extend ); + break; + } + continue; + } + if( str_path == NULL ) { + str_path = T1_GetCharOutline(*f_ind, _str[i], size, transform); + if( mod_flag & T1_UNDERLINE ) { + underline_path = str_path; + } + continue; + } amount_kern = (int) T1_GetKerning(*f_ind, str[i-1], str[i]); amount_kern += str[i-1] == ' ' ? space : 0; add_width = (int) (amount_kern+width)/extend;