Пример #1
0
/*
	Draw the next word in s on screen. We stop at the next white space character.

	We return the number of characters in the word.
	If the word did not fit in the given width, we return 0.
	
	If the variable cnt is not NULL, we do NOT draw the text, but simply count the width in pixels
	that we would draw and store the result in *cnt.
	If the word does not fit completely, cnt is returned as greater than width.
	If we are already at a whitespace character, we draw only this character.
*/
static int
draw_text_word(char *s, int start_row, int start_col, int width, int fg_col, int bg_col, int *cnt){
	int c=0;	
	char ch;	
	int n=0;
	
	while ( (ch = *s++) ){
		
		/* can we put the next character on the line ? */
		if ( c + char_width(ch) <= width ){
			
			/* draw this character */
			if (NULL == cnt)  draw_char(start_row, start_col + c, ch, fg_col, bg_col, width - c );
			
			c += (char_width(ch) + ic_space);
			n++;
			
			if ( ('\0' == *s) || is_whitespace(*s) ){
				/* This word did fit completely */
				break;
			}
		} else {
			/* This word did not fit completely */
			c = width + 1;
			n = 0;
			break;
		};
	};
	
	if (NULL != cnt)
		*cnt = c;
	return n;
};
Пример #2
0
void pdf_out_char (internal_font_number f, ASCII_code c)
{
  pdf_rect rect;
  char cbuf[2];
  cbuf[0] = c;
  cbuf[1] = 0;
  pdf_dev_set_string(cur_h, -cur_v, cbuf, 1, char_width(f, char_info(f, c)), font_id[f], 1);
  pdf_dev_set_rect(&rect, cur_h, -cur_v, char_width(f, char_info(f, c)),
      char_height(f, height_depth(char_info(f, c))),
      char_depth(f, height_depth(char_info(f, c))));
  pdf_doc_expand_box(&rect);
}
Пример #3
0
void tex::make_accent ()
	{
	fnt	f;
	qcell	i;
	ptr	p, q, r;
	scal	a, h, w, x;
	float	s, t;
	scal	delta;

	scan_char_num();
	f = cur_font;
	p = new_character(f, cur_val);
	if (p != null) {
		x = x_height(f);
		s = (float) slant(f) / 65536.0;
		a = char_width(f, char_info(f, character(p)));
		do_assignments();
		q = null;
		f = cur_font;
		if (cur_cmd == LETTER
		|| cur_cmd == OTHER_CHAR
		|| cur_cmd ==  CHAR_GIVEN) {
			q = new_character(f, cur_chr);
		} else if (cur_cmd ==  CHAR_NUM) {
			scan_char_num();
			q = new_character(f, cur_val);
		} else {
			back_input();
		}
		if (q != null) {
			t = (float) slant(f) / 65536.0;
			i = char_info(f, character(q));
			w = char_width(f, i); 
			h = char_height(f, height_depth(i));
			if (h != x) {
				p = hpack(p, 0, ADDITIONAL);
				shift_amount(p) = x - h;
			}
			delta = round((float) (w - a) / 2.0 + h * t - x * s);
			r = new_kern(delta);
			subtype(r) = ACC_KERN;
			link(tail) = r;
			link(r) = p;
			tail = new_kern(-a - delta);
			subtype(tail) = ACC_KERN;
			link(p) = tail;
			p = q;
		}
		tail_append(p);
		space_factor = 1000;
		}
	}
Пример #4
0
void    GLUI_List::draw_text(const char *t, int selected, int x, int y )
{
  int text_x, i, x_pos;
  int box_width;

  GLUI_DRAWINGSENTINAL_IDIOM

  /** Find where to draw the text **/

  text_x = 2 + GLUI_LIST_BOXINNERMARGINX;

  /** Draw selection area dark **/
  if ( enabled && selected ) {
    glColor3f( 0.0f, 0.0f, .6f );
    glBegin( GL_QUADS );
    glVertex2i(text_x, y+5 );    glVertex2i( w-text_x, y+5 );
    glVertex2i(w-text_x, y+19 );    glVertex2i(text_x, y+19 );
    glEnd();
  }
  box_width = get_box_width();   

  if ( !selected || !enabled ) {   /* No current selection */
    x_pos = text_x;                /*  or control disabled */
    if ( enabled )
      glColor3b( 0, 0, 0 );
    else
      glColor3b( 32, 32, 32 );
    
    glRasterPos2i( text_x, y+15);
    i = 0;
    while( t[i] != '\0' && substring_width(t,0,i) < box_width) {
      glutBitmapCharacter( get_font(), t[i] );
      x_pos += char_width( t[i] );
      i++;
    }
  }
  else { /* There is a selection */
    i = 0;
    x_pos = text_x;
    glColor3f( 1., 1., 1. );
    glRasterPos2i( text_x, y+15);
    while( t[i] != '\0' && substring_width(t,0,i) < box_width) {
      glutBitmapCharacter( get_font(), t[i] );
      x_pos += char_width( t[i] );
      i++;
    }
  }
}
Пример #5
0
uint8_t 
draw_char(uint8_t start_row, uint8_t start_col, unsigned char ch, uint8_t fg_col, uint8_t bg_col, uint8_t width) {
	unsigned int w;
	unsigned int i, cpos, cnt;
	uint8 res = 0;
	
	// NOTE maybe print a ? or something
	if (ch > max_char) return 1;	/* We print nothing, character not encoded */
	
	cpos = char_pos[ch];		// Start of glyph bits in font_bits[]
	
	w = char_width(ch);		// Width of the character without inter character space
	if (w > width) w = width;	// w is now min(char_width(ch), width)

	// draw w columns into drawbuf
	// each column is copied (with correct color) to drawbuf directly from font_bits
	for (cnt = 0; cnt < w; cnt++, cpos+=bytes_per_col)
		store_buf(cnt, font_bits[cpos] | (font_bits[cpos+1] << 8), fg_col, bg_col);
	if ( (width - cnt) >= ic_space ){
		for (i=0; i<ic_space; i++)
			store_buf(cnt++, 0, fg_col, bg_col);		// inter character space
		res = cnt;
	};
	write_buf(start_row, start_col, cnt, font_height);
	return res;	
}
Пример #6
0
int wrap(const char *input, int max_width, char *output, int max_length) {
    *output = '\0';
    char *text = malloc(sizeof(char) * (strlen(input) + 1));
    strcpy(text, input);
    int space_width = char_width(' ');
    int line_number = 0;
    char *key1, *key2;
    char *line = tokenize(text, "\r\n", &key1);
    while (line) {
        int line_width = 0;
        char *token = tokenize(line, " ", &key2);
        while (token) {
            int token_width = string_width(token);
            if (line_width) {
                if (line_width + token_width > max_width) {
                    line_width = 0;
                    line_number++;
                    strncat(output, "\n", max_length);
                }
                else {
                    strncat(output, " ", max_length);
                }
            }
            strncat(output, token, max_length);
            line_width += token_width + space_width;
            token = tokenize(NULL, " ", &key2);
        }
        line_number++;
        strncat(output, "\n", max_length);
        line = tokenize(NULL, "\r\n", &key1);
    }
    free(text);
    return line_number;
}
Пример #7
0
int string_width(const char *input) {
    int result = 0;
    int length = strlen(input);
    for (int i = 0; i < length; i++) {
        result += char_width(input[i]);
    }
    return result;
}
Пример #8
0
/******************************** GLUI_List::substring_width() *********/
int  GLUI_List::substring_width( const char *t, int start, int end )
{
  int i, width;

  width = 0;

  for( i=start; i<=end; i++ )
    width += char_width( t[i] ); 

  return width;
}
Пример #9
0
int  GLUI_EditText::substring_width( int start, int end )
{
  int i, width;

  width = 0;

  for( i=start; i<=end; i++ )
    width += char_width( text[i] ); 

  return width;
}
Пример #10
0
/**
 * convert a str into text ( for listbox )
 * width is the available width of a line in pixels
 */
Text* create_text( struct _Font *fnt, const char *orig_str, int width )
{
    struct TextData td;
    const char *line_start = orig_str;
    const char *head = orig_str;
    const char *committed = orig_str;
    int cumulated_width = 0;	/* width of text in this line */
    int break_line = 0;
    if (width < 0) width = 0;

    memset(&td, 0, sizeof(td));
    td.text = calloc ( 1, sizeof( Text ) );

    while (*committed) {
        int ch_width = char_width(fnt, *head);

        if (committed != head && text_is_linebreak(head[-1]))
            break_line = 1;
        else if (cumulated_width > width) {
            /* if the word is too long to fit into one line,
             * force a line break at the current position.
             */
            if (committed == line_start)
                /* take away last char (unless only one) and break there */
                committed = head - (head - 1 != line_start);
            head = committed;
            break_line = 1;
        }
        else if (text_is_breakable(committed, head))
            committed = head;

        if (!break_line) {
            cumulated_width += ch_width;
            head++;
        }

        if (!*head) break_line = 1;

        if (break_line) {
            text_add_line(&td, line_start, head);
            line_start = committed = head;
            cumulated_width = 0;
            break_line = 0;
        }
    }

    if (!td.text->lines) text_add_line(&td, "", "" + 1);

    return td.text;
}
Пример #11
0
/* 
	Given a character position, returns the corresponding start column at which the character would be drawn.
	Is used by cursor drawing routine.
*/
uint8_t
char_start_col(char *txt, int pos){ 
	unsigned char ch;
	unsigned int i, w = 0, cpos;
	
	for (i = 0; i < pos; i++){
		ch = txt[i];
		
		if (ch <= max_char){ 
			cpos = char_pos[ch];		// Start of glyph bits in font_bits[]
			w += char_width(ch) + ic_space;
		};
	};
	return w;
};
Пример #12
0
void     GLUI_EditText::draw_insertion_pt( void )
{
  int curr_x, i;

  if ( NOT can_draw() )
    return;

  /*** Don't draw insertion pt if control is disabled ***/
  if ( NOT enabled )
    return;

  if ( debug )    dump( stdout, "-> DRAW_INS_PT" );

  if ( sel_start != sel_end OR insertion_pt < 0 ) {
    return;  /* Don't draw insertion point if there is a current selection */
  }

  /*    printf( "insertion pt: %d\n", insertion_pt );              */

  curr_x = this->x_abs + text_x_offset 
    + substring_width( substring_start, substring_end )
    + 2                             /* The edittext box has a 2-pixel margin */
    + GLUI_EDITTEXT_BOXINNERMARGINX;   /** plus this many pixels blank space
					 between the text and the box       **/

  for( i=substring_end; i>=insertion_pt; i-- ) {
    curr_x -= char_width( text[i] ); 
  }  

  glColor3f( 0.0, 0.0, 0.0 );
  glBegin( GL_LINE_LOOP );
  /***
    glVertex2i( curr_x, y_abs + 4 );
    glVertex2i( curr_x, y_abs + 4 );
    glVertex2i( curr_x, y_abs + h - 3 );
    glVertex2i( curr_x, y_abs + h - 3 );
    ***/
  curr_x -= x_abs;
  glVertex2i( curr_x, 0 + 4 );
  glVertex2i( curr_x, 0 + 4 );
  glVertex2i( curr_x, 0 + h - 3 );
  glVertex2i( curr_x, 0 + h - 3 );
  glEnd();

  if ( debug )    dump( stdout, "-> DRAW_INS_PT" );
}
Пример #13
0
/******************************** GLUI_TextBox::substring_width() *********/
int  GLUI_TextBox::substring_width( int start, int end, int initial_width )
{
  // This function only works properly if start is really the start of a line.
  // Otherwise tabs will be messed up.
  int i, width = initial_width;

  for( i=start; i<=end; i++ )
    if (text[i] == '\t') { // Character is a tab, jump to next tab stop
      width += tab_width-(width%tab_width);
      //while (width == 0 || width % tab_width) 
	    //  width++;
    }
    else
      width += char_width( text[i] ); 

  return width;
}
Пример #14
0
static u32 calculate_chars_count(char *str, u32 str_len, u32 screen_width,
		u32 screen_height)
{
	u32 i, count = 0;

	for (i = 0; i < str_len; i++)
		count += char_width(str[i], count, screen_width);

	/* Ensure that 'count' can occupy at least the whole screen */
	if (count < screen_width * screen_height)
		count = screen_width * screen_height;

	/* Pad to line end */
	if (count % screen_width != 0)
		count += screen_width - (count % screen_width);

	return count;
}
Пример #15
0
int  GLUI_EditText::find_insertion_pt( int x, int y )
{
  int curr_x, i;

  /*** See if we clicked outside box ***/
  if ( x < this->x_abs + text_x_offset )
    return -1;

  /* We move from right to left, looking to see if the mouse was clicked
     to the right of the ith character */

  curr_x = this->x_abs + text_x_offset 
    + substring_width( substring_start, substring_end )
    + 2                             /* The edittext box has a 2-pixel margin */
    + GLUI_EDITTEXT_BOXINNERMARGINX;   /** plus this many pixels blank space
					 between the text and the box       **/

  /*** See if we clicked in an empty box ***/
  if ( (int) text.length() == 0 ) 
    return 0;

  /** find mouse click in text **/
  for( i=substring_end; i>=substring_start; i-- ) {
    curr_x -= char_width( text[i] );

    if ( x > curr_x ) {
      /*      printf( "-> %d\n", i );              */
      
      return i+1;
    }
  }

  return 0;

  /* Well, the mouse wasn't after any of the characters...see if it's
     before the beginning of the substring */
  if ( 0 ) {
    if ( x > (x_abs + text_x_offset + 2 ) )
      return substring_start;
    
    return -1; /* Nothing found */
  }
}
Пример #16
0
/*
 * This method takes an input buffer and sanitizes it for display, which means:
 *  - '\n' is converted to spaces until end of line
 *  - Tabs are converted to spaces of size TAB_WIDTH
 *  - Only printable characters are preserved
 */
static int sanitize_buffer_for_display(char *str, u32 str_len, char *out,
		u32 out_len, u32 screen_width)
{
	u32 cursor = 0;
	u32 i;

	for (i = 0; i < str_len && cursor < out_len; i++) {
		u32 width = char_width(str[i], cursor, screen_width);

		if (width == 1)
			out[cursor++] = str[i];
		else if (width > 1)
			while (width-- && cursor < out_len)
				out[cursor++] = ' ';
	}

	/* Fill the rest of the out buffer with spaces */
	while (cursor < out_len)
		out[cursor++] = ' ';

	return 0;
}
Пример #17
0
void
create_dirinfo(Boolean file_exp, Widget parent, Widget below, Widget *ret_beside, Widget *ret_below, Widget *mask_w, Widget *dir_w, Widget *flist_w, Widget *dlist_w, int file_width, Boolean file_panel)
{
    Widget	    w,dir_alt,home;
    Widget	    file_viewport;
    Widget	    dir_viewport;
    XFontStruct	   *temp_font;
    int		    char_ht,char_wd;
    char	   *dir;

    dir_entry_cnt = NENTRIES;
    file_entry_cnt = NENTRIES;
    filelist = (char **) calloc(file_entry_cnt, sizeof(char *));
    dirlist = (char **) calloc(dir_entry_cnt, sizeof(char *));

    if (browse_up) {
	get_directory(cur_browse_dir);
	dir = cur_browse_dir;
    } else if (export_up) {
	get_directory(cur_export_dir);
	dir = cur_export_dir;
    } else {
	get_directory(cur_file_dir);
	dir = cur_file_dir;
    }

    if (file_up) {
	FirstArg(XtNlabel, "Fig files");
    } else {
	FirstArg(XtNlabel, "     Existing");
    }
    NextArg(XtNfromVert, below);
    NextArg(XtNborderWidth, 0);
    NextArg(XtNtop, XtChainTop);
    NextArg(XtNbottom, XtChainTop);
    NextArg(XtNleft, XtChainLeft);
    NextArg(XtNright, XtChainLeft);
    w = XtCreateManagedWidget("file_alt_label", labelWidgetClass,
			      parent, Args, ArgCount);

    FirstArg(XtNfont, &temp_font);
    GetValues(w);
    char_ht = max_char_height(temp_font) + 2;
    char_wd = char_width(temp_font) + 2;

    /* make a viewport to hold the list widget of filenames */
    FirstArg(XtNallowVert, True);
    if (file_up) {
	/* for the file panel, put the viewport below the Alternatives label */
	NextArg(XtNfromVert, w);
	NextArg(XtNheight, char_ht * 15);	/* show first 15 filenames */
    } else {
	/* for the export or browse panel, put the viewport beside the Alternatives label */
	NextArg(XtNfromVert, below);
	NextArg(XtNfromHoriz, w);
	if (browse_up) {
	    NextArg(XtNheight, char_ht * 10);	/* show 10 lines for existing browse files */
	} else {
	    NextArg(XtNheight, char_ht * 4);	/* show 4 lines for existing export files */
	}
    }
    NextArg(XtNborderWidth, INTERNAL_BW);
    NextArg(XtNwidth, file_width);
    NextArg(XtNtop, XtChainTop);		/* chain so the viewport resizes fully */
    NextArg(XtNbottom, XtChainBottom);
    NextArg(XtNleft, XtChainLeft);
    NextArg(XtNright, XtChainRight);
    file_viewport = XtCreateManagedWidget("vport", viewportWidgetClass,
					  parent, Args, ArgCount);

    /* label for filename mask */

    FirstArg(XtNlabel, "Filename Mask");
    NextArg(XtNborderWidth, 0);
    NextArg(XtNfromVert, file_viewport);
    NextArg(XtNtop, XtChainBottom);
    NextArg(XtNbottom, XtChainBottom);
    NextArg(XtNleft, XtChainLeft);
    NextArg(XtNright, XtChainLeft);
    w = XtCreateManagedWidget("mask_label", labelWidgetClass, 
				parent, Args, ArgCount);

    /* text widget for the filename mask */

    FirstArg(XtNeditType, XawtextEdit);
    NextArg(XtNleftMargin, 4);
    NextArg(XtNheight, char_ht * 2);
    NextArg(XtNscrollHorizontal, XawtextScrollWhenNeeded);
    NextArg(XtNborderWidth, INTERNAL_BW);
    NextArg(XtNwidth, file_panel? F_FILE_WIDTH: E_FILE_WIDTH);
    NextArg(XtNfromHoriz, w);
    NextArg(XtNfromVert, file_viewport);
    NextArg(XtNtop, XtChainBottom);
    NextArg(XtNbottom, XtChainBottom);
    NextArg(XtNleft, XtChainLeft);
    NextArg(XtNright, XtChainRight);
    *mask_w = XtCreateManagedWidget("mask", asciiTextWidgetClass, 
					parent, Args, ArgCount);
    XtOverrideTranslations(*mask_w, XtParseTranslationTable(mask_text_translations));

    /* get the first directory listing */

    FirstArg(XtNstring, &dirmask);
    GetValues(*mask_w);
    if (MakeFileList(dir, dirmask, &dir_list, &file_list) == False)
	file_msg("No files in directory?");

    FirstArg(XtNlabel, "  Current Dir");
    NextArg(XtNborderWidth, 0);
    NextArg(XtNfromVert, *mask_w);
    NextArg(XtNtop, XtChainBottom);
    NextArg(XtNbottom, XtChainBottom);
    NextArg(XtNleft, XtChainLeft);
    NextArg(XtNright, XtChainLeft);
    w = XtCreateManagedWidget("dir_label", labelWidgetClass,
			      parent, Args, ArgCount);

    FirstArg(XtNstring, dir);
    NextArg(XtNleftMargin, 4);
    NextArg(XtNinsertPosition, strlen(dir));
    NextArg(XtNheight, char_ht * 2);
    NextArg(XtNborderWidth, INTERNAL_BW);
    NextArg(XtNscrollHorizontal, XawtextScrollWhenNeeded);
    NextArg(XtNeditType, XawtextEdit);
    NextArg(XtNfromVert, *mask_w);
    NextArg(XtNfromHoriz, w);
    NextArg(XtNwidth, file_panel? F_FILE_WIDTH: E_FILE_WIDTH);
    NextArg(XtNtop, XtChainBottom);
    NextArg(XtNbottom, XtChainBottom);
    NextArg(XtNleft, XtChainLeft);
    NextArg(XtNright, XtChainRight);
    *dir_w = XtCreateManagedWidget("dir_name", asciiTextWidgetClass,
				   parent, Args, ArgCount);

    XtOverrideTranslations(*dir_w, XtParseTranslationTable(dir_translations));

    /* directory alternatives */

    FirstArg(XtNlabel, "  Directories");
    NextArg(XtNborderWidth, 0);
    NextArg(XtNfromVert, *dir_w);
    NextArg(XtNtop, XtChainBottom);
    NextArg(XtNbottom, XtChainBottom);
    NextArg(XtNleft, XtChainLeft);
    NextArg(XtNright, XtChainLeft);
    dir_alt = XtCreateManagedWidget("dir_alt_label", labelWidgetClass,
			      parent, Args, ArgCount);

    /* put a Home button to the left of the list of directories */
    FirstArg(XtNlabel, "Home");
    NextArg(XtNfromVert, dir_alt);
    NextArg(XtNfromHoriz, dir_alt);
    NextArg(XtNhorizDistance, -(char_wd * 5));
    NextArg(XtNborderWidth, INTERNAL_BW);
    NextArg(XtNtop, XtChainBottom);
    NextArg(XtNbottom, XtChainBottom);
    NextArg(XtNleft, XtChainLeft);
    NextArg(XtNright, XtChainLeft);
    home = XtCreateManagedWidget("home", commandWidgetClass, parent, Args, ArgCount);
    XtAddCallback(home, XtNcallback, GoHome, (XtPointer) NULL);

    /* put a button for showing/hiding hidden files below the Home button */

    FirstArg(XtNlabel, show_hidden? "Hide Hidden": "Show Hidden");
    NextArg(XtNfromVert, home);
    NextArg(XtNfromHoriz, dir_alt);
    NextArg(XtNhorizDistance, (int) -(char_wd * 10.5));
    NextArg(XtNborderWidth, INTERNAL_BW);
    NextArg(XtNtop, XtChainBottom);
    NextArg(XtNbottom, XtChainBottom);
    NextArg(XtNleft, XtChainLeft);
    NextArg(XtNright, XtChainLeft);
    hidden = XtCreateManagedWidget("hidden", commandWidgetClass, 
				parent, Args, ArgCount);
    XtAddCallback(hidden, XtNcallback, ShowHidden, (XtPointer) NULL);

    FirstArg(XtNallowVert, True);
    NextArg(XtNforceBars, True);
    NextArg(XtNfromHoriz, dir_alt);
    NextArg(XtNfromVert, *dir_w);
    NextArg(XtNborderWidth, INTERNAL_BW);
    NextArg(XtNwidth, file_panel? F_FILE_WIDTH: E_FILE_WIDTH);
    NextArg(XtNheight, char_ht * 5);
    NextArg(XtNtop, XtChainBottom);
    NextArg(XtNbottom, XtChainBottom);
    NextArg(XtNleft, XtChainLeft);
    NextArg(XtNright, XtChainRight);
    dir_viewport = XtCreateManagedWidget("dirvport", viewportWidgetClass,
					 parent, Args, ArgCount);

    FirstArg(XtNlist, file_list);
    /* for file panel use only one column */
    if (file_panel) {
	NextArg(XtNdefaultColumns, 1);
	NextArg(XtNforceColumns, True);
    }
    *flist_w = XtCreateManagedWidget("file_list_panel", figListWidgetClass,
				     file_viewport, Args, ArgCount);
    XtAddCallback(*flist_w, XtNcallback, FileSelected, (XtPointer) NULL);
    XtOverrideTranslations(*flist_w,
			   XtParseTranslationTable(list_panel_translations));

    FirstArg(XtNlist, dir_list);
    *dlist_w = XtCreateManagedWidget("dir_list_panel", figListWidgetClass,
				     dir_viewport, Args, ArgCount);
    XtOverrideTranslations(*dlist_w,
			   XtParseTranslationTable(list_panel_translations));

    XtAddCallback(*dlist_w, XtNcallback, DirSelected, (XtPointer) NULL);

    if (!actions_added) {
	XtAppAddActions(tool_app, actionTable, XtNumber(actionTable));
	actions_added = True;
    }

    FirstArg(XtNlabel, "Rescan");
    NextArg(XtNfromVert, dir_viewport);
    NextArg(XtNvertDistance, 15);
    NextArg(XtNborderWidth, INTERNAL_BW);
    NextArg(XtNhorizDistance, 45);
    NextArg(XtNheight, 25);
    NextArg(XtNtop, XtChainBottom);
    NextArg(XtNbottom, XtChainBottom);
    NextArg(XtNleft, XtChainLeft);
    NextArg(XtNright, XtChainLeft);
    w = XtCreateManagedWidget("rescan", commandWidgetClass, parent,
			      Args, ArgCount);
    XtAddCallback(w, XtNcallback, CallbackRescan, (XtPointer) NULL);

    /* install accelerators so they can be used from each window */
    XtInstallAccelerators(parent, w);
    XtInstallAccelerators(*flist_w, parent);
    XtInstallAccelerators(*dlist_w, parent);

    *ret_beside = w;
    *ret_below = dir_viewport;

    return;
}
Пример #18
0
/* Populates the sc->lines list with as many lines as possible.
 */
static void
get_more_lines (sws_configuration *sc)
{
  /* wrap anyway, if it's absurdly long. */
  int wrap_pix = (wrap_p ? sc->line_pixel_width : 10000);
  
  int col = 0;
  int col_pix = 0;

  char *s = sc->buf;

  int target = sc->buf_size - sc->buf_tail - 2;

  /* Fill as much as we can into sc->buf.
   */
  while (target > 0)
    {
      char c = textclient_getc (sc->tc);
      if (c <= 0)
        break;
      sc->buf[sc->buf_tail++] = c;
      sc->buf[sc->buf_tail] = 0;
      target--;
    }

  while (sc->total_lines < max_lines)
    {
      int cw;

      if (s >= sc->buf + sc->buf_tail)
        /* Reached end of buffer before end of line.  Bail. */
        return;

      cw = char_width (sc, *s);

      if (*s == '\r' || *s == '\n' ||
          col_pix + cw >= wrap_pix)
        {
          int L = s - sc->buf;

          if (*s == '\r' || *s == '\n')
            {
              if (*s == '\r' && s[1] == '\n')  /* swallow CRLF too */
                *s++ = 0;

              *s++ = 0;
            }
          else
            {
              /* We wrapped -- try to back up to the previous word boundary. */
              char *s2 = s;
              int n = 0;
              while (s2 > sc->buf && *s2 != ' ' && *s2 != '\t')
                s2--, n++;
              if (s2 > sc->buf)
                {
                  s = s2;
                  *s++ = 0;
                  L = s - sc->buf;
                }
            }

          sc->lines[sc->total_lines] = (char *) malloc (L+1);
          memcpy (sc->lines[sc->total_lines], sc->buf, L);
          sc->lines[sc->total_lines][L] = 0;

          if (!textures_p)
            latin1_to_ascii (sc->lines[sc->total_lines]);

          {
            char *t = sc->lines[sc->total_lines];
            char *ut = untabify (t);
            strip (ut, (alignment == 0), 1); /* if centering, strip
                                                leading whitespace too */
            sc->lines[sc->total_lines] = ut;
            free (t);
          }

          sc->total_lines++;

          if (sc->buf_tail > (s - sc->buf))
            {
              int i = sc->buf_tail - (s - sc->buf);
              memmove (sc->buf, s, i);
              sc->buf_tail = i;
              sc->buf[sc->buf_tail] = 0;
            }
          else
            {
              sc->buf_tail = 0;
            }

          sc->buf[sc->buf_tail] = 0;
          s = sc->buf;
          col = 0;
          col_pix = 0;
        }
      else
        {
          col++;
          col_pix += cw;
          if (*s == '\t')
            {
              int tab_pix = TAB_WIDTH * sc->char_width;
              col     = TAB_WIDTH * ((col / TAB_WIDTH) + 1);
              col_pix = tab_pix   * ((col / tab_pix)   + 1);
            }
          s++;
        }
    }
}
Пример #19
0
static int64_t pdf_char_width(pdfstructure * p, internal_font_number f, int i)
{
    return i64round((double) char_width(f, i) / font_size(f) * ten_pow[e_tj + p->cw.e]);
}
Пример #20
0
void tex::init_math ()
	{
	fnt	f;
	int	m, n;
	ptr	p, q;
	scal	d, l, s, v, w;

	get_token();
	if (cur_cmd == MATH_SHIFT && mode > 0) {
		if (head == tail) {
			pop_nest();
			w = -MAX_DIMEN;
		} else {
			line_break(display_widow_penalty);
			v = shift_amount(just_box) + 2 * quad(cur_font);
			w = -MAX_DIMEN;
			p = list_ptr(just_box);
			while (p != null) {
		reswitch:
				if (is_char_node(p)) {
					f = font(p);
					d = char_width(f,
						char_info(f, character(p)));
					goto found;
				}
				switch (type(p))
				{
				case HLIST_NODE:
				case VLIST_NODE:
				case RULE_NODE:
					d = box_width(p);
					goto found;
				
				case LIGATURE_NODE:
					p = make_char_from_lig(p);
					goto reswitch;
				
				case KERN_NODE:
					d = kern_width(p);
					break;

				case MATH_NODE:
					d = box_width(p);
					break;

				case GLUE_NODE:
					q = glue_ptr(p);
					d = box_width(q);
					if (glue_sign(just_box) ==
						STRETCHING) {
						if (glue_order(just_box) ==
							stretch_order(q)
						&& stretch(q) != 0)
							v = MAX_DIMEN;
					} else if (glue_sign(just_box) ==
						SHRINKING)  {
						if (glue_order(just_box) ==
							shrink_order(q)
						&& shrink(q) != 0) 
							v = MAX_DIMEN;
					}
					if (subtype(p) >= A_LEADERS)	
						goto found;
					break;

				case WHATSIT_NODE: 
					d = 0;
					break;

				default:
					d = 0;
					break;
				}
				if (v < MAX_DIMEN)
					v += d;
				goto not_found;
			
			found:
				if (v < MAX_DIMEN) {
					v += d;
					w = v;
				} else {
					w = MAX_DIMEN;
					break;
				}

			not_found:
				p = link(p);
			}
		}
		if (par_shape_ptr == null) {
			if (hang_indent != 0
			&& (hang_after >= 0
				&& prev_graf + 2 > hang_after
					|| prev_graf + 1 < -hang_after)) {
				l = hsize - abs(hang_indent);
				s = (hang_indent > 0) ? hang_indent : 0;
			} else {
				l = hsize;
				s = 0;
			}
		} else {
			n = info(par_shape_ptr);
			if (prev_graf + 2 >= n)
				m = n;
			else m = prev_graf + 2;
			l = par_shape_width(m);
			s = par_shape_indent(m);
		}
		push_math(MATH_SHIFT_GROUP);
		mode = MMODE;
		reg_define(int_reg[CUR_FAM_CODE], INT_REG, -1);
		reg_define(dimen_reg[PRE_DISPLAY_SIZE_CODE], DIMEN_REG, w);
		reg_define(dimen_reg[DISPLAY_WIDTH_CODE], DIMEN_REG, l);
		reg_define(dimen_reg[DISPLAY_INDENT_CODE], DIMEN_REG, s);
		if (every_display != null)
			begin_token_list(every_display, EVERY_DISPLAY_TEXT);
		if (nest_ptr == nest + 1)
			build_page();
	} else {
		back_input(); 
		push_math(MATH_SHIFT_GROUP);
		reg_define(int_reg[CUR_FAM_CODE], INT_REG, -1);
		if (every_math != null)
			begin_token_list(every_math, EVERY_MATH_TEXT);
	}
}
Пример #21
0
void 
do_vf_packet (internal_font_number vf_f, integer c) {
  internal_font_number lf;
  charinfo *co;
  scaled save_cur_h, save_cur_v;
  real_eight_bits *vf_packets;
  integer cur_packet_byte;
  integer cmd, fs_f;
  scaled i;
  unsigned k;
  str_number s;

  packet_cur_s++;
  if (packet_cur_s >= packet_max_recursion)
    overflow_string("max level recursion of virtual fonts", packet_max_recursion);
  save_cur_v = cur_v;
  save_cur_h = cur_h;
  
  lf = 0; /* for -Wall */
  co = get_charinfo(vf_f,c);
  vf_packets = get_charinfo_packets(co);
  if (vf_packets == NULL) {
    packet_cur_s--;
    return ;
  }
  cur_packet_byte = 0;
  fs_f = font_size(vf_f);
  while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) {
    cur_packet_byte++;
    /*
    if (cmd>packet_end_code) {
      fprintf(stdout, "do_vf_packet(%i,%i) command code = illegal \n", vf_f,c);
    } else {
      fprintf(stdout, "do_vf_packet(%i,%i) command code = %s\n",vf_f, c, packet_command_names[cmd]);
    }
    */
    switch (cmd) {
    case packet_font_code:
      packet_number(lf);
      break;
    case packet_push_code: 
      packet_stack[packet_stack_ptr].stack_h = cur_h;
      packet_stack[packet_stack_ptr].stack_v = cur_v;
      packet_stack_ptr++;
      break;
    case packet_pop_code:
      packet_stack_ptr--;
      cur_h = packet_stack[packet_stack_ptr].stack_h;
      cur_v = packet_stack[packet_stack_ptr].stack_v;
      break;
    case packet_char_code: 
      packet_number(k);
      if (!char_exists(lf,k)) {
	char_warning(lf, k);
      } else {
	output_one_char(lf, k);
      }
      cur_h = cur_h + char_width(lf,k);
      break;
    case packet_rule_code: 
      packet_scaled(rule_ht,fs_f);
      packet_scaled(rule_wd,fs_f);
      if ((rule_wd > 0) && (rule_ht > 0)) {
	pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
	cur_h = cur_h + rule_wd;
      }
      break;
    case packet_right_code:
      packet_scaled(i,fs_f);
      cur_h = cur_h + i;
      break;
    case packet_down_code:
	  packet_scaled(i,fs_f);
      cur_v = cur_v + i;
      break;
    case packet_special_code:
      packet_number(k);
      string_room(k);
      while (k > 0) {
		k--;
		append_pool_char(do_packet_byte());
      }
      s = make_string();
      literal(s, scan_special, false);
      flush_str(s);
      break;
	case packet_node_code:
	  packet_number(k);
	  temp_ptr = k; 
	  pdf_hlist_out();
	  break;
    case packet_nop_code:
      break;
    default: 
      pdf_error(maketexstring("vf"), maketexstring("invalid DVI command"));     
    }
  };
  cur_h = save_cur_h;
  cur_v = save_cur_v;
  packet_cur_s--;
}
Пример #22
0
void    GLUI_EditText::draw_text( int x, int y )
{
  GLUI_DRAWINGSENTINAL_IDIOM
  int text_x, i, sel_lo, sel_hi;

  if ( debug )    dump( stdout, "-> DRAW_TEXT" );

  if ( NOT draw_text_only ) {
    if ( enabled )
      glColor3f( 1., 1., 1. );
    else
      set_to_bkgd_color();
    glDisable( GL_CULL_FACE );
    glBegin( GL_QUADS );
    glVertex2i( text_x_offset+2, 2 );     glVertex2i( w-2, 2 );
    glVertex2i( w-2, h-2 );               glVertex2i( text_x_offset+2, h-2 );
    glEnd();
  }

  /** Find where to draw the text **/

  text_x = text_x_offset + 2 + GLUI_EDITTEXT_BOXINNERMARGINX;

  /*printf( "text_x: %d      substr_width: %d     start/end: %d/%d\n",
    text_x,     substring_width( substring_start, substring_end ),
    substring_start, substring_end );
    */
  /** Find lower and upper selection bounds **/
  sel_lo = MIN(sel_start, sel_end );
  sel_hi = MAX(sel_start, sel_end );

  int sel_x_start, sel_x_end, delta;

  /** Draw selection area dark **/
  if ( sel_start != sel_end ) {
    sel_x_start = text_x;
    sel_x_end   = text_x;
    for( i=substring_start; i<=substring_end; i++ ) {
      delta = char_width( text[i] );

      if ( i < sel_lo ) {
	sel_x_start += delta;
	sel_x_end   += delta;
      }
      else if ( i < sel_hi ) {
	sel_x_end   += delta;
      }
    }

    glColor3f( 0.0f, 0.0f, .6f );
    glBegin( GL_QUADS );
    glVertex2i( sel_x_start, 2 );    glVertex2i( sel_x_end, 2 );
    glVertex2i( sel_x_end, h-2 );    glVertex2i( sel_x_start, h-2 );
    glEnd();
  }
   

  if ( sel_start == sel_end ) {   /* No current selection */
    if ( enabled )
      glColor3b( 0, 0, 0 );
    else
      glColor3b( 32, 32, 32 );
      
    glRasterPos2i( text_x, 13);
    for( i=substring_start; i<=substring_end; i++ ) {
      glutBitmapCharacter( get_font(), this->text[i] );
    }
  }
  else {                          /* There is a selection */
    int x = text_x;
    for( i=substring_start; i<=substring_end; i++ ) {
      if ( IN_BOUNDS( i, sel_lo, sel_hi-1)) { /* This character is selected */
	glColor3f( 1., 1., 1. );
	glRasterPos2i( x, 13);
	glutBitmapCharacter( get_font(), this->text[i] );
      }
      else {
	glColor3f( 0., 0., 0. );
	glRasterPos2i( x, 13);
	glutBitmapCharacter( get_font(), this->text[i] );
      }
      
      x += char_width( text[i] );
    }
  }

  if ( debug )    dump( stdout, "<- DRAW_TEXT" );  
}
Пример #23
0
int BufferUtils::_genSignBuffer(GLfloat *data, float x, float y, float z, int face, const char *text)
{
    static const int glyph_dx[8] = {0, 0, -1, 1, 1, 0, -1, 0};
    static const int glyph_dz[8] = {1, -1, 0, 0, 0, -1, 0, 1};
    static const int line_dx[8] = {0, 0, 0, 0, 0, 1, 0, -1};
    static const int line_dy[8] = {-1, -1, -1, -1, 0, 0, 0, 0};
    static const int line_dz[8] = {0, 0, 0, 0, 1, 0, -1, 0};
    if (face < 0 || face >= 8) {
        return 0;
    }
    int count = 0;
    float max_width = 64;
    float line_height = 1.25;
    char lines[1024];
    int rows = wrap(text, max_width, lines, 1024);
    rows = MIN(rows, 5);
    int dx = glyph_dx[face];
    int dz = glyph_dz[face];
    int ldx = line_dx[face];
    int ldy = line_dy[face];
    int ldz = line_dz[face];
    float n = 1.0 / (max_width / 10);
    float sx = x - n * (rows - 1) * (line_height / 2) * ldx;
    float sy = y - n * (rows - 1) * (line_height / 2) * ldy;
    float sz = z - n * (rows - 1) * (line_height / 2) * ldz;
    char *key;
    char *line = tokenize(lines, "\n", &key);
    while (line) {
        int length = (int)strlen(line);
        int line_width = string_width(line);
        line_width = MIN(line_width, max_width);
        float rx = sx - dx * line_width / max_width / 2;
        float ry = sy;
        float rz = sz - dz * line_width / max_width / 2;
        for (int i = 0; i < length; i++) {
            int width = char_width(line[i]);
            line_width -= width;
            if (line_width < 0) {
                break;
            }
            rx += dx * width / max_width / 2;
            rz += dz * width / max_width / 2;
            if (line[i] != ' ') {
                make_character_3d(
                                  data + count * 30, rx, ry, rz, n / 2, face, line[i]);
                count++;
            }
            rx += dx * width / max_width / 2;
            rz += dz * width / max_width / 2;
        }
        sx += n * line_height * ldx;
        sy += n * line_height * ldy;
        sz += n * line_height * ldz;
        line = tokenize(NULL, "\n", &key);
        rows--;
        if (rows <= 0) {
            break;
        }
    }
    return count;
}
Пример #24
0
void pdf_hlist_out (void)
{
  scaled base_line;
  scaled left_edge;
  scaled save_h, save_v;
  pointer this_box;
  // glue_ord g_order;
  int g_order;
  // char g_sign;
  int g_sign;
  pointer p;
  integer save_loc;
  pointer leader_box;
  scaled leader_wd;
  scaled lx;
  boolean outer_doing_leaders;
  scaled edge;
  real glue_temp;
  real cur_glue;
  scaled cur_g;

  cur_g = 0;
  cur_glue = 0.0;
  this_box = temp_ptr;
  g_order = glue_order(this_box);
  g_sign = glue_sign(this_box);
  p = list_ptr(this_box);
  incr(cur_s);

  if (cur_s > max_push)
    max_push = cur_s;

  save_loc = dvi_offset + dvi_ptr;
  base_line = cur_v;
  left_edge = cur_h;

  while (p != 0)
reswitch:
  if (is_char_node(p))
  {
    pdf_synch_h();
    pdf_synch_v();

    do
    {
      f = font(p);
      c = character(p);

      if (f != dvi_f)
      {
        if (!font_used[f])
        {
          font_used[f] = true;
          font_id[f]   = pdf_get_font_id(f);
        }

        dvi_f = f;
      }

      pdf_out_char(dvi_f, c);
      cur_h = cur_h + char_width(f, char_info(f, c));
      p = link(p);
    } while (!(!is_char_node(p)));

    dvi_h = cur_h;
  }
  else
  {
    switch (type(p))
    {
      case hlist_node:
      case vlist_node:
        if (list_ptr(p) == 0)
          cur_h = cur_h + width(p);
        else
        {
          save_h = dvi_h;
          save_v = dvi_v;
          cur_v = base_line + shift_amount(p);
          temp_ptr = p;
          edge = cur_h;

          if (type(p) == vlist_node)
            pdf_vlist_out();
          else
            pdf_hlist_out();

          dvi_h = save_h;
          dvi_v = save_v;
          cur_h = edge + width(p);
          cur_v = base_line;
        }
        break;

      case rule_node:
        {
          rule_ht = height(p);
          rule_dp = depth(p);
          rule_wd = width(p);
          goto fin_rule;
        }
        break;

      case whatsit_node:
        out_what(p);
        break;

      case glue_node:
        {
          g = glue_ptr(p);
          rule_wd = width(g) - cur_g;

          if (g_sign != normal)
          {
            if (g_sign == stretching)
            {
              if (stretch_order(g) == g_order)
              {
                cur_glue = cur_glue + stretch(g);
                vet_glue(glue_set(this_box) * cur_glue);
                cur_g = round(glue_temp);
              }
            }
            else if (shrink_order(g) == g_order)
            {
              cur_glue = cur_glue - shrink(g);
              vet_glue(glue_set(this_box) * cur_glue);
              cur_g = round(glue_temp);
            }
          }

          rule_wd = rule_wd + cur_g;

          if (subtype(p) >= a_leaders)
          {
            leader_box = leader_ptr(p);

            if (type(leader_box) == rule_node)
            {
              rule_ht = height(leader_box);
              rule_dp = depth(leader_box);
              goto fin_rule;
            }

            leader_wd = width(leader_box);

            if ((leader_wd > 0) && (rule_wd > 0))
            {
              rule_wd = rule_wd + 10;
              edge = cur_h + rule_wd;
              lx = 0;

              if (subtype(p) == a_leaders)
              {
                save_h = cur_h;
                cur_h = left_edge + leader_wd * ((cur_h - left_edge) / leader_wd);

                if (cur_h < save_h)
                  cur_h = cur_h + leader_wd;
              }
              else
              {
                lq = rule_wd / leader_wd;
                lr = rule_wd % leader_wd;

                if (subtype(p) == c_leaders)
                  cur_h = cur_h + (lr / 2);
                else
                {
                  lx = (2 * lr + lq + 1) / (2 * lq + 2);
                  cur_h = cur_h + ((lr - (lq - 1)* lx) / 2);
                }
              }

              while (cur_h + leader_wd <= edge)
              {
                cur_v = base_line + shift_amount(leader_box);
                pdf_synch_v();
                save_v = dvi_v;
                pdf_synch_h();
                save_h = dvi_h;
                temp_ptr = leader_box;
                outer_doing_leaders = doing_leaders;
                doing_leaders = true;

                if (type(leader_box) == vlist_node)
                  pdf_vlist_out();
                else
                  pdf_hlist_out();

                doing_leaders = outer_doing_leaders;
                dvi_v = save_v;
                dvi_h = save_h;
                cur_v = base_line;
                cur_h = save_h + leader_wd + lx;
              }

              cur_h = edge - 10;
              goto next_p;
            }
          }

          goto move_past;
        }
        break;

      case kern_node:
      case math_node:
        cur_h = cur_h + width(p);
        break;

      case ligature_node:
        {
          mem[lig_trick] = mem[lig_char(p)];
          link(lig_trick) = link(p);
          p = lig_trick;
          goto reswitch;
        }
        break;

      default:
        break;
    }

    goto next_p;

fin_rule:
    if (is_running(rule_ht))
      rule_ht = height(this_box);

    if (is_running(rule_dp))
      rule_dp = depth(this_box);

    rule_ht = rule_ht + rule_dp;

    if ((rule_ht > 0) && (rule_wd > 0))
    {
      pdf_synch_h();
      cur_v = base_line + rule_dp;
      pdf_synch_v();
      pdf_dev_set_rule(dvi_h, -dvi_v, rule_wd, rule_ht);
      cur_v = base_line;
      dvi_h = dvi_h + rule_wd;
    }

move_past:
    cur_h = cur_h + rule_wd;

next_p:
    p = link(p);
  }

  prune_movements(save_loc);
  decr(cur_s);
}
Пример #25
0
/* Returns a single line of text from the output buffer of the subprocess,
   taking into account wrapping, centering, etc.  Returns 0 if no complete
   line is currently available.
 */
static char *
get_one_line (fliptext_configuration *sc)
{
  char *result = 0;
  int wrap_pix = sc->font_wrap_pixels;
  int col = 0;
  int col_pix = 0;
  char *s = sc->buf;
  int target = sc->buf_size - sc->buf_tail - 2;

  /* Fill as much as we can into sc->buf, but stop at newline.
   */
  while (target > 0)
    {
      int c = textclient_getc (sc->tc);
      if (c <= 0)
        break;
      sc->buf[sc->buf_tail++] = (char) c;
      sc->buf[sc->buf_tail] = 0;
      target--;
      if (c == '\r' || c == '\n')
        break;
    }

  while (!result)
    {
      int cw;

      if (s >= sc->buf + sc->buf_tail)
        /* Reached end of buffer before end of line.  Bail. */
        return 0;

      cw = char_width (sc, *s);

      if (*s == '\r' || *s == '\n' ||
          col_pix + cw >= wrap_pix)
        {
          int L = s - sc->buf;

          if (*s == '\r' || *s == '\n')
            {
              if (*s == '\r' && s[1] == '\n')  /* swallow CRLF too */
                *s++ = 0;

              *s++ = 0;
            }
          else
            {
              /* We wrapped -- try to back up to the previous word boundary. */
              char *s2 = s;
              int n = 0;
              while (s2 > sc->buf && *s2 != ' ' && *s2 != '\t')
                s2--, n++;
              if (s2 > sc->buf)
                {
                  s = s2;
                  *s++ = 0;
                  L = s - sc->buf;
                }
            }

          if (result) abort();
          result = (char *) malloc (L+1);
          memcpy (result, sc->buf, L);
          result[L] = 0;

          {
            char *t = result;
            char *ut = untabify (t);
            strip (ut, (sc->alignment == 0), 1); /* if centering, strip
                                                    leading whitespace too */
            result = ut;
            free (t);
          }

          if (sc->buf_tail > (s - sc->buf))
            {
              int i = sc->buf_tail - (s - sc->buf);
              memmove (sc->buf, s, i);
              sc->buf_tail = i;
              sc->buf[sc->buf_tail] = 0;
            }
          else
            {
              sc->buf_tail = 0;
            }

          sc->buf[sc->buf_tail] = 0;
          s = sc->buf;
          col = 0;
          col_pix = 0;
        }
      else
        {
          col++;
          col_pix += cw;
          if (*s == '\t')
            {
              int tab_pix = TAB_WIDTH * sc->char_width;
              col     = TAB_WIDTH * ((col / TAB_WIDTH) + 1);
              col_pix = tab_pix   * ((col / tab_pix)   + 1);
            }
          s++;
        }
    }

  return result;
}
Пример #26
0
struct chartrans *BKE_text_to_curve(Main *bmain, Scene *scene, Object *ob, int mode)
{
	VFont *vfont, *oldvfont;
	VFontData *vfd= NULL;
	Curve *cu;
	CharInfo *info = NULL, *custrinfo;
	TextBox *tb;
	VChar *che;
	struct chartrans *chartransdata=NULL, *ct;
	float *f, xof, yof, xtrax, linedist, *linedata, *linedata2, *linedata3, *linedata4;
	float twidth, maxlen= 0;
	int i, slen, j;
	int curbox;
	int selstart, selend;
	int utf8len;
	short cnr=0, lnr=0, wsnr= 0;
	wchar_t *mem, *tmp, ascii;

	/* renark: do calculations including the trailing '\0' of a string
	 * because the cursor can be at that location */

	if (ob->type!=OB_FONT) return NULL;

	// Set font data
	cu= (Curve *) ob->data;
	vfont= cu->vfont;
	
	if (cu->str == NULL) return NULL;
	if (vfont == NULL) return NULL;

	// Create unicode string
	utf8len = BLI_strlen_utf8(cu->str);
	mem = MEM_callocN(((utf8len + 1) * sizeof(wchar_t)), "convertedmem");
	
	BLI_strncpy_wchar_from_utf8(mem, cu->str, utf8len + 1);

	// Count the wchar_t string length
	slen = wcslen(mem);

	if (cu->ulheight == 0.0f)
		cu->ulheight = 0.05f;
	
	if (cu->strinfo==NULL)	/* old file */
		cu->strinfo = MEM_callocN((slen+4) * sizeof(CharInfo), "strinfo compat");
	
	custrinfo= cu->strinfo;
	if (cu->editfont)
		custrinfo= cu->editfont->textbufinfo;
	
	if (cu->tb==NULL)
		cu->tb= MEM_callocN(MAXTEXTBOX*sizeof(TextBox), "TextBox compat");

	vfd= vfont_get_data(bmain, vfont);

	/* The VFont Data can not be found */
	if (!vfd) {
		if (mem)
			MEM_freeN(mem);	
		return NULL;
	}

	/* calc offset and rotation of each char */
	ct = chartransdata =
		(struct chartrans*)MEM_callocN((slen+1)* sizeof(struct chartrans),"buildtext");

	/* We assume the worst case: 1 character per line (is freed at end anyway) */

	linedata= MEM_mallocN(sizeof(float)*(slen*2 + 1),"buildtext2");
	linedata2= MEM_mallocN(sizeof(float)*(slen*2 + 1),"buildtext3");
	linedata3= MEM_callocN(sizeof(float)*(slen*2 + 1),"buildtext4");	
	linedata4= MEM_callocN(sizeof(float)*(slen*2 + 1),"buildtext5");		
	
	linedist= cu->linedist;
	
	xof= cu->xof + (cu->tb[0].x/cu->fsize);
	yof= cu->yof + (cu->tb[0].y/cu->fsize);

	xtrax= 0.5f*cu->spacing-0.5f;

	oldvfont = NULL;

	for (i=0; i<slen; i++) custrinfo[i].flag &= ~(CU_CHINFO_WRAP|CU_CHINFO_SMALLCAPS_CHECK);

	if (cu->selboxes) MEM_freeN(cu->selboxes);
	cu->selboxes = NULL;
	if (BKE_font_getselection(ob, &selstart, &selend))
		cu->selboxes = MEM_callocN((selend-selstart+1)*sizeof(SelBox), "font selboxes");

	tb = &(cu->tb[0]);
	curbox= 0;
	for (i = 0 ; i<=slen ; i++) {
	makebreak:
		// Characters in the list
		info = &(custrinfo[i]);
		ascii = mem[i];
		if (info->flag & CU_CHINFO_SMALLCAPS) {
			ascii = towupper(ascii);
			if (mem[i] != ascii) {
				mem[i]= ascii;
				info->flag |= CU_CHINFO_SMALLCAPS_CHECK;
			}
		}

		vfont = which_vfont(cu, info);
		
		if (vfont==NULL) break;

		che= find_vfont_char(vfd, ascii);

		/*
		 * The character wasn't in the current curve base so load it
		 * But if the font is FO_BUILTIN_NAME then do not try loading since
		 * whole font is in the memory already
		 */
		if (che == NULL && strcmp(vfont->name, FO_BUILTIN_NAME))	{
			BLI_vfontchar_from_freetypefont(vfont, ascii);
		}

		/* Try getting the character again from the list */
		che= find_vfont_char(vfd, ascii);

		/* No VFont found */
		if (vfont==NULL) {
			if (mem)
				MEM_freeN(mem);
			MEM_freeN(chartransdata);
			return NULL;
		}

		if (vfont != oldvfont) {
			vfd= vfont_get_data(bmain, vfont);
			oldvfont = vfont;
		}

		/* VFont Data for VFont couldn't be found */
		if (!vfd) {
			if (mem)
				MEM_freeN(mem);
			MEM_freeN(chartransdata);
			return NULL;
		}

		twidth = char_width(cu, che, info);

		// Calculate positions
		if ((tb->w != 0.0f) && (ct->dobreak==0) && ((xof-(tb->x/cu->fsize)+twidth)*cu->fsize) > tb->w + cu->xof*cu->fsize) {
	//		fprintf(stderr, "linewidth exceeded: %c%c%c...\n", mem[i], mem[i+1], mem[i+2]);
			for (j=i; j && (mem[j] != '\n') && (mem[j] != '\r') && (chartransdata[j].dobreak==0); j--) {
				if (mem[j]==' ' || mem[j]=='-') {
					ct -= (i-(j-1));
					cnr -= (i-(j-1));
					if (mem[j] == ' ') wsnr--;
					if (mem[j] == '-') wsnr++;
					i = j-1;
					xof = ct->xof;
					ct[1].dobreak = 1;
					custrinfo[i+1].flag |= CU_CHINFO_WRAP;
					goto makebreak;
				}
				if (chartransdata[j].dobreak) {
	//				fprintf(stderr, "word too long: %c%c%c...\n", mem[j], mem[j+1], mem[j+2]);
					ct->dobreak= 1;
					custrinfo[i+1].flag |= CU_CHINFO_WRAP;
					ct -= 1;
					cnr -= 1;
					i--;
					xof = ct->xof;
					goto makebreak;
				}
			}
		}
		if (ascii== '\n' || ascii== '\r' || ascii==0 || ct->dobreak) {
			ct->xof= xof;
			ct->yof= yof;
			ct->linenr= lnr;
			ct->charnr= cnr;
			
			yof-= linedist;
			
			maxlen= MAX2(maxlen, (xof-tb->x/cu->fsize));
			linedata[lnr]= xof-tb->x/cu->fsize;
			linedata2[lnr]= cnr;
			linedata3[lnr]= tb->w/cu->fsize;
			linedata4[lnr]= wsnr;
			
			if ( (tb->h != 0.0f) &&
				 ((-(yof-(tb->y/cu->fsize))) > ((tb->h/cu->fsize)-(linedist*cu->fsize)) - cu->yof) &&
				 (cu->totbox > (curbox+1)) ) {
				maxlen= 0;
				tb++;
				curbox++;
				yof= cu->yof + tb->y/cu->fsize;
			}

			/* XXX, has been unused for years, need to check if this is useful, r4613 r5282 - campbell */
#if 0
			if (ascii == '\n' || ascii == '\r')
				xof = cu->xof;
			else
				xof= cu->xof + (tb->x/cu->fsize);
#else
			xof= cu->xof + (tb->x/cu->fsize);
#endif
			lnr++;
			cnr= 0;
			wsnr= 0;
		}
		else if (ascii==9) {	/* TAB */
			float tabfac;
			
			ct->xof= xof;
			ct->yof= yof;
			ct->linenr= lnr;
			ct->charnr= cnr++;

			tabfac= (xof-cu->xof+0.01f);
			tabfac= 2.0f*ceilf(tabfac/2.0f);
			xof= cu->xof+tabfac;
		}
		else {
			SelBox *sb= NULL;
			float wsfac;

			ct->xof= xof;
			ct->yof= yof;
			ct->linenr= lnr;
			ct->charnr= cnr++;

			if (cu->selboxes && (i>=selstart) && (i<=selend)) {
				sb = &(cu->selboxes[i-selstart]);
				sb->y = yof*cu->fsize-linedist*cu->fsize*0.1f;
				sb->h = linedist*cu->fsize;
				sb->w = xof*cu->fsize;
			}
	
			if (ascii==32) {
				wsfac = cu->wordspace; 
				wsnr++;
			} 
			else wsfac = 1.0f;
			
			// Set the width of the character
			twidth = char_width(cu, che, info);

			xof += (twidth*wsfac*(1.0f+(info->kern/40.0f)) ) + xtrax;
			
			if (sb) 
				sb->w = (xof*cu->fsize) - sb->w;
		}
		ct++;
	}
	
	cu->lines= 1;
	ct= chartransdata;
	tmp = mem;
	for (i= 0; i<=slen; i++, tmp++, ct++) {
		ascii = *tmp;
		if (ascii== '\n' || ascii== '\r' || ct->dobreak) cu->lines++;
	}	

	// linedata is now: width of line
	// linedata2 is now: number of characters
	// linedata3 is now: maxlen of that line
	// linedata4 is now: number of whitespaces of line

	if (cu->spacemode!=CU_LEFT) {
		ct= chartransdata;

		if (cu->spacemode==CU_RIGHT) {
			for (i=0;i<lnr;i++) linedata[i]= linedata3[i]-linedata[i];
			for (i=0; i<=slen; i++) {
				ct->xof+= linedata[ct->linenr];
				ct++;
			}
		}
		else if (cu->spacemode==CU_MIDDLE) {
			for (i=0;i<lnr;i++) linedata[i]= (linedata3[i]-linedata[i])/2;
			for (i=0; i<=slen; i++) {
				ct->xof+= linedata[ct->linenr];
				ct++;
			}
		}
		else if ((cu->spacemode==CU_FLUSH) &&
				  (cu->tb[0].w != 0.0f)) {
			for (i=0;i<lnr;i++)
				if (linedata2[i]>1)
					linedata[i]= (linedata3[i]-linedata[i])/(linedata2[i]-1);
			for (i=0; i<=slen; i++) {
				for (j=i; (!ELEM3(mem[j], '\0', '\n', '\r')) && (chartransdata[j].dobreak == 0) && (j < slen); j++) {
					/* do nothing */
				}

//				if ((mem[j]!='\r') && (mem[j]!='\n') && (mem[j])) {
					ct->xof+= ct->charnr*linedata[ct->linenr];
//				}
				ct++;
			}
		} 
		else if ((cu->spacemode==CU_JUSTIFY) && (cu->tb[0].w != 0.0f)) {
			float curofs= 0.0f;
			for (i=0; i<=slen; i++) {
				for (j=i; (mem[j]) && (mem[j]!='\n') && 
						  (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++);
				if ((mem[j]!='\r') && (mem[j]!='\n') &&
					((chartransdata[j].dobreak!=0))) {
					if (mem[i]==' ') curofs += (linedata3[ct->linenr]-linedata[ct->linenr])/linedata4[ct->linenr];
					ct->xof+= curofs;
				}
				if (mem[i]=='\n' || mem[i]=='\r' || chartransdata[i].dobreak) curofs= 0;
				ct++;
			}			
		}
	}
	
	/* TEXT ON CURVE */
	/* Note: Only OB_CURVE objects could have a path  */
	if (cu->textoncurve && cu->textoncurve->type==OB_CURVE) {
		Curve *cucu= cu->textoncurve->data;
		int oldflag= cucu->flag;
		
		cucu->flag |= (CU_PATH+CU_FOLLOW);
		
		if (cucu->path==NULL) makeDispListCurveTypes(scene, cu->textoncurve, 0);
		if (cucu->path) {
			float distfac, imat[4][4], imat3[3][3], cmat[3][3];
			float minx, maxx, miny, maxy;
			float timeofs, sizefac;
			
			invert_m4_m4(imat, ob->obmat);
			copy_m3_m4(imat3, imat);

			copy_m3_m4(cmat, cu->textoncurve->obmat);
			mul_m3_m3m3(cmat, cmat, imat3);
			sizefac= normalize_v3(cmat[0])/cu->fsize;
			
			minx=miny= 1.0e20f;
			maxx=maxy= -1.0e20f;
			ct= chartransdata;
			for (i=0; i<=slen; i++, ct++) {
				if (minx>ct->xof) minx= ct->xof;
				if (maxx<ct->xof) maxx= ct->xof;
				if (miny>ct->yof) miny= ct->yof;
				if (maxy<ct->yof) maxy= ct->yof;
			}
			
			/* we put the x-coordinaat exact at the curve, the y is rotated */
			
			/* length correction */
			distfac= sizefac*cucu->path->totdist/(maxx-minx);
			timeofs= 0.0f;
			
			if (distfac > 1.0f) {
				/* path longer than text: spacemode involves */
				distfac= 1.0f/distfac;
				
				if (cu->spacemode==CU_RIGHT) {
					timeofs= 1.0f-distfac;
				}
				else if (cu->spacemode==CU_MIDDLE) {
					timeofs= (1.0f-distfac)/2.0f;
				}
				else if (cu->spacemode==CU_FLUSH) distfac= 1.0f;
				
			}
			else distfac= 1.0;
			
			distfac/= (maxx-minx);
			
			timeofs+= distfac*cu->xof;	/* not cyclic */
			
			ct= chartransdata;
			for (i=0; i<=slen; i++, ct++) {
				float ctime, dtime, vec[4], tvec[4], rotvec[3];
				float si, co;
				
				/* rotate around center character */
				ascii = mem[i];

				che= find_vfont_char(vfd, ascii);
	
				twidth = char_width(cu, che, info);

				dtime= distfac*0.5f*twidth;

				ctime= timeofs + distfac*( ct->xof - minx);
				CLAMP(ctime, 0.0f, 1.0f);

				/* calc the right loc AND the right rot separately */
				/* vec, tvec need 4 items */
				where_on_path(cu->textoncurve, ctime, vec, tvec, NULL, NULL, NULL);
				where_on_path(cu->textoncurve, ctime+dtime, tvec, rotvec, NULL, NULL, NULL);
				
				mul_v3_fl(vec, sizefac);
				
				ct->rot= (float)(M_PI-atan2(rotvec[1], rotvec[0]));

				si= (float)sin(ct->rot);
				co= (float)cos(ct->rot);

				yof= ct->yof;
				
				ct->xof= vec[0] + si*yof;
				ct->yof= vec[1] + co*yof;
				
			}
			cucu->flag= oldflag;
		}
	}

	if (cu->selboxes) {
		ct= chartransdata;
		for (i=0; i<=selend; i++, ct++) {
			if (i>=selstart) {
				cu->selboxes[i-selstart].x = ct->xof*cu->fsize;
				cu->selboxes[i-selstart].y = ct->yof*cu->fsize;				
			}
		}
	}

	if (mode==FO_CURSUP || mode==FO_CURSDOWN || mode==FO_PAGEUP || mode==FO_PAGEDOWN) {
		/* 2: curs up
		 * 3: curs down */
		ct= chartransdata+cu->pos;
		
		if ((mode==FO_CURSUP || mode==FO_PAGEUP) && ct->linenr==0);
		else if ((mode==FO_CURSDOWN || mode==FO_PAGEDOWN) && ct->linenr==lnr);
		else {
			switch(mode) {
				case FO_CURSUP:		lnr= ct->linenr-1; break;
				case FO_CURSDOWN:	lnr= ct->linenr+1; break;
				case FO_PAGEUP:		lnr= ct->linenr-10; break;
				case FO_PAGEDOWN:	lnr= ct->linenr+10; break;
			}
			cnr= ct->charnr;
			/* seek for char with lnr en cnr */
			cu->pos= 0;
			ct= chartransdata;
			for (i= 0; i<slen; i++) {
				if (ct->linenr==lnr) {
					if (ct->charnr==cnr) break;
					if ( (ct+1)->charnr==0) break;
				}
				else if (ct->linenr>lnr) break;
				cu->pos++;
				ct++;
			}
		}
	}
	
	/* cursor first */
	if (cu->editfont) {
		float si, co;
		
		ct= chartransdata+cu->pos;
		si= (float)sin(ct->rot);
		co= (float)cos(ct->rot);
				
		f= cu->editfont->textcurs[0];
		
		f[0]= cu->fsize*(-0.1f*co + ct->xof);
		f[1]= cu->fsize*(0.1f*si + ct->yof);
		
		f[2]= cu->fsize*(0.1f*co + ct->xof);
		f[3]= cu->fsize*(-0.1f*si + ct->yof);
		
		f[4]= cu->fsize*( 0.1f*co + 0.8f*si + ct->xof);
		f[5]= cu->fsize*(-0.1f*si + 0.8f*co + ct->yof);
		
		f[6]= cu->fsize*(-0.1f*co + 0.8f*si + ct->xof);
		f[7]= cu->fsize*( 0.1f*si + 0.8f*co + ct->yof);
		
	}

	MEM_freeN(linedata);
	MEM_freeN(linedata2);		
	MEM_freeN(linedata3);
	MEM_freeN(linedata4);

	if (mode == FO_SELCHANGE) {
		MEM_freeN(chartransdata);
		MEM_freeN(mem);
		return NULL;
	}

	if (mode == FO_EDIT) {
		/* make nurbdata */
		freeNurblist(&cu->nurb);
		
		ct= chartransdata;
		if (cu->sepchar==0) {
			for (i= 0; i<slen; i++) {
				unsigned long cha = (uintptr_t) mem[i];
				info = &(custrinfo[i]);
				if (info->mat_nr > (ob->totcol)) {
					/* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */
					info->mat_nr = 0;
				}
				// We do not want to see any character for \n or \r
				if (cha != '\n' && cha != '\r')
					buildchar(bmain, cu, cha, info, ct->xof, ct->yof, ct->rot, i);
				
				if ((info->flag & CU_CHINFO_UNDERLINE) && (cu->textoncurve == NULL) && (cha != '\n') && (cha != '\r')) {
					float ulwidth, uloverlap= 0.0f;
					
					if ( (i<(slen-1)) && (mem[i+1] != '\n') && (mem[i+1] != '\r') &&
						 ((mem[i+1] != ' ') || (custrinfo[i+1].flag & CU_CHINFO_UNDERLINE)) && ((custrinfo[i+1].flag & CU_CHINFO_WRAP)==0)
						 ) {
						uloverlap = xtrax + 0.1f;
					}
					// Find the character, the characters has to be in the memory already 
					// since character checking has been done earlier already.
					che= find_vfont_char(vfd, cha);

					twidth = char_width(cu, che, info);
					ulwidth = cu->fsize * ((twidth* (1.0f+(info->kern/40.0f)))+uloverlap);
					build_underline(cu, ct->xof*cu->fsize, ct->yof*cu->fsize + (cu->ulpos-0.05f)*cu->fsize,
									ct->xof*cu->fsize + ulwidth, 
									ct->yof*cu->fsize + (cu->ulpos-0.05f)*cu->fsize - cu->ulheight*cu->fsize,
									i, info->mat_nr);
				}
				ct++;
			}
		}
		else {
			int outta = 0;
			for (i= 0; (i<slen) && (outta==0); i++) {
				ascii = mem[i];
				info = &(custrinfo[i]);
				if (cu->sepchar == (i+1)) {
					float vecyo[3];

					vecyo[0]= ct->xof;
					vecyo[1]= ct->yof;
					vecyo[2]= 0.0f;

					mem[0] = ascii;
					mem[1] = 0;
					custrinfo[0]= *info;
					cu->pos = 1;
					cu->len = 1;
					mul_v3_m4v3(ob->loc, ob->obmat, vecyo);
					outta = 1;
					cu->sepchar = 0;
				}
				ct++;
			}
		}
	}

	if (mode==FO_DUPLI) {
		MEM_freeN(mem);
		return chartransdata;
	}

	if (mem)
		MEM_freeN(mem);

	MEM_freeN(chartransdata);
	return NULL;
}
Пример #27
0
void    GLUI_TextBox::draw_text( int x, int y )
{
  GLUI_DRAWINGSENTINAL_IDIOM
  int text_x, i, sel_lo, sel_hi, x_pos;

  if ( debug )    dump( stdout, "-> DRAW_TEXT" );

  /** Find where to draw the text **/

  text_x = 2 + GLUI_TEXTBOX_BOXINNERMARGINX;

  /** Find lower and upper selection bounds **/
  sel_lo = MIN(sel_start, sel_end );
  sel_hi = MAX(sel_start, sel_end );

  int sel_x_start, sel_x_end, delta;

  /** Draw selection area dark **/
  if ( sel_start != sel_end ) {
    sel_x_start = text_x;
    sel_x_end   = text_x;
    for( i=substring_start; sel_x_end < (w - text_x) && i<=substring_end; i++ ) {
      delta = 0;
      if (text[i] == '\t') // Character is a tab, go to next tab stop
        while (((delta + sel_x_end) < (w - text_x)) && 
          (delta == 0 || delta % tab_width))
          delta++;
        else
          delta = char_width( text[i] );
        
        if ( i < sel_lo ) {
          sel_x_start += delta;
          sel_x_end   += delta;
        }
        else if ( i < sel_hi ) {
          sel_x_end   += delta;
        }
    }
    
    glColor3f( 0.0f, 0.0f, .6f );
    glRecti(sel_x_start, y+5, sel_x_end, y+20);
  }
  

  if ( sel_start == sel_end ) {   // No current selection 
    x_pos = text_x;
    if ( enabled )
      glColor3b( 0, 0, 0 );
    else
      glColor3b( 32, 32, 32 );
      
    glRasterPos2i( text_x, y+LINE_HEIGHT);
    for( i=substring_start; i<=substring_end; i++ ) {
      if (this->text[i] == '\t') { // Character is a tab, go to next tab stop
        x_pos = ((x_pos-text_x)/tab_width)*tab_width+tab_width+text_x;
        glRasterPos2i( x_pos, y+LINE_HEIGHT); // Reposition pen after tab
      } else {
        glutBitmapCharacter( get_font(), this->text[i] );
        x_pos += char_width( this->text[i] );
      }
    }
  }
  else {                        // There is a selection
    x_pos = text_x;
    for( i=substring_start; i<=substring_end; i++ ) {
      if ( IN_BOUNDS( i, sel_lo, sel_hi-1)) { // This character is selected
        glColor3f( 1., 1., 1. );
        glRasterPos2i( x_pos, y+LINE_HEIGHT);
        if (this->text[i] == '\t') { // Character is a tab, go to next tab stop
         x_pos = ((x_pos-text_x)/tab_width)*tab_width+tab_width+text_x;
        } 
        else
          glutBitmapCharacter( get_font(), this->text[i] );
      }
      else {
        glColor3f( 0., 0., 0. );
        glRasterPos2i( x_pos, y+LINE_HEIGHT);
        if (this->text[i] == '\t') { // Character is a tab, go to next tab stop
          x_pos = ((x_pos-text_x)/tab_width)*tab_width+tab_width+text_x;
          glRasterPos2i( x_pos, y+LINE_HEIGHT); // Reposition pen after tab 
        } else
          glutBitmapCharacter( get_font(), this->text[i] );
      }
      
      x_pos += char_width( text[i] );
    }
  }

  if ( debug )    dump( stdout, "<- DRAW_TEXT" );  
}
Пример #28
0
void _draw_screen_text(const char *text, screen_rectangle *destination, short flags, short font_id, short text_color)
{
	int x, y;

	// Find font information
	assert(font_id >= 0 && font_id < NUMBER_OF_INTERFACE_FONTS);
	uint16 style = InterfaceFonts[font_id].Style;
	const font_info *font = InterfaceFonts[font_id].Info;
	if (font == NULL)
		return;

	// Get color
	SDL_Color color;
	_get_interface_color(text_color, &color);

	// Copy the text to draw
	char text_to_draw[256];
	strncpy(text_to_draw, text, 256);
	text_to_draw[255] = 0;

	// Check for wrapping, and if it occurs, be recursive
	if (flags & _wrap_text) {
		int last_non_printing_character = 0, text_width = 0;
		unsigned count = 0;
		while (count < strlen(text_to_draw) && text_width < RECTANGLE_WIDTH(destination)) {
			text_width += char_width(text_to_draw[count], font, style);
			if (text_to_draw[count] == ' ')
				last_non_printing_character = count;
			count++;
		}
		
		if( count != strlen(text_to_draw)) {
			char remaining_text_to_draw[256];
			screen_rectangle new_destination;
			
			// If we ever have to wrap text, we can't also center vertically. Sorry.
			flags &= ~_center_vertical;
			flags |= _top_justified;
			
			// Pass the rest of it back in, recursively, on the next line
			memcpy(remaining_text_to_draw, text_to_draw + last_non_printing_character + 1, strlen(text_to_draw + last_non_printing_character + 1) + 1);
	
			new_destination = *destination;
			new_destination.top += InterfaceFonts[font_id].LineSpacing;
			_draw_screen_text(remaining_text_to_draw, &new_destination, flags, font_id, text_color);
	
			// Now truncate our text to draw
			text_to_draw[last_non_printing_character] = 0;
		}
	}

	// Truncate text if necessary
	int t_width = text_width(text_to_draw, font, style);
	if (t_width > RECTANGLE_WIDTH(destination)) {
		text_to_draw[trunc_text(text_to_draw, RECTANGLE_WIDTH(destination), font, style)] = 0;
		t_width = text_width(text_to_draw, font, style);
	}

	// Horizontal positioning
	if (flags & _center_horizontal)
		x = destination->left + (((destination->right - destination->left) - t_width) / 2);
	else if (flags & _right_justified)
		x = destination->right - t_width;
	else
		x = destination->left;

	// Vertical positioning
	int t_height = InterfaceFonts[font_id].Height;
	if (flags & _center_vertical) {
		if (t_height > RECTANGLE_HEIGHT(destination))
			y = destination->top;
		else {
			y = destination->bottom;
			int offset = RECTANGLE_HEIGHT(destination) - t_height;
			y -= (offset / 2) + (offset & 1) + 1;
		}
	} else if (flags & _top_justified) {
		if (t_height > RECTANGLE_HEIGHT(destination))
			y = destination->bottom;
		else
			y = destination->top + t_height;
	} else
		y = destination->bottom;

	// Now draw it
	draw_text(text_to_draw, x, y, SDL_MapRGB(draw_surface->format, color.r, color.g, color.b), font, style);
}