Beispiel #1
0
int			print_lx(t_data *data, va_list arg)
{
    char	*nb;
    int		i;
    char	*mod;

    nb = what_uconv(arg, data, 16);
    if (ft_strcmp(nb, "0") == 0 && data->prec == 0)
        ft_str_empty(nb);
    mod = ((data->flag & 1) && ft_strcmp(nb, "0") != 0) ? "0X" : NULL;
    ft_strupper(nb);
    if (nb[0] == '-')
        i = data->field - ft_max(ft_strlen(nb) + ft_strnlen(mod),
                                 data->prec + 1);
    else
        i = data->field - ft_max(ft_strlen(nb), data->prec);
    if (data->prec != -1 && ((data->flag & 2) != 0))
        data->flag = data->flag - 2;
    if ((data->flag & 4) != 0)
        print_nb_str(nb, data, mod);
    while ((i-- > 0) && (data->flag & 2) == 0)
        ft_printchar(' ', data);
    if ((data->flag & 4) == 0)
        print_nb_str(nb, data, mod);
    free(nb);
    return (1);
}
Beispiel #2
0
ssize_t				ft_printf_manage_octal(char **format, va_list *args,
		t_data *data)
{
	uintmax_t	nbr;

	(void)format;
	nbr = ft_printf_get_unsigned_from_length(args, data);
	if (data->prefix && !nbr &&
			data->got_accuracy && !data->accuracy)
	{
		if (data->got_width && !data->right_pad)
			ft_printf_width_pad(1, data->width, data->zero_pad ? '0' : ' ');
		ft_putstr("0");
		if (data->got_width && data->right_pad)
			ft_printf_width_pad(1, data->width, ' ');
		return (data->got_width ? ft_max(data->width, 1) : 1);
	}
	else if (data->prefix && nbr)
	{
		data->got_accuracy = 1;
		data->accuracy = ft_max(data->accuracy,
				ft_printf_nbrlen(nbr, "01234567") + 1);
	}
	return (ft_printfu(nbr, data, "01234567", NULL));
}
Beispiel #3
0
static int	ucalcul_size(t_flags *tflags, uintmax_t nb, char *base)
{
	int size;
	int nbsize;
	int sizeb;
	int tmp;

	sizeb = ft_strlen(base);
	size = 1;
	tmp = nb;
	nbsize = 1;
	while ((nb /= sizeb) != 0)
		++nbsize;
	size = ft_max(nbsize, tflags->prec);
	if (nb == 0 && tflags->prec == 0)
		size = 0;
	if (tmp != 0)
		tflags->prec -= nbsize;
	if (tflags->flags[4] && (tmp != 0 || tflags->type == 'p'))
	{
		if (tflags->type == 'x' || tflags->type == 'X' || tflags->type == 'p')
			size += 2;
		else if (tflags->type == 'o' || tflags->type == 'O')
			size += 1;
	}
	return (size);
}
Beispiel #4
0
void			ft_aff_lst(f_list *laliste)
{
	size_t lmax;
	size_t smax;

	lmax = 1;
	smax = 1;
	ft_max(*laliste, &lmax, &smax);
	while (laliste != NULL)
	{
		ft_putchar(laliste->type);
		ft_putstr(laliste->mod);
		ft_putstr("  ");
		ft_putstr(ft_add_spaces(laliste->link, lmax));
		ft_putchar(' ');
		ft_putstr(laliste->user);
		ft_putstr("  ");
		ft_putstr(laliste->group);
		ft_putstr("  ");
		ft_putstr(ft_add_spaces(laliste->size, smax));
		ft_putchar(' ');
		ft_putstr(laliste->date);
		ft_putchar(' ');
		ft_putstr(laliste->name);
		ft_putchar('\n');
		laliste = laliste->next;
	}
}
int	btree_level_count(t_btree *root)
{
	if (!root)
		return (0);
	return (ft_max(btree_level_count(root->left),
	btree_level_count(root->right)) + 1);
}
Beispiel #6
0
void	conv_i(t_spec *spec, t_print *print)
{
	int			i;
	int			j;
	intmax_t	p;

	p = get_param(spec->hljz, print->ap);
	if (p >= -9223372036854775807)
	{
		i = (p < 0) || (spec->flags & 3);
		j = !(spec->prec || p) ? 0
			: (ft_max(spec->prec + i, ft_nbrlen(ft_abs(p)) + i));
		++spec->mfw;
		(spec->flags & E_ZERO) ? apply_plusspace(print, spec, p >= 0)
			: --spec->mfw;
		(spec->flags & E_ZERO && p > 0) ? --spec->prec : 0;
		(!(spec->flags & E_DASH)) ? apply_mfw(print, spec, spec->mfw - j) : 0;
		!(spec->flags & E_ZERO) ? apply_plusspace(print, spec, p >= 0) : 0;
		apply_numprec(print, spec, ft_nbrlen(ft_abs(p)));
		(!spec->prec && !p) ? 0 : ft_sitoa(p, print, ft_nbrlen(ft_abs(p)));
		j = (spec->flags & 3) && (p > 0);
		(spec->flags & E_DASH) ? apply_mfw(print, spec, spec->mfw +
			(p >= 0) - j) : 0;
	}
}
Beispiel #7
0
void			number(void)
{
	if (sgt_printf()->flags.prec < 0 && sgt_printf()->flags.spec != 'f')
		sgt_printf()->flags.prec = 1;
	else if (sgt_printf()->flags.spec != 'f')
		sgt_printf()->flags.pad = ' ';
	if (sgt_printf()->flags.prec == 0 && sgt_printf()->flags.number.word == 0)
	{
		if ((sgt_printf()->flags.base == 8 && sgt_printf()->flags.alt)
			|| sgt_printf()->flags.spec == 'f'
			|| sgt_printf()->flags.spec == 'b')
			number_type();
	}
	else
	{
		number_type();
	}
	if (sgt_printf()->flags.spec == 'f' && sgt_printf()->flags.alt
		&& sgt_printf()->flags.prec == 0)
		sgt_printf()->work_buffer = concat2(sgt_printf()->work_buffer,
				ft_strlen(sgt_printf()->work_buffer), ".", 1);
	sgt_printf()->flags.prec = ft_max(0, sgt_printf()->flags.prec -
			ft_strlen(sgt_printf()->work_buffer));
	if (sgt_printf()->flags.left == false)
		s_not_left();
	else
		number_left();
}
Beispiel #8
0
char	*ft_itoa_base(int n, int base)
{
	char			digits[32];
	unsigned int	negative;
	unsigned int	index;
	unsigned int	count;
	char			*out;

	base = ft_min(ft_max(base, 2), 16);
	negative = n & SIGN_BIT_INT;
	if (negative)
		n = -n;
	count = 0;
	while (1)
	{
		digits[count++] = "0123456789abcdef"[n % base];
		if ((n = n / base) == 0)
			break ;
	}
	if ((out = ft_memalloc(count + 2)) == NULL)
		return (NULL);
	if (negative)
		*out = '-';
	index = negative && 1;
	while (count--)
		*(out + index++) = digits[count];
	return (out);
}
Beispiel #9
0
int					print_int(t_tag *tag, intmax_t nbr)
{
	char			*prefix;
	unsigned int	nbr_strlen;
	unsigned int	nbr_len;
	int				cut;

	prefix = NULL;
	cut = 0;
	nbr_len = nbr_length(nbr, "0123456789");
	nbr_strlen = nbr_strlength(tag, nbr, "0123456789");
	if ((nbr < 0 || tag->flag_plus || tag->flag_space) && (cut += 1))
		nbr_strlen = handle_prefix(nbr, prefix, tag);
	else if (tag->has_width && !tag->flag_minus && !tag->flag_zero)
		print_width_pad(nbr_strlen, tag->width, ' ');
	nbr = (nbr < 0 ? -nbr : nbr);
	if (tag->has_width && tag->flag_zero)
		print_width_pad(nbr_strlen - cut, tag->width, '0');
	else if (tag->has_precision)
		print_width_pad(ft_getsize(nbr), tag->precision, '0');
	ft_putnbr(nbr);
	if (tag->has_width && tag->flag_minus)
		print_width_pad(nbr_strlen - cut, tag->width, ' ');
	if (tag->has_width)
		return (ft_max(tag->width + cut, nbr_strlen));
	return (nbr_strlen);
}
Beispiel #10
0
int				track_nodes(t_node *nodes, int count, int curr)
{
	int				i;
	int				max;

	set_flags_by(nodes, count, curr);
	i = -1;
	max = 1;
	while (++i < count)
	{
		if (nodes[i].a == curr && !(nodes[i].flags != FLAG_BY_A))
			max = ft_max(max, track_nodes(nodes, count, nodes[i].b) + 1);
		if (nodes[i].b == curr && !(nodes[i].flags != FLAG_BY_B))
			max = ft_max(max, track_nodes(nodes, count, nodes[i].a) + 1);
	}
	unset_flags_by(nodes, count, curr);
	return (max);
}
Beispiel #11
0
unsigned int	nbr_strlength(t_tag *tag, uintmax_t nbr, char *base)
{
	unsigned int	nbr_strlen;
	unsigned int	nbr_len;

	nbr_len = nbr_length(nbr, base);
	if (nbr == 0 && tag->has_precision && tag->precision == 0)
		nbr_strlen = 1;
	else if (tag->has_precision)
		nbr_strlen = ft_max(nbr_len, tag->precision);
	else
		nbr_strlen = nbr_len;
	return (nbr_strlen);
}
Beispiel #12
0
int				print_wstring(t_tag *tag, wchar_t *str)
{
	int			str_len;

	str_len = tag->has_precision ? ft_strnwlen(str, tag->precision) :
										ft_strwlen(str);
	if (tag->has_width && !tag->flag_minus)
		print_width_pad(str_len, tag->width, tag->flag_zero ?
			'0' : ' ');
	ft_putnwstr(str, str_len);
	if (tag->has_width && tag->flag_minus)
		print_width_pad(str_len, tag->width, ' ');
	return (tag->has_width ? ft_max(tag->width, str_len) : str_len);
}
Beispiel #13
0
static void		set_v(t_tetrimino *t)
{
	int			i;
	uint16_t	mask;

	mask = 0xF000;
	i = 0;
	while (i < 4)
	{
		t->bits.part[i] = (t->value & mask) << (i * 4);
		if (t->bits.part[i])
		{
			t->height++;
			t->width = ft_max(t->width, get_width(t->bits.part[i]));
		}
		mask >>= 4;
		++i;
	}
}
Beispiel #14
0
ssize_t	handle_wstr(char **format, va_list *args, t_arg *arg)
{
	wchar_t	*str;
	size_t	strlen;

	(void)format;
	(void)arg;
	str = va_arg(*args, wchar_t*);
	if (str == NULL)
		str = L"(null)";
	strlen = arg->got_precision ? calc_wstrlen(str, arg->precision, 0) :
			ft_wstrlen(str);
	if (arg->got_width && !arg->right_pad)
		width_pad(strlen, arg->width, arg->pad_zeroes ? '0' : ' ', arg);
	ft_putnwstr(str, strlen);
	if (arg->got_width && arg->right_pad)
		width_pad(strlen, arg->width, ' ', arg);
	return (arg->got_width ? ft_max(strlen, arg->width) : strlen);
}
Beispiel #15
0
Datei: long.c Projekt: PlatonV/ls
void			print_size(t_stat st, t_maxes maxes)
{
	int		aux;

	if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))
	{
		ft_putchar(' ');
		print_nmax(major(st.st_rdev), maxes.max);
		ft_putstr(",");
		print_nmax(minor(st.st_rdev), maxes.min);
		ft_putchar(' ');
	}
	else
	{
		aux = maxes.max;
		while (aux--)
			ft_putchar(' ');
		print_nmax(st.st_size, ft_max(maxes.min, maxes.size));
		ft_putchar(' ');
	}
}
Beispiel #16
0
size_t	ft_print_gen(t_pfvar *var, const char *pre, const char *base)
{
	size_t			bytes;
	unsigned long	n;
	ssize_t			len;
	int				l;

	bytes = 0;
	n = get_arg_long(var);
	if (!n)
		var->flag |= ~FT_PRINTF_FLAG_DIESE;
	l = ft_log(n, ft_strlen(base));
	len = ft_max(var->precision, l);
	bytes += ft_fillspc(1, var, len);
	bytes += ft_fillzero(var, l);
	if (var->flag & FT_PRINTF_FLAG_DIESE)
		bytes += ft_putstr_fd(var->fd, pre);
	bytes += ft_putul(var->fd, n, base);
	bytes += ft_fillspc(0, var, len);
	return (bytes);
}
Beispiel #17
0
ssize_t	handle_str(char **format, va_list *args, t_arg *arg)
{
	char	*str;
	size_t	strlen;

	if (arg->length == l)
		return (handle_wstr(format, args, arg));
	else
	{
		str = va_arg(*args, char*);
		if (str == NULL)
			str = "(null)";
		strlen = arg->got_precision ? ft_nstrlen(str, arg->precision) :
				ft_strlen(str);
		if (arg->got_width && !arg->right_pad)
			width_pad(strlen, arg->width, arg->pad_zeroes ? '0' : ' ', arg);
		ft_putnstr(str, strlen);
		if (arg->got_width && arg->right_pad)
			width_pad(strlen, arg->width, ' ', arg);
		return (arg->got_width ? ft_max(strlen, arg->width) : strlen);
	}
}
Beispiel #18
0
static int	calc_map_size(t_env *e)
{
	int		i;
	int		j;
	int		size;
	int		tmp_max;

	size = 0;
	i = 0;
	while (i < MAP_WIDTH)
	{
		j = 0;
		while (j < MAP_WIDTH)
		{
			if (MAP[i][j] != 0 && (tmp_max = ft_max(i + 1, j + 1)) >= size)
				size = tmp_max;
			j++;
		}
		i++;
	}
	return (size);
}
Beispiel #19
0
ssize_t	handle_wchar(char **format, va_list *args, t_arg *arg)
{
	wchar_t		chr;
	unsigned	chr_len;

	(void)format;
	chr = (wchar_t)va_arg(*args, wint_t);
	if (chr <= 0x7F)
		chr_len = 1;
	else if (chr <= 0x7FF)
		chr_len = 2;
	else if (chr <= 0xFFFF)
		chr_len = 3;
	else if (chr <= 0x10FFFF)
		chr_len = 4;
	else
		chr_len = 0;
	if (arg->got_width && !arg->right_pad)
		width_pad(chr_len, arg->width, arg->pad_zeroes ? '0' : ' ', arg);
	ft_putwchar(chr);
	if (arg->got_width && arg->right_pad)
		width_pad(chr_len, arg->width, arg->pad_zeroes ? '0' : ' ', arg);
	return (arg->got_width ? ft_max(chr_len, arg->width) : chr_len);
}
Beispiel #20
0
void	conv_o(t_spec *spec, t_print *print)
{
	t_uintmax	p;
	int			i;
	int			j;
	int			k;

	p = urecupparam(spec->hljz, print->ap);
	i = (spec->flags & E_SHARP && !(spec->flags & E_ZERO));
	if (spec->flags & E_ZERO)
		applysharp(print, spec);
	j = ((spec->prec == -1) ? i : 0);
	k = !(spec->prec || p) ? 0
		: (j + ft_max(spec->prec, (int)ft_nbrlenbasemax(p, 8)));
	if (!(spec->flags & E_DASH))
		applymfw(print, spec, spec->mfw - k);
	if (!(spec->flags & E_ZERO))
		applysharp(print, spec);
	applynumprec(print, spec, i + (int)ft_nbrlenbasemax(p, 8));
	if (spec->prec || p)
		uitoabase(p, "01234567", print, ft_nbrlenbasemax(p, 8));
	if (spec->flags & E_DASH)
		applymfw(print, spec, spec->mfw);
}
Beispiel #21
0
int	btree_height(t_btree *root)
{
	if (!root)
		return (0);
	return (1 + ft_max(btree_height(root->left), btree_height(root->right)));
}
Beispiel #22
0
unsigned char *gks_ft_get_bitmap(int *x, int *y, int *width, int *height,
                                 gks_state_list_t *gkss, const char *text,
                                 int length) {
  FT_Face face;                   /* font face */
  FT_Vector pen;                  /* glyph position */
  FT_BBox bb;                     /* bounding box */
  FT_Vector bearing;              /* individual glyph translation */
  FT_UInt previous;               /* previous glyph index */
  FT_Vector spacing;              /* amount of additional space between glyphs */
  FT_ULong textheight;            /* textheight in FreeType convention */
  FT_Error error;                 /* error code */
  FT_Matrix rotation;             /* text rotation matrix */
  FT_UInt size;                   /* number of pixels of the bitmap */
  FT_String *file;                /* concatenated font path */
  const FT_String *font, *prefix; /* font file name and directory */
  FT_UInt *unicode_string;        /* unicode text string */
  FT_Int halign, valign;          /* alignment */
  FT_Byte *mono_bitmap = NULL;    /* target for rendered text */
  FT_Int num_glyphs;              /* number of glyphs */
  FT_Vector align;
  FT_Bitmap ftbitmap;
  FT_UInt codepoint;
  int i, textfont, dx, dy, value, pos_x, pos_y;
  unsigned int j, k;
  double angle;
  const int windowwidth = *width;
  const int direction = (gkss->txp <= 3 && gkss->txp >= 0 ? gkss->txp : 0);
  const FT_Bool vertical = (direction == GKS_K_TEXT_PATH_DOWN ||
                            direction == GKS_K_TEXT_PATH_UP);
  const FT_String *suffix_type1 = ".afm";

  if (!init) gks_ft_init();

  if (gkss->txal[0] != GKS_K_TEXT_HALIGN_NORMAL) {
    halign = gkss->txal[0];
  } else if (vertical) {
    halign = GKS_K_TEXT_HALIGN_CENTER;
  } else if (direction == GKS_K_TEXT_PATH_LEFT) {
    halign = GKS_K_TEXT_HALIGN_RIGHT;
  } else {
    halign = GKS_K_TEXT_HALIGN_LEFT;
  }
  valign = gkss->txal[1];
  if (valign != GKS_K_TEXT_VALIGN_NORMAL) {
    valign = gkss->txal[1];
  } else {
    valign = GKS_K_TEXT_VALIGN_BASE;
  }

  textfont = abs(gkss->txfont);
  if (textfont >= 101 && textfont <= 131)
    textfont -= 100;
  else if (textfont > 1 && textfont <= 32)
    textfont = map[textfont - 1];
  else
    textfont = 9;

  textfont = textfont - 1;
  font = gks_font_list[textfont];

  if (font_face_cache[textfont] == NULL) {
    prefix = gks_getenv("GKS_FONTPATH");
    if (prefix == NULL) {
      prefix = gks_getenv("GRDIR");
      if (prefix == NULL)
        prefix = GRDIR;
    }
    file = (FT_String *) malloc(strlen(prefix) + 7 + strlen(font) + 4 + 1);
    strcpy(file, prefix);
#ifndef _WIN32
    strcat(file, "/fonts/");
#else
    strcat(file, "\\FONTS\\");
#endif
    strcat(file, font);
    strcat(file, ".pfb");
    error = FT_New_Face(library, file, 0, &face);
    if (error == FT_Err_Unknown_File_Format) {
      gks_perror("unknown file format: %s", file);
      return NULL;
    } else if (error) {
      gks_perror("could not open font file: %s", file);
      return NULL;
    }
    if (strcmp(FT_Get_X11_Font_Format(face), "Type 1") == 0) {
      strcpy(file, prefix);
#ifndef _WIN32
      strcat(file, "/fonts/");
#else
      strcat(file, "\\FONTS\\");
#endif
      strcat(file, font);
      strcat(file, suffix_type1);
      FT_Attach_File(face, file);
    }
    free(file);
    font_face_cache[textfont] = face;
  } else {
    face = font_face_cache[textfont];
  }

  num_glyphs = length;
  unicode_string = (FT_UInt *) malloc(length * sizeof(FT_UInt) + 1);
  if (textfont + 1 == 13) {
    symbol_to_unicode((FT_Bytes)text, unicode_string, num_glyphs);
  } else {
    utf_to_unicode((FT_Bytes)text, unicode_string, &num_glyphs);
  }

  textheight = nint(gkss->chh * windowwidth * 64 / caps[textfont]);
  error = FT_Set_Char_Size(face, nint(textheight * gkss->chxp), textheight,
                           72, 72);
  if (error) gks_perror("cannot set text height");

  if (gkss->chup[0] != 0.0 || gkss->chup[1] != 0.0) {
    angle = atan2f(gkss->chup[1], gkss->chup[0]) - M_PI / 2;
    rotation.xx = nint( cosf(angle) * 0x10000L);
    rotation.xy = nint(-sinf(angle) * 0x10000L);
    rotation.yx = nint( sinf(angle) * 0x10000L);
    rotation.yy = nint( cosf(angle) * 0x10000L);
    FT_Set_Transform(face, &rotation, NULL);
  } else {
    FT_Set_Transform(face, NULL, NULL);
  }

  spacing.x = spacing.y = 0;
  if (gkss->chsp != 0.0) {
    error = FT_Load_Glyph(face, FT_Get_Char_Index(face, ' '),
                          vertical ? FT_LOAD_VERTICAL_LAYOUT : FT_LOAD_DEFAULT);
    if (!error) {
      spacing.x = nint(face->glyph->advance.x * gkss->chsp);
      spacing.y = nint(face->glyph->advance.y * gkss->chsp);
    } else {
      gks_perror("cannot apply character spacing");
    }
  }

  bb.xMin = bb.yMin = LONG_MAX;
  bb.xMax = bb.yMax = LONG_MIN;
  pen.x = pen.y = 0;
  previous = 0;

  for (i = 0; i < num_glyphs; i++) {
    codepoint = unicode_string[direction == GKS_K_TEXT_PATH_LEFT ?
                               (num_glyphs - 1 - i) : i];
    error = set_glyph(face, codepoint, &previous, &pen, vertical, &rotation,
                      &bearing, halign);
    if (error) continue;

    bb.xMin = ft_min(bb.xMin, pen.x + bearing.x);
    bb.xMax = ft_max(bb.xMax, pen.x + bearing.x + 64*face->glyph->bitmap.width);
    bb.yMin = ft_min(bb.yMin, pen.y + bearing.y - 64*face->glyph->bitmap.rows);
    bb.yMax = ft_max(bb.yMax, pen.y + bearing.y);

    if (direction == GKS_K_TEXT_PATH_DOWN) {
      pen.x -= face->glyph->advance.x + spacing.x;
      pen.y -= face->glyph->advance.y + spacing.y;
    } else {
      pen.x += face->glyph->advance.x + spacing.x;
      pen.y += face->glyph->advance.y + spacing.y;
    }
  }
  *width  = (int)((bb.xMax - bb.xMin) / 64);
  *height = (int)((bb.yMax - bb.yMin) / 64);
  if (bb.xMax <= bb.xMin || bb.yMax <= bb.yMin) {
    gks_perror("invalid bitmap size");
    free(unicode_string);
    return NULL;
  }
  size = *width * *height;
  mono_bitmap = (FT_Byte *) safe_realloc(mono_bitmap, size);
  memset(mono_bitmap, 0, size);

  pen.x = 0;
  pen.y = 0;
  previous = 0;

  for (i = 0; i < num_glyphs; i++) {
    bearing.x = bearing.y = 0;
    codepoint = unicode_string[direction == GKS_K_TEXT_PATH_LEFT ?
                               (num_glyphs - 1 - i) : i];
    error = set_glyph(face, codepoint, &previous, &pen, vertical, &rotation,
                      &bearing, halign);
    if (error) continue;

    pos_x = ( pen.x + bearing.x - bb.xMin) / 64;
    pos_y = (-pen.y - bearing.y + bb.yMax) / 64;
    ftbitmap = face->glyph->bitmap;
    for (j = 0; j < (unsigned int) ftbitmap.rows; j++) {
      for (k = 0; k < (unsigned int) ftbitmap.width; k++) {
        dx = k + pos_x;
        dy = j + pos_y;
        value = mono_bitmap[dy * *width + dx];
        value += ftbitmap.buffer[j * ftbitmap.pitch + k];
        if (value > 255) {
          value = 255;
        }
        mono_bitmap[dy * *width + dx] = value;
      }
    }

    if (direction == GKS_K_TEXT_PATH_DOWN) {
      pen.x -= face->glyph->advance.x + spacing.x;
      pen.y -= face->glyph->advance.y + spacing.y;
    } else {
      pen.x += face->glyph->advance.x + spacing.x;
      pen.y += face->glyph->advance.y + spacing.y;
    }
  }
  free(unicode_string);

  /* Alignment */
  if (direction == GKS_K_TEXT_PATH_DOWN) {
    pen.x += spacing.x;
    pen.y += spacing.y;
  } else {
    pen.x -= spacing.x;
    pen.y -= spacing.y;
  }

  align.x = align.y = 0;
  if (valign != GKS_K_TEXT_VALIGN_BASE) {
    align.y = nint(gkss->chh * windowwidth * 64);
    FT_Vector_Transform(&align, &rotation);
    if (valign == GKS_K_TEXT_VALIGN_HALF) {
      align.x = nint(0.5 * align.x);
      align.y = nint(0.5 * align.y);
    } else if (valign == GKS_K_TEXT_VALIGN_TOP) {
      align.x = nint(1.2 * align.x);
      align.y = nint(1.2 * align.y);
    } else if (valign == GKS_K_TEXT_VALIGN_BOTTOM) {
      align.x = nint(-0.2 * align.x);
      align.y = nint(-0.2 * align.y);
    }
  }

  if (!vertical && halign != GKS_K_TEXT_HALIGN_LEFT) {
    FT_Vector right;
    right.x = face->glyph->metrics.width + face->glyph->metrics.horiBearingX;
    right.y = 0;
    if (right.x != 0) {
      FT_Vector_Transform(&right, &rotation);
    }
    pen.x += right.x - face->glyph->advance.x;
    pen.y += right.y - face->glyph->advance.y;
    if (halign == GKS_K_TEXT_HALIGN_CENTER) {
      align.x += pen.x / 2;
      align.y += pen.y / 2;
    } else if (halign == GKS_K_TEXT_HALIGN_RIGHT) {
      align.x += pen.x;
      align.y += pen.y;
    }
  }

  *x += (bb.xMin - align.x) / 64;
  *y += (bb.yMin - align.y) / 64;
  return mono_bitmap;
}