/* p_text.c
 * Copyright (C) 1997-98 Thomas Merz. All rights reserved.
 *
 * PDFlib text routines
 */

#include <stdio.h>

#include "p_intern.h"

/* Auxiliary routines */

void
pdf_begin_text(PDF *p)
{
    if (p->contents == c_text)
	return;

    p->res.procset	|= Text;
    p->contents		= c_text;

    (void) fputs( "BT\n", p->fp);
}

void
pdf_end_text(PDF *p)
{
    if (p->contents != c_text)
	return;

    p->contents	= c_stream;

    (void) fputs("ET\n", p->fp);
}

/* This function doesn't work with null characters! */

void
pdf_quote_string(PDF *p, char *string)
{
    unsigned char *s;

    fputc('(', p->fp);

    for (s = (unsigned char *) string; *s; s++) {
		/* expand tabs */
		if (*s == '\t') {
			fputs("    ", p->fp);
		} else
		if (p->info->binary_mode == false && (*s < 0x20 || *s > 0x7f)) {
			fprintf(p->fp, "\\%03o", *s);
		} else {
			if (*s == '(' || *s == ')' || *s == '\\')
			fputc('\\', p->fp);
			fputc(*s, p->fp);
		}
    }
    fputc(')', p->fp);
}

void
pdf_put_fonts(PDF *p)
{
    pdf_item	*item;
    int		index = 0;

    /* output pending font objects */
    for (item = p->res.font; item != (pdf_item *) NULL; item = item->next) 
    {
	pdf_put_t1font(p, item->basename, item->obj_id, index++, true);
    }
}

/* Section 8.7.3 Text state operators */

void
PDF_set_font(PDF *p, char *fontname, float fontsize, PDF_encoding enc)
{
    pdf_item	*item;

    item = pdf_add_res_font(p, fontname);

    pdf_begin_text(p);
    (void) fprintf(p->fp, "%s %s Tf\n", item->name, pdf_float(fontsize));
    PDF_set_leading(p, fontsize);

    switch (p->current_font->encoding) {
	case builtin:
	case winansi:
	case macroman:
	    break;

	default:
	    pdf_error(p, PDF_WARN, "Bogus encoding for font %s", fontname);
	    enc = builtin;
    }

    pdf_read_afm(p, fontname, enc);
    p->current_font->encoding = enc;
    p->current_font->size = fontsize;
}

void
PDF_set_leading(PDF *p, float l)
{
    pdf_begin_text(p);
    (void) fprintf(p->fp, "%s TL\n", pdf_float(l));
}

void
PDF_set_text_rendering(PDF *p, byte mode)
{
#define LAST_MODE	7
	if (mode > LAST_MODE) {
		pdf_error(p, PDF_WARN, "Bogus text rendering mode");
		return;
	}
		
    pdf_begin_text(p);
    (void) fprintf(p->fp, "%d Tr\n", mode);
#undef LAST_MODE
}

void
PDF_set_text_rise(PDF *p, float rise)
{
    pdf_begin_text(p);
    (void) fprintf(p->fp, "%s Ts\n", pdf_float(rise));
}

void
PDF_set_horiz_scaling(PDF *p, float scale)
{
    pdf_begin_text(p);
    (void) fprintf(p->fp, "%s Tz\n", pdf_float(scale));
}

/* Section 8.7.4 Text positioning operators */

void
PDF_set_text_matrix(PDF *p, PDF_matrix m)
{
    pdf_begin_text(p);
    (void) fprintf(p->fp,"%s %s %s %s %s %s Tm\n",
		  pdf_float(m.a), pdf_float(m.b), pdf_float(m.c),
		  pdf_float(m.d), pdf_float(m.e), pdf_float(m.f));
}

void
PDF_set_text_pos(PDF *p, float x, float y)
{
    pdf_begin_text(p);
    (void) fprintf(p->fp,"1 0 0 1 %s %s Tm\n", pdf_float(x), pdf_float(y));
}

/* Section 8.7.6 Text string operators */

void
PDF_show(PDF *p, char *text)
{
    pdf_begin_text(p);
    pdf_quote_string(p, text);
    (void) fputs("Tj\n", p->fp);
}

void
PDF_continue_text(PDF *p, char *text)
{
    pdf_begin_text(p);
    pdf_quote_string(p, text);
    (void) fputs("'\n", p->fp);
}

void
PDF_show_xy(PDF *p, char *text, float x, float y)
{
    pdf_begin_text(p);

    (void) fprintf(p->fp,"1 0 0 1 %s %s Tm\n", pdf_float(x), pdf_float(y));
    pdf_quote_string(p, text);
    (void) fputs("Tj\n", p->fp);
}

/* character spacing for justified lines */
void
PDF_set_char_spacing(PDF *p, float spacing)
{
    pdf_begin_text(p);
    (void) fprintf(p->fp,"%s Tc\n", pdf_float(spacing));
}

/* word spacing for justified lines */
void
PDF_set_word_spacing(PDF *p, float spacing)
{
    pdf_begin_text(p);
    (void) fprintf(p->fp,"%s Tw\n", pdf_float(spacing));
}
